C#PrintWindow - 经过多次迭代后,GetHdc崩溃

时间:2017-08-18 11:12:21

标签: c# bitmap screenshot argumentexception

这里的第一个问题,如果我能改进这个帖子,请随时告诉我:) 我目前正在C#中使用" PrintWindow"编写一个相当简单的.Net应用程序。来自" user32.dll"为了获取其他应用程序的屏幕截图,即使它在另一个窗口后面运行。

我的目标是让我的程序无休止地运行/很长一段时间,但我遇到了我无法解决的问题。

大约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吗?我宁愿坚持下去,因为这是迄今为止我发现的唯一一种捕捉背景窗口的方式。

1 个答案:

答案 0 :(得分:0)

好的,好的! 我发现了这个问题,希望这有助于将来的某些人。在GDIView的帮助下,我发现我的应用程序泄露了“DC”对象。如果创建了超过10.000个对象(我应该首先查找它),GDI拒绝工作。 之后未被删除的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对象,因此不再崩溃。