捕获新创建的桌面无法使用 win api 的屏幕截图

问题描述 投票:0回答:1
using System.Diagnostics;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Windows.Media.Imaging;

internal class Program
{
    private static void Main(string[] args)
    {
        ProcessStartInfo ps = new ProcessStartInfo()
        {
            UseShellExecute = false,
            RedirectStandardInput = true,
            FileName = "notepad.exe"
        };

        IntPtr desktopHandle = CreateDesktopExW("abcdesktop", null, IntPtr.Zero, 0, access, IntPtr.Zero, 1000, IntPtr.Zero);

        if(desktopHandle == IntPtr.Zero)
        {
            MessageBox.Show(GetLastError().ToString());
            return;
        }

        if (!SetThreadDesktop(desktopHandle))
        {
            MessageBox.Show(GetLastError().ToString());
            return;
        }

        using (Process notepad = Process.Start(ps))
        {
            notepad.StandardInput.Write("Hi");
            TakeScreenShot();
        }

        Task.Delay(10000).Wait();

        if (!CloseDesktop(desktopHandle))
        {
            MessageBox.Show(GetLastError().ToString());
            return;
        }

        if (!SetThreadDesktop(IntPtr.Zero))
        {
            MessageBox.Show(GetLastError().ToString());
            return;
        }

        MessageBox.Show("Test succeeded!");
    }

    static void TakeScreenShot()
    {
        // Get the device context of the entire screen
        IntPtr hScreenDC = GetDC(IntPtr.Zero);

        // Define the width and height of the screenshot
        int width = Screen.PrimaryScreen.Bounds.Width;
        int height = Screen.PrimaryScreen.Bounds.Height;

        // Create a compatible bitmap
        using (Bitmap bitmap = new Bitmap(width, height))
        {
            // Create a Graphics object associated with the screen device context
            using (Graphics graphics = Graphics.FromImage(bitmap))
            {
                // Capture the screen
                graphics.CopyFromScreen(0, 0, 0, 0, new Size(width, height));
            }

            // Save the captured image
            bitmap.Save(Path.Combine(Directory.GetCurrentDirectory(), "ScreenShot.png"), ImageFormat.Png);
        }

        // Release the device context
        ReleaseDC(IntPtr.Zero, hScreenDC);
    }

    #region dllImports

    //https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createdesktopexw
    [DllImport("user32.dll")]
    static extern IntPtr CreateDesktopExW(
        [MarshalAs(UnmanagedType.LPWStr)] string lpszDesktop,
        [MarshalAs(UnmanagedType.LPWStr)] string lpszDevice,
        IntPtr pDevmode,
        UInt32 dwFlags,
        UInt32 dwDesiredAccess,
        IntPtr lpsa,
        UInt32 ulHeapSize,
        IntPtr pvoid
        );

    //https://learn.microsoft.com/en-us/windows/win32/winstation/desktop-security-and-access-rights
    static UInt32 access = (UInt32)(0x0004L | 0x0002L | 0x0040L | 0x0008L | 0x0020L | 0x0010L | 0x0001L | 0x0100L | 0x0080L);

    [DllImport("user32.dll")]
    static extern bool CloseDesktop(IntPtr hDesktop);

    [DllImport("kernel32.dll")]
    public static extern uint GetLastError();

    //https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setthreaddesktop
    [DllImport("user32.dll")]
    static extern bool SetThreadDesktop(IntPtr hDesktop);


    [DllImport("user32.dll")]
    public static extern IntPtr GetDC(IntPtr hWnd);

    [DllImport("user32.dll")]
    public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);

    [DllImport("user32.dll")]
    static extern bool SwitchDesktop(IntPtr hDesktop);

    #endregion
}

我检查了每个返回,似乎没有任何失败,除了屏幕截图方法运行时,它似乎失败了,因为我已经使调用进程在新创建的桌面线程上运行。我在

g.CopyFromScreen
序列上得到“无效句柄”。

我还尝试了 SwitchDesktop,似乎如果我切换桌面,我的屏幕就会返回空白。

为什么会这样?

c# winapi dllimport user32
1个回答
0
投票

这是个好问题!我也很想知道如何修复这个错误,因为我也遇到了同样的错误。

© www.soinside.com 2019 - 2024. All rights reserved.