using System;
using System.Threading;
using System.Collections;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Collections.Specialized;
using System.IO;
namespace Desktop_withExplorer
{
public class Desktop : IDisposable, ICloneable
{
#region Imports
[DllImport("kernel32.dll")]
private static extern int GetThreadId(IntPtr thread);
[DllImport("kernel32.dll")]
private static extern int GetProcessId(IntPtr process);
[DllImport("user32.dll")]
private static extern IntPtr CreateDesktop(string lpszDesktop, IntPtr lpszDevice, IntPtr pDevmode, int dwFlags, long dwDesiredAccess, IntPtr lpsa);
[DllImport("user32.dll")]
private static extern bool CloseDesktop(IntPtr hDesktop);
[DllImport("user32.dll")]
private static extern IntPtr OpenDesktop(string lpszDesktop, int dwFlags, bool fInherit, long dwDesiredAccess);
[DllImport("user32.dll")]
private static extern IntPtr OpenInputDesktop(int dwFlags, bool fInherit, long dwDesiredAccess);
[DllImport("user32.dll")]
private static extern bool SwitchDesktop(IntPtr hDesktop);
[DllImport("user32.dll")]
private static extern bool EnumDesktops(IntPtr hwinsta, EnumDesktopProc lpEnumFunc, IntPtr lParam);
[DllImport("user32.dll")]
private static extern IntPtr GetProcessWindowStation();
[DllImport("user32.dll")]
private static extern bool EnumDesktopWindows(IntPtr hDesktop, EnumDesktopWindowsProc lpfn, IntPtr lParam);
[DllImport("user32.dll")]
private static extern bool SetThreadDesktop(IntPtr hDesktop);
[DllImport("user32.dll")]
private static extern IntPtr GetThreadDesktop(int dwThreadId);
[DllImport("user32.dll")]
private static extern bool GetUserObjectInformation(IntPtr hObj, int nIndex, IntPtr pvInfo, int nLength, ref int lpnLengthNeeded);
[DllImport("kernel32.dll")]
private static extern bool CreateProcess(
string lpApplicationName,
string lpCommandLine,
IntPtr lpProcessAttributes,
IntPtr lpThreadAttributes,
bool bInheritHandles,
int dwCreationFlags,
IntPtr lpEnvironment,
string lpCurrentDirectory,
ref STARTUPINFO lpStartupInfo,
ref PROCESS_INFORMATION lpProcessInformation
);
[DllImport("user32.dll")]
private static extern int GetWindowText(IntPtr hWnd, IntPtr lpString, int nMaxCount);
private delegate bool EnumDesktopProc(string lpszDesktop, IntPtr lParam);
private delegate bool EnumDesktopWindowsProc(IntPtr desktopHandle, IntPtr lParam);
[StructLayout(LayoutKind.Sequential)]
private struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public int dwProcessId;
public int dwThreadId;
}
[StructLayout(LayoutKind.Sequential)]
private struct STARTUPINFO
{
public int cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public int dwX;
public int dwY;
public int dwXSize;
public int dwYSize;
public int dwXCountChars;
public int dwYCountChars;
public int dwFillAttribute;
public int dwFlags;
public short wShowWindow;
public short cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
#endregion
#region Constants
public const int MaxWindowNameLength = 100;
private const short SW_HIDE = 0;
private const short SW_NORMAL = 1;
private const int STARTF_USESTDHANDLES = 0x00000100;
private const int STARTF_USESHOWWINDOW = 0x00000001;
private const int UOI_NAME = 2;
private const int STARTF_USEPOSITION = 0x00000004;
private const int NORMAL_PRIORITY_CLASS = 0x00000020;
private const long DESKTOP_CREATEWINDOW = 0x0002L;
private const long DESKTOP_ENUMERATE = 0x0040L;
private const long DESKTOP_WRITEOBJECTS = 0x0080L;
private const long DESKTOP_SWITCHDESKTOP = 0x0100L;
private const long DESKTOP_CREATEMENU = 0x0004L;
private const long DESKTOP_HOOKCONTROL = 0x0008L;
private const long DESKTOP_READOBJECTS = 0x0001L;
private const long DESKTOP_JOURNALRECORD = 0x0010L;
private const long DESKTOP_JOURNALPLAYBACK = 0x0020L;
private const long AccessRights = DESKTOP_JOURNALRECORD | DESKTOP_JOURNALPLAYBACK | DESKTOP_CREATEWINDOW | DESKTOP_ENUMERATE | DESKTOP_WRITEOBJECTS | DESKTOP_SWITCHDESKTOP | DESKTOP_CREATEMENU | DESKTOP_HOOKCONTROL | DESKTOP_READOBJECTS;
#endregion
#region Structures
public struct Window
{
#region Private Variables
private IntPtr m_handle;
private string m_text;
#endregion
#region Public Properties
public IntPtr Handle
{
get
{
return m_handle;
}
}
public string Text
{
get
{
return m_text;
}
}
#endregion
#region Construction
public Window(IntPtr handle, string text)
{
m_handle = handle;
m_text = text;
}
#endregion
}
public class WindowCollection : CollectionBase
{
#region Public Properties
public Window this[int index]
{
get
{
return (Window)List[index];
}
}
#endregion
#region Methods
public void Add(Window wnd)
{
List.Add(wnd);
}
#endregion
}
#endregion
#region Private Variables
private IntPtr m_desktop;
private string m_desktopName;
private static StringCollection m_sc;
private ArrayList m_windows;
private bool m_disposed;
#endregion
#region Public Properties
public bool IsOpen
{
get
{
return (m_desktop != IntPtr.Zero);
}
}
public string DesktopName
{
get
{
return m_desktopName;
}
}
public IntPtr DesktopHandle
{
get
{
return m_desktop;
}
}
public static readonly Desktop Default = Desktop.OpenDefaultDesktop();
public static readonly Desktop Input = Desktop.OpenInputDesktop();
#endregion
#region Construction/Destruction
public Desktop()
{
m_desktop = IntPtr.Zero;
m_desktopName = String.Empty;
m_windows = new ArrayList();
m_disposed = false;
}
private Desktop(IntPtr desktop)
{
m_desktop = desktop;
m_desktopName = Desktop.GetDesktopName(desktop);
m_windows = new ArrayList();
m_disposed = false;
}
~Desktop()
{
Close();
}
#endregion
#region Methods
public bool Create(string name)
{
CheckDisposed();
if (m_desktop != IntPtr.Zero)
{
if (!Close()) return false;
}
if (Desktop.Exists(name))
{
return Open(name);
}
m_desktop = CreateDesktop(name, IntPtr.Zero, IntPtr.Zero, 0, AccessRights, IntPtr.Zero);
m_desktopName = name;
if (m_desktop == IntPtr.Zero) return false;
return true;
}
public bool Close()
{
CheckDisposed();
if (m_desktop != IntPtr.Zero)
{
bool result = CloseDesktop(m_desktop);
if (result)
{
m_desktop = IntPtr.Zero;
m_desktopName = String.Empty;
}
return result;
}
return true;
}
public bool Open(string name)
{
CheckDisposed();
if (m_desktop != IntPtr.Zero)
{
if (!Close()) return false;
}
m_desktop = OpenDesktop(name, 0, true, AccessRights);
if (m_desktop == IntPtr.Zero) return false;
m_desktopName = name;
return true;
}
public bool OpenInput()
{
CheckDisposed();
if (m_desktop != IntPtr.Zero)
{
if (!Close()) return false;
}
m_desktop = OpenInputDesktop(0, true, AccessRights);
if (m_desktop == IntPtr.Zero) return false;
m_desktopName = Desktop.GetDesktopName(m_desktop);
return true;
}
public bool Show()
{
CheckDisposed();
if (m_desktop == IntPtr.Zero) return false;
bool result = SwitchDesktop(m_desktop);
return result;
}
public WindowCollection GetWindows()
{
CheckDisposed();
if (!IsOpen) return null;
m_windows.Clear();
WindowCollection windows = new WindowCollection();
bool result = EnumDesktopWindows(m_desktop, new EnumDesktopWindowsProc(DesktopWindowsProc), IntPtr.Zero);
if (!result) return null;
windows = new WindowCollection();
IntPtr ptr = Marshal.AllocHGlobal(MaxWindowNameLength);
foreach (IntPtr wnd in m_windows)
{
GetWindowText(wnd, ptr, MaxWindowNameLength);
windows.Add(new Window(wnd, Marshal.PtrToStringAnsi(ptr)));
}
Marshal.FreeHGlobal(ptr);
return windows;
}
private bool DesktopWindowsProc(IntPtr wndHandle, IntPtr lParam)
{
m_windows.Add(wndHandle);
return true;
}
public Process CreateProcess(string path)
{
CheckDisposed();
if (!IsOpen) return null;
STARTUPINFO si = new STARTUPINFO();
si.cb = Marshal.SizeOf(si);
si.lpDesktop = m_desktopName;
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
bool result = CreateProcess(null, path, IntPtr.Zero, IntPtr.Zero, true, NORMAL_PRIORITY_CLASS, IntPtr.Zero, null, ref si, ref pi);
if (!result) return null;
return Process.GetProcessById(pi.dwProcessId);
}
public void Prepare()
{
CheckDisposed();
if (IsOpen)
{
CreateProcess("explorer.exe");
}
}
#endregion
#region Static Methods
public static string[] GetDesktops()
{
IntPtr windowStation = GetProcessWindowStation();
if (windowStation == IntPtr.Zero) return new string[0];
string[] desktops;
lock (m_sc = new StringCollection())
{
bool result = EnumDesktops(windowStation, new EnumDesktopProc(DesktopProc), IntPtr.Zero);
if (!result) return new string[0];
desktops = new string[m_sc.Count];
for (int i = 0; i < desktops.Length; i++) desktops[i] = m_sc[i];
}
return desktops;
}
private static bool DesktopProc(string lpszDesktop, IntPtr lParam)
{
m_sc.Add(lpszDesktop);
return true;
}
public static bool Show(string name)
{
bool result = false;
using (Desktop d = new Desktop())
{
result = d.Open(name);
if (!result) return false;
result = d.Show();
}
return result;
}
public static Desktop GetCurrent()
{
return new Desktop(GetThreadDesktop(AppDomain.GetCurrentThreadId()));
}
public static bool SetCurrent(Desktop desktop)
{
if (!desktop.IsOpen) return false;
return SetThreadDesktop(desktop.DesktopHandle);
}
public static Desktop OpenDesktop(string name)
{
Desktop desktop = new Desktop();
bool result = desktop.Open(name);
if (!result) return null;
return desktop;
}
public static Desktop OpenInputDesktop()
{
Desktop desktop = new Desktop();
bool result = desktop.OpenInput();
if (!result) return null;
return desktop;
}
public static Desktop OpenDefaultDesktop()
{
return Desktop.OpenDesktop("Default");
}
public static Desktop CreateDesktop(string name)
{
Desktop desktop = new Desktop();
bool result = desktop.Create(name);
if (!result) return null;
return desktop;
}
public static string GetDesktopName(Desktop desktop)
{
if (desktop.IsOpen) return null;
return GetDesktopName(desktop.DesktopHandle);
}
public static string GetDesktopName(IntPtr desktopHandle)
{
if (desktopHandle == IntPtr.Zero) return null;
int needed = 0;
string name = String.Empty;
GetUserObjectInformation(desktopHandle, UOI_NAME, IntPtr.Zero, 0, ref needed);
IntPtr ptr = Marshal.AllocHGlobal(needed);
bool result = GetUserObjectInformation(desktopHandle, UOI_NAME, ptr, needed, ref needed);
name = Marshal.PtrToStringAnsi(ptr);
Marshal.FreeHGlobal(ptr);
if (!result) return null;
return name;
}
public static bool Exists(string name)
{
return Desktop.Exists(name, false);
}
public static bool Exists(string name, bool caseInsensitive)
{
string[] desktops = Desktop.GetDesktops();
foreach (string desktop in desktops)
{
if (caseInsensitive)
{
if (desktop.ToLower() == name.ToLower()) return true;
}
else
{
if (desktop == name) return true;
}
}
return false;
}
public static Process CreateProcess(string path, string desktop)
{
if (!Desktop.Exists(desktop)) return null;
Desktop d = Desktop.OpenDesktop(desktop);
return d.CreateProcess(path);
}
public static Process[] GetInputProcesses()
{
Process[] processes = Process.GetProcesses();
ArrayList m_procs = new ArrayList();
string currentDesktop = GetDesktopName(Desktop.Input.DesktopHandle);
foreach (Process process in processes)
{
foreach (ProcessThread pt in process.Threads)
{
if (GetDesktopName(GetThreadDesktop(pt.Id)) == currentDesktop)
{
m_procs.Add(process);
break;
}
}
}
Process[] procs = new Process[m_procs.Count];
for (int i = 0; i < procs.Length; i++) procs[i] = (Process)m_procs[i];
return procs;
}
#endregion
#region IDisposable
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public virtual void Dispose(bool disposing)
{
if (!m_disposed)
{
Close();
}
m_disposed = true;
}
private void CheckDisposed()
{
if (m_disposed)
{
throw new ObjectDisposedException("");
}
}
#endregion
#region ICloneable
public object Clone()
{
CheckDisposed();
Desktop desktop = new Desktop();
if (IsOpen) desktop.Open(m_desktopName);
return desktop;
}
#endregion
#region Overrides
public override string ToString()
{
return m_desktopName;
}
#endregion
public static void Log(string logMessage, TextWriter w)
{
w.WriteLine(" {0}", logMessage);
}
static void Main(string[] args)
{
Desktop desktop_normal= OpenInputDesktop();
Desktop desktop_new = CreateDesktop("myDesktop");
desktop_new.Show();
Thread.Sleep(3000);
Process p = desktop_new.CreateProcess("calc.exe");
Thread.Sleep(3000);
p.Kill();
Thread.Sleep(3000);
desktop_normal.Show();
Thread.Sleep(3000);
desktop_new.Dispose();
Thread.Sleep(3000);
}
}
}