2017-08-18 7 views
0

ここで最初の質問ですが、この投稿を改善することができれば教えてください:) 私は現在、C#で "PrintWindow"を使用するかなり簡単な.Netアプリケーションをプログラミングしています別のウィンドウの背後で実行されていても、他のアプリケーションのスクリーンショットを撮るために "user32.dll"C#PrintWindow - 多くの繰り返しの後にGetHdcがクラッシュする

プログラムを無限に/長期間実行することを目指していますが、解決できない問題が発生しました。

約10.000スクリーンショットで私のアプリケーションは常にクラッシュします。ここではそれに付属している私はバグを再現するには、コンソールアプリケーションで使用されるコードとエラーです:

class Program 
{ 
    /* Get Image even if Process is running behind another window ******************* */ 
    [DllImport("user32.dll")] 
    public static extern bool PrintWindow(IntPtr hwnd, IntPtr hdcBlt, uint nFlags); 
    [DllImport("user32.dll")] 
    public static extern IntPtr GetWindowDC(IntPtr hWnd); 
    /* ****************************************************************************** */ 

    static void Main(string[] args) 
    { 
     Process process = ReturnProcess(); 
     int counter = 0; 

     Console.WriteLine(RotMG.ToString()); 

     while (true) 
     { 
      Bitmap bmpTest = CaptureWindow(RotMG.MainWindowHandle); 
      bmpTest.Dispose(); 

      counter++; 
      Console.WriteLine(counter.ToString()); 
     } 
    } 

    private static Process ReturnProcess() 
    { 
     Process[] processes = Process.GetProcessesByName("desiredProcess"); 
     return processes[0]; 
    } 

    public static Bitmap CaptureWindow(IntPtr hWnd) 
    { 
     Rectangle rctForm = System.Drawing.Rectangle.Empty; 
     using (Graphics grfx = Graphics.FromHdc(GetWindowDC(hWnd))) 
     { 
      rctForm = Rectangle.Round(grfx.VisibleClipBounds); 
     } 
     Bitmap pImage = new Bitmap(rctForm.Width, rctForm.Height); 
     Graphics graphics = Graphics.FromImage(pImage); 
     IntPtr hDC = graphics.GetHdc(); 
     try 
     { 
      PrintWindow(hWnd, hDC, (uint)0); 
     } 
     finally 
     { 
      graphics.ReleaseHdc(hDC); 
      graphics.Dispose(); 
     } 
     return pImage; 
    } 
} 

のIntPtrたhDC = graphics.GetHdcは(); System.ArgumentException:パラメータが無効です

私の実際のアプリケーションでは、明らかに高速の画像をキャプチャすることは想定されていませんが、数時間後に同じエラーが発生します。

私はここから重要なコードをコーディング:https://codereview.stackexchange.com/questions/29364/capturing-and-taking-a-screenshot-of-a-window-in-a-loop

が、私は私のプロジェクトのためPrintWindowを捨てなければなりませんか?私はそれがバックグラウンドにあるウィンドウをキャプチャするために今まで私が見つけた唯一の方法であるので、むしろそれに固執するでしょう。

答えて

0

大丈夫です! 私はこの問題を発見しました。うまくいけば、これは将来誰かに役立ちます。 GDIViewの助けを借りて、私のアプリケーションが "DC"オブジェクトを漏らしていることがわかりました。 GDIは10.000個以上のオブジェクトが作成されている場合は作業を拒否します(最初に調べたはずです)。 その後次の行に隠れ削除されていないDC:あなたは次の参照を追加した場合

using (Graphics grfx = Graphics.FromHdc(GetWindowDC(hWnd))) 

[DllImport("gdi32.dll")] 
static extern IntPtr DeleteDC(IntPtr hDc); 

をして、このようなコード変更:

IntPtr WindowDC = GetWindowDC(hWnd); 
using (Graphics grfx = Graphics.FromHdc(WindowDC)) 
{ 
    rctForm = Rectangle.Round(grfx.VisibleClipBounds); 
} 
DeleteDC(WindowDC); 

をその後、DCオブジェクトは正しく削除され、プログラムはもはや10.000個のDCオブジェクトを超えなくなり、もはやクラッシュしなくなります。

関連する問題