Hello, I am running Windows XP, SP2. .Net framework 3.5, Visual Studio 2008. C# is the language of coding, but will do VB if needed. I am trying to move a running application\process from one desktop to another virtual desktop. Both desktops are running on the same windows station. The application is a windows form application. I want to start this application, create a new virtual
desktop and select a radio button that switches me to the newly created desktop. All of these work fine, however, I want to transfer the current running windows form over to the newly created desktop. I can start new processes on the new desktop easily, but
I need to move\transfer my running application to the newly created desktop. I have downloaded Dexpot, which is a virtual desktop program. This application allows me to move a program over to another desktop no problem. I want to emulate this program. I have even created a simple windows app that shows a messagebox when the app opens and closes. I then moved this app to another desktop using Dexpot and I didn't see any messageboxes pop up on any of the desktops...so I know that it isn't closing the
original app and then reopening it. Any ideas on how to do it...i have been drowning in the MSDN for the last 3 days. Thanks in advance, Wayne PS when the form switches to the other desktop. I start a timer that automatically switches back to the original desktop after 15 seconds. Before I did this, I was stuck in the other newly created desktop >:) I have posted the code below. I would be glad to zip the project and send it as well if needed. Thanks again. WindowDesktop Class using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics; using System.Runtime.InteropServices; using System.Text; namespace New_Desktop { public class WindowDesktop : IDisposable { #region DLLs [DllImport("user32.dll", EntryPoint = "CloseDesktop", CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CloseDesktop(IntPtr handle); [DllImport("user32.dll")] private static extern IntPtr CreateDesktop(string lpszDesktop, IntPtr lpszDevice, IntPtr pDevmode, int dwFlags, long dwDesiredAccess, IntPtr lpsa); [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 bool EnumDesktops(IntPtr hwinsta, EnumDesktopProc lpEnumFunc, IntPtr lParam); [DllImport("user32.dll")] private static extern bool EnumDesktopWindows(IntPtr hDesktop, EnumDesktopWindowsProc lpfn, IntPtr lParam); [DllImport("kernel32.dll")] public static extern int GetCurrentThreadId(); [DllImport("kernel32.dll")] public static extern int GetLastError(); [DllImport("user32.dll",SetLastError=true)] private static extern bool GetUserObjectInformation(IntPtr hObj, int nIndex, [Out] byte [] pvInfo, uint nLength, out uint lpnLengthNeeded); [DllImport("user32.dll")] private static extern IntPtr GetProcessWindowStation(); [DllImport("user32.dll")] public static extern IntPtr GetThreadDesktop(int dwThreadId); [DllImport("user32.dll")] private static extern IntPtr OpenDesktop(string lpszDesktop, int dwFlags, bool fInherit, int dwDesiredAccess); [DllImport("user32.dll")] internal static extern IntPtr OpenInputDesktop(int dwFlags, bool fInherit, int dwDesiredAccess); [DllImport("User32", CharSet = CharSet.Auto, ExactSpelling = true)] internal static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndParent); [DllImport("User32.dll")] internal static extern bool SetProcessWindowStation(IntPtr hWinSta); [DllImport("user32.dll")] public static extern bool SetThreadDesktop(IntPtr hDesktop); [DllImport("user32.dll")] private static extern bool SwitchDesktop(IntPtr hDesktop); #endregion #region Enumerator [Flags] internal enum DESKTOP_ACCESS_MASK : uint { DESKTOP_NONE = 0, DESKTOP_READOBJECTS = 0x0001, DESKTOP_CREATEWINDOW = 0x0002, DESKTOP_CREATEMENU = 0x0004, DESKTOP_HOOKCONTROL = 0x0008, DESKTOP_JOURNALRECORD = 0x0010, DESKTOP_JOURNALPLAYBACK = 0x0020, DESKTOP_ENUMERATE = 0x0040, DESKTOP_WRITEOBJECTS = 0x0080, DESKTOP_SWITCHDESKTOP = 0x0100, GENERIC_ALL = (DESKTOP_READOBJECTS | DESKTOP_CREATEWINDOW | DESKTOP_CREATEMENU | DESKTOP_HOOKCONTROL | DESKTOP_JOURNALRECORD | DESKTOP_JOURNALPLAYBACK | DESKTOP_ENUMERATE | DESKTOP_WRITEOBJECTS | DESKTOP_SWITCHDESKTOP), } #endregion # region Struct [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; } public struct PROCESS_INFORMATION { public long hProcess; public long hThread; public long dwProcessId; public long dwThreadId; } # endregion //End of Strcut #region Dispose public void Dispose() { SwitchToOrginal(); ((IDisposable)this).Dispose(); } /// <summary> /// Implemented Dispose method from IDisposable /// </summary> /// <param name="fDisposing"></param> protected virtual void Dispose(bool fDisposing) { if (fDisposing) { // free up resources //BspVariable1 = null; CloseDesktop(DesktopPtr); } } void IDisposable.Dispose() { Dispose(true); GC.SuppressFinalize(this); //Suppress garbage collector } #endregion #region Variables private const int UOI_FLAGS = 1; private const int UOI_NAME = 2; private const int UOI_TYPE = 3; private const int UOI_USER_SID = 4; private const int NORMAL_PRIORITY_CLASS = 0x00000020; IntPtr _hOrigDesktop; public IntPtr DesktopPtr; private string _sMyDesk; public string DesktopName { get { return (_sMyDesk); } set { _sMyDesk = value; } } private static StringCollection _sc; #endregion #region Constructors public WindowDesktop() { _sMyDesk = string.Empty; } public WindowDesktop(string sDesktopName) { _hOrigDesktop = GetCurrentDesktopPtr(); _sMyDesk = sDesktopName; DesktopPtr = CreateMyDesktop(); } #endregion # region Delegates private delegate bool EnumDesktopProc(string lpszDesktop, IntPtr lParam); private delegate bool EnumDesktopWindowsProc(IntPtr desktopHandle, IntPtr lParam); # endregion #region Methods public void show() { SetThreadDesktop(DesktopPtr); SwitchDesktop(DesktopPtr); } public void SwitchToOrginal() { SwitchDesktop(_hOrigDesktop); SetThreadDesktop(_hOrigDesktop); } private IntPtr CreateMyDesktop() { return CreateDesktop(_sMyDesk, IntPtr.Zero, IntPtr.Zero, 0, (long)DESKTOP_ACCESS_MASK.GENERIC_ALL, IntPtr.Zero); } public bool CreateProcess(string path, string desktopName) { // start the process. STARTUPINFO si = new STARTUPINFO(); si.lpDesktop = DesktopName; //int hCurrentThread = GetCurrentThreadId(); //IntPtr ptr = GetThreadDesktop(GetCurrentThreadId()); PROCESS_INFORMATION pi = new PROCESS_INFORMATION(); return CreateProcess(null, path, IntPtr.Zero, IntPtr.Zero, true, NORMAL_PRIORITY_CLASS, IntPtr.Zero, null, ref si, ref pi); } private static bool DesktopProc(string lpszDesktop, IntPtr lParam) { // add the desktop to the collection. _sc.Add(lpszDesktop); return true; } public IntPtr GetCurrentDesktopPtr() { return GetThreadDesktop(GetCurrentThreadId()); } public static StringCollection GetDesktops() { //define and initialize local variables IntPtr windowStation = GetProcessWindowStation(); //be sure the handle is valid if (windowStation == IntPtr.Zero) { return null; } // lock the object. thread safety and all. lock (_sc = new StringCollection()) { bool result = EnumDesktops(windowStation, new EnumDesktopProc(DesktopProc), IntPtr.Zero); //something went wrong. if (!result) { return null; } } return _sc; } public static StringCollection GetDesktopWindows(WindowDesktop wd) { //define and intialize local variables //be sure the handle is valid if (wd.DesktopPtr == IntPtr.Zero) { return null; } //lock the object thread safety and all lock (_sc = new StringCollection()) { bool result = EnumDesktopWindows(wd.DesktopPtr, new EnumDesktopWindowsProc(WindowProc), IntPtr.Zero); //an error ocurred if (!result) { return null; } } return _sc; } private static bool WindowProc(IntPtr desktopHandle, IntPtr lParam) { // add the desktop to the collection. _sc.Add(desktopHandle.ToString()); return true; } #endregion } } Form1 Class using System; using System.Collections.Generic; using System.Collections.Specialized; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace New_Desktop { public partial class Form1 : Form { WindowDesktop _d = null; IntPtr _ptrDefaultDesktopThread; WindowDesktop _wdDefault = new WindowDesktop("Default"); public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { //enable Timer tmrSwitchToDesktop.Interval = 15000; } private void btnClose_Click(object sender, EventArgs e) { try { //switches back to the default desktop //check to see if another desktop is created besides the original three: Logon, Default, and ??? if (_d != null) { //switch back to the default desktop _d.SwitchToOrginal(); } this.Close(); } //handle exceptions catch (Exception ex) { MessageBox.Show(string.Format("Error: {0}", ex.Message), "Form Closing Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void btnNewDesktop_Click(object sender, EventArgs e) { //Click Event for the New Desktop Button try { //make a new desktop _d = new WindowDesktop("myDesktop"); //get all the desktops for this Window Station StringCollection scDesktops = WindowDesktop.GetDesktops(); if (scDesktops != null && scDesktops.Count > 0) { for (int i = 0; i < scDesktops.Count; i++) { lstDesktops.Items.Add(scDesktops[i]); //get all the windows for the specified Desktop StringCollection scWindows = WindowDesktop.GetDesktopWindows(_d); if (scWindows != null && scWindows.Count > 0) { for (int j = 0; j < scWindows.Count; j++) { lstWindows.Items.Add(scWindows[j]); } } } } } //handle exceptions catch (Exception ex) { MessageBox.Show(string.Format("New Desktop Error: {0}", ex.Message), "New Desktop Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void tmrSwitchToDesktop_Tick(object sender, EventArgs e) { //switch back to default desktop if (_d != null) { //switch to default desktop _d.SwitchToOrginal(); } tmrSwitchToDesktop.Enabled = false; } private void radDefaultDesktop_CheckedChanged(object sender, EventArgs e) { try { if (_d != null) { _d.SwitchToOrginal(); } } //handle exceptions catch (Exception ex) { MessageBox.Show(string.Format("Switch Default Desktop Error: {0}", ex.Message), "Switch Default Desktop Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void radOtherDesktop_CheckedChanged(object sender, EventArgs e) { try { //make a new desktop if (_d == null) { _d = new WindowDesktop("myDesktop"); //create new process to run on the new desktop _d.CreateProcess(@"C:\WINDOWS\system32\cmd.exe",_d.DesktopName); } if (_d != null) { //move application back to original desktop // _d.CreateProcess(Application.ExecutablePath, "myDesktop"); _d.show(); } //enable timer tmrSwitchToDesktop.Enabled = true; } //handle exceptions catch (Exception ex) { MessageBox.Show(string.Format("Switch Other Desktop Error: {0}", ex.Message), "Switch Other Desktop Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { //destroy created desktop if (_d != null) { WindowDesktop.CloseDesktop(_d.DesktopPtr); } } } } |
Wayne Keadle