简体   繁体   English

如何在SetCompatibleTextRenderingDefault抛出InvalidOperationException时找出IWin32Window已创建的内容?

[英]How to find out what IWin32Window has been created when SetCompatibleTextRenderingDefault throws an InvalidOperationException?

After major refactoring, I run my WinForms application and it immediately crashes on Application.SetCompatibleTextRenderingDefault(false) . 在重大重构之后,我运行我的WinForms应用程序,它立即在Application.SetCompatibleTextRenderingDefault(false)崩溃。 In general, I understand what causes this: an IWin32Window has already been created. 一般来说,我明白是什么原因造成的:已经创建了IWin32Window

My problem is that for the life of me I can't figure out what such an object (or objects?) have been instantiated. 我的问题是,对于我的生活,我无法弄清楚这样的对象(或对象?)是如何被实例化的。 "Where" it was instantiated comes as a hopefully easier later question :) The line that throws is literally the second line of my code: if I step into my application (launching with F10 rather than F5, to be clear), it goes through the usual Application.EnableVisualStyles() without trouble, then it stops on the second line. “在哪里”它被实例化后来成为一个希望更容易的后续问题:)抛出的线实际上是我的代码的第二行:如果我进入我的应用程序(使用F10而不是F5启动,要清楚),它会通过通常的Application.EnableVisualStyles()没有问题,然后它停在第二行。

Is there a way to "inspect" created windows? 有没有办法“检查”创建的窗口? I'm looking for any solution, lines of code, debugger features, external programs, anything. 我正在寻找任何解决方案,代码行,调试器功能,外部程序,任何东西。 Thank you. 谢谢。

PLEASE NOTE that it's evident to me that I must have messed something up during my refactoring. 请注意 ,对我来说很明显,我在重构过程中一定搞砸了。 I couldn't compile for three days, so it's most likely that I created the bug myself. 我无法编译三天,所以我最有可能自己创建了这个bug。 I'm asking whether there's a way to confidently find the offending IWin32Window object. 我问是否有办法自信地找到有问题的IWin32Window对象。

UPDATE UPDATE

I've added the following code at the very beginning of Program.Main() : 我在Program.Main()的最开头添加了以下代码:

        var thisProcess = System.Diagnostics.Process.GetCurrentProcess();
        if (thisProcess != null)
        {
            var mainWindow = thisProcess.MainWindowHandle;
        }

Well, mainWindow is (a pointer to) zero. 好吧, mainWindow (指针)为零。

You have to look for code that runs before your Main() method runs. 您必须查找 Main()方法运行之前运行的代码。 Not a lot of candidates for such code, only the static constructor (aka type initializer) for the Program class qualifies. 对于这样的代码没有很多候选者,只有Program类的静态构造函数(aka type initializer)才有资格。 You'd know if you had written one, and could set a breakpoint on it, the less obvious case is a static variable in the Program class with a field initializer. 你知道你是否已经写了一个,并且可以设置断点,不太明显的情况是Program类中带有字段初始值设定项的static变量。 Not actually supported by the CLR, the C# compiler works around it by creating that static constructor itself and moving the code of the field initializer. CLR实际上不支持,C#编译器通过创建静态构造函数本身并移动字段初始化程序的代码来解决它。

If knowing that it is caused by a field initializer doesn't help then you can consider setting a breakpoint on the relevant framework method. 如果知道它是由字段初始化程序引起的,那么您可以考虑在相关框架方法上设置断点。 That does require some insight in how it works internally and there is no simple shortcut for that. 这需要对内部如何工作有一些了解,并没有简单的快捷方式。 Well, other than asking at SO :) 好吧,除了在SO询问:)

First use Tools > Options > Debugging > General and untick "Just My Code". 首先使用工具>选项>调试>常规,然后取消选中“仅我的代码”。 This isn't your code. 这不是你的代码。 Next use Debug > New Breakpoint > Function Breakpoint > type "System.Windows.Forms.NativeWindow.AddWindowToTable". 接下来使用Debug> New Breakpoint> Function Breakpoint>键入“System.Windows.Forms.NativeWindow.AddWindowToTable”。 That is the internal method that stores a reference to any created window, ensuring that the .NET class wrapper object does not get garbage collected too early. 这是存储对任何已创建窗口的引用的内部方法,确保.NET类包装器对象不会过早收集垃圾。

Press F5, the Call Stack window points at the evil-doer. 按F5,调用堆栈窗口指向邪恶的行为者。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM