【问题标题】:C# PrintWindow - GetHdc crashes after many iterationsC# PrintWindow - GetHdc 在多次迭代后崩溃
【发布时间】:2018-01-27 01:25:56
【问题描述】:

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

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

在大约 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 吗?我宁愿坚持使用它,因为它是迄今为止我发现的捕获背景窗口的唯一方法。

【问题讨论】:

    标签: c# bitmap screenshot argumentexception


    【解决方案1】:

    好吧! 我发现了问题,希望这对将来的某人有所帮助。在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对象,因此不再崩溃。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-08-07
      • 1970-01-01
      • 1970-01-01
      • 2012-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多