2017-05-05 36 views
3

重大重構後,我運行我的WinForms應用程序,它立即崩潰Application.SetCompatibleTextRenderingDefault(false)。一般來說,我明白是什麼原因造成的:已經創建了IWin32Window如何在SetCompatibleTextRenderingDefault引發InvalidOperationException時發現IWin32Window已經創建?

我的問題是,對於我的生活,我無法弄清楚這樣一個對象(或對象?)已被實例化。 「它在哪裏」實例化後來成爲一個希望更容易的問題:)拋出的這一行實際上是我的代碼的第二行:如果我進入我的應用程序(使用F10而不是F5啓動,清除),它會通過通常Application.EnableVisualStyles()沒有問題,然後停在第二行。

有沒有辦法「檢查」創建的窗口?我正在尋找任何解決方案,代碼行,調試器功能,外部程序,任何東西。謝謝。

請注意對我來說,在我的重構過程中,我一定弄錯了一些東西。我無法編譯三天,所以最有可能是我自己創建了錯誤。我問是否有辦法自信地找到有問題的對象IWin32Window

UPDATE

我在Program.Main()最開始添加如下代碼:

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

好,mainWindow是(指針)爲零。

+1

也許你可以使用'SetWinEventHook'方法來監聽'EVENT_OBJECT_CREATE'事件。也可能你可以處理Windows UI自動化事件。看看[這篇文章](http://stackoverflow.com/a/40285043/3110834)。 –

+1

沒有很多方法來解決這個問題。除了一個。我的水晶球告訴我你用一個場初始化器爲你的Program類增加了一個'static'變量。就像'public static Form1 MainWindow = new Form1();'首先執行,當你單步執行時,調試器不會顯示它。不要這樣做。 –

+0

@HansPassant哈,祝! :)我在大多數表單的構造函數中放置了斷點,但仍然沒有運氣。我只有兩個靜態變量(我知道,我不應該那樣做,但它是我沒有編寫的遺留代碼,並且仍然在積壓中進行重構),並且沒有一個顯然實例化任何形式。 – Simone

回答

3

您必須查找在您的Main()方法運行之前運行之前運行的代碼。對於這樣的代碼來說,並不是很多候選者,只有Program類的靜態構造函數(又名類型初始化器)纔有資格。你會知道,如果你寫了一個,並且可以在其上設置一個斷點,那麼不太明顯的例子是帶有字段初始值設定項的Program類中的static變量。 CLR實際上不支持C#編譯器,它通過創建靜態構造函數本身並移動字段初始值設定項的代碼來解決它。

如果知道它是由字段初始值設定項引起的沒有幫助,那麼可以考慮在相關框架方法上設置斷點。這確實需要一些關於它如何在內部工作的見解,並且沒有簡單的捷徑。那麼,除了要求在這麼:) :)

首先使用工具>選項>調試>常規,並取消「只是我的代碼」。這不是你的代碼。接下來使用Debug> New Breakpoint> Function Breakpoint>鍵入「System.Windows.Forms.NativeWindow.AddWindowToTable」。這是存儲對任何創建的窗口的引用的內部方法,以確保.NET類包裝器對象不會太早收集垃圾回收。

按F5,呼叫堆棧窗口指向邪惡者。

相關問題