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
}
I've checked every return and nothing seems to fail except when the screenshot method runs, it seems like it fails because I've made the calling process run on the newly created desktop thread. "Invalid handle" I get on the g.CopyFromScreen sequence.
I also experimented with SwitchDesktop, and it seems like if I switch desktop my screen returns blank.
Why could this be?