本文介绍了适用于.net2.0的桌面交换示例代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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);

        //
        // Imported winAPI functions.
        //
        [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
        /// <summary>
        /// Size of buffer used when retrieving window names.
        /// </summary>
        public const int MaxWindowNameLength = 100;

        //
        // winAPI constants.
        //
        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
        /// <summary>
        /// Stores window handles and titles.
        /// </summary>
        public struct Window
        {
            #region Private Variables
            private IntPtr m_handle;
            private string m_text;
            #endregion

            #region Public Properties
            /// <summary>
            /// Gets the window handle.
            /// </summary>
            public IntPtr Handle
            {
                get
                {
                    return m_handle;
                }
            }

            /// <summary>
            /// Gets teh window title.
            /// </summary>
            public string Text
            {
                get
                {
                    return m_text;
                }
            }
            #endregion

            #region Construction
            /// <summary>
            /// Creates a new window object.
            /// </summary>
            /// <param name="handle">Window handle.</param>
            /// <param name="text">Window title.</param>
            public Window(IntPtr handle, string text)
            {
                m_handle = handle;
                m_text = text;
            }
            #endregion
        }




        /// <summary>
        /// A collection for Window objects.
        /// </summary>
        public class WindowCollection : CollectionBase
        {
            #region Public Properties
            /// <summary>
            /// Gets a window from teh collection.
            /// </summary>
            public Window this[int index]
            {
                get
                {
                    return (Window)List[index];
                }
            }
            #endregion

            #region Methods
            /// <summary>
            /// Adds a window to the collection.
            /// </summary>
            /// <param name="wnd">Window to add.</param>
            public void Add(Window wnd)
            {
                // adds a widow to the collection.
                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
        /// <summary>
        /// Gets if a desktop is open.
        /// </summary>
        public bool IsOpen
        {
            get
            {
                return (m_desktop != IntPtr.Zero);
            }
        }

        /// <summary>
        /// Gets the name of the desktop, returns null if no desktop is open.
        /// </summary>
        public string DesktopName
        {
            get
            {
                return m_desktopName;
            }
        }

        /// <summary>
        /// Gets a handle to the desktop, IntPtr.Zero if no desktop open.
        /// </summary>
        public IntPtr DesktopHandle
        {
            get
            {
                return m_desktop;
            }
        }

        /// <summary>
        /// Opens the default desktop.
        /// </summary>
        public static readonly Desktop Default = Desktop.OpenDefaultDesktop();

        /// <summary>
        /// Opens the desktop the user if viewing.
        /// </summary>
        public static readonly Desktop Input = Desktop.OpenInputDesktop();
        #endregion

        #region Construction/Destruction
        /// <summary>
        /// Creates a new Desktop object.
        /// </summary>
        public Desktop()
        {
            // init variables.
            m_desktop = IntPtr.Zero;
            m_desktopName = String.Empty;
            m_windows = new ArrayList();
            m_disposed = false;
        }

        // constructor is private to prevent invalid handles being passed to it.
        private Desktop(IntPtr desktop)
        {
            // init variables.
            m_desktop = desktop;
            m_desktopName = Desktop.GetDesktopName(desktop);
            m_windows = new ArrayList();
            m_disposed = false;
        }

        ~Desktop()
        {
            // clean up, close the desktop.
            Close();
        }
        #endregion

        #region Methods
        /// <summary>
        /// Creates a new desktop.  If a handle is open, it will be closed.
        /// </summary>
        /// <param name="name">The name of the new desktop.  Must be unique, and is case sensitive.</param>
        /// <returns>True if desktop was successfully created, otherwise false.</returns>
        public bool Create(string name)
        {
            // make sure object isnt disposed.
            CheckDisposed();

            // close the open desktop.
            if (m_desktop != IntPtr.Zero)
            {
                // attempt to close the desktop.
                if (!Close()) return false;
            }

            // make sure desktop doesnt already exist.
            if (Desktop.Exists(name))
            {
                // it exists, so open it.
                return Open(name);
            }

            // attempt to create desktop.
            m_desktop = CreateDesktop(name, IntPtr.Zero, IntPtr.Zero, 0, AccessRights, IntPtr.Zero);

            m_desktopName = name;

            // something went wrong.
            if (m_desktop == IntPtr.Zero) return false;

            return true;
        }

        /// <summary>
        /// Closes the handle to a desktop.
        /// </summary>
        /// <returns>True if an open handle was successfully closed.</returns>
        public bool Close()
        {
            // make sure object isnt disposed.
            CheckDisposed();

            // check there is a desktop open.
            if (m_desktop != IntPtr.Zero)
            {
                // close the desktop.
                bool result = CloseDesktop(m_desktop);

                if (result)
                {
                    m_desktop = IntPtr.Zero;

                    m_desktopName = String.Empty;
                }

                return result;
            }

            // no desktop was open, so desktop is closed.
            return true;
        }

        /// <summary>
        /// Opens a desktop.
        /// </summary>
        /// <param name="name">The name of the desktop to open.</param>
        /// <returns>True if the desktop was successfully opened.</returns>
        public bool Open(string name)
        {
            // make sure object isnt disposed.
            CheckDisposed();

            // close the open desktop.
            if (m_desktop != IntPtr.Zero)
            {
                // attempt to close the desktop.
                if (!Close()) return false;
            }

            // open the desktop.
            m_desktop = OpenDesktop(name, 0, true, AccessRights);

            // something went wrong.
            if (m_desktop == IntPtr.Zero) return false;

            m_desktopName = name;

            return true;
        }

        /// <summary>
        /// Opens the current input desktop.
        /// </summary>
        /// <returns>True if the desktop was succesfully opened.</returns>
        public bool OpenInput()
        {
            // make sure object isnt disposed.
            CheckDisposed();

            // close the open desktop.
            if (m_desktop != IntPtr.Zero)
            {
                // attempt to close the desktop.
                if (!Close()) return false;
            }

            // open the desktop.
            m_desktop = OpenInputDesktop(0, true, AccessRights);

            // something went wrong.
            if (m_desktop == IntPtr.Zero) return false;

            // get the desktop name.
            m_desktopName = Desktop.GetDesktopName(m_desktop);

            return true;
        }

        /// <summary>
        /// Switches input to the currently opened desktop.
        /// </summary>
        /// <returns>True if desktops were successfully switched.</returns>
        public bool Show()
        {
            // make sure object isnt disposed.
            CheckDisposed();

            // make sure there is a desktop to open.
            if (m_desktop == IntPtr.Zero) return false;

            // attempt to switch desktops.
            bool result = SwitchDesktop(m_desktop);

            return result;
        }

        /// <summary>
        /// Enumerates the windows on a desktop.
        /// </summary>
        /// <param name="windows">Array of Desktop.Window objects to recieve windows.</param>
        /// <returns>A window colleciton if successful, otherwise null.</returns>
        public WindowCollection GetWindows()
        {
            // make sure object isnt disposed.
            CheckDisposed();

            // make sure a desktop is open.
            if (!IsOpen) return null;

            // init the arraylist.
            m_windows.Clear();
            WindowCollection windows = new WindowCollection();

            // get windows.
            bool result = EnumDesktopWindows(m_desktop, new EnumDesktopWindowsProc(DesktopWindowsProc), IntPtr.Zero);

            // check for error.
            if (!result) return null;

            // get window names.
            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)
        {
            // add window handle to colleciton.
            m_windows.Add(wndHandle);

            return true;
        }

        /// <summary>
        /// Creates a new process in a desktop.
        /// </summary>
        /// <param name="path">Path to application.</param>
        /// <returns>The process object for the newly created process.</returns>
        public Process CreateProcess(string path)
        {
            // make sure object isnt disposed.
            CheckDisposed();

            // make sure a desktop is open.
            if (!IsOpen) return null;

            // set startup parameters.
            STARTUPINFO si = new STARTUPINFO();
            si.cb = Marshal.SizeOf(si);
            si.lpDesktop = m_desktopName;

            PROCESS_INFORMATION pi = new PROCESS_INFORMATION();

            // start the process.
            bool result = CreateProcess(null, path, IntPtr.Zero, IntPtr.Zero, true, NORMAL_PRIORITY_CLASS, IntPtr.Zero, null, ref si, ref pi);

            // error?
            if (!result) return null;

            // Get the process.
            return Process.GetProcessById(pi.dwProcessId);
        }

        /// <summary>
        /// Prepares a desktop for use.  For use only on newly created desktops, call straight after CreateDesktop.
        /// </summary>
        public void Prepare()
        {
            // make sure object isnt disposed.
            CheckDisposed();

            // make sure a desktop is open.
            if (IsOpen)
            {
                // load explorer.
                CreateProcess("explorer.exe");
            }
        }
        #endregion

        #region Static Methods
        /// <summary>
        /// Enumerates all of the desktops.
        /// </summary>
        /// <param name="desktops">String array to recieve desktop names.</param>
        /// <returns>True if desktop names were successfully enumerated.</returns>
        public static string[] GetDesktops()
        {
            // attempt to enum desktops.
            IntPtr windowStation = GetProcessWindowStation();

            // check we got a valid handle.
            if (windowStation == IntPtr.Zero) return new string[0];

            string[] desktops;

            // lock the object. thread safety and all.
            lock (m_sc = new StringCollection())
            {
                bool result = EnumDesktops(windowStation, new EnumDesktopProc(DesktopProc), IntPtr.Zero);

                // something went wrong.
                if (!result) return new string[0];

                //	// turn the collection into an array.
                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)
        {
            // add the desktop to the collection.
            m_sc.Add(lpszDesktop);

            return true;
        }

        /// <summary>
        /// Switches to the specified desktop.
        /// </summary>
        /// <param name="name">Name of desktop to switch input to.</param>
        /// <returns>True if desktops were successfully switched.</returns>
        public static bool Show(string name)
        {
            // attmempt to open desktop.
            bool result = false;

            using (Desktop d = new Desktop())
            {
                result = d.Open(name);

                // something went wrong.
                if (!result) return false;

                // attempt to switch desktops.
                result = d.Show();
            }

            return result;
        }

        /// <summary>
        /// Gets the desktop of the calling thread.
        /// </summary>
        /// <returns>Returns a Desktop object for the valling thread.</returns>
        public static Desktop GetCurrent()
        {
            // get the desktop.
            return new Desktop(GetThreadDesktop(AppDomain.GetCurrentThreadId()));
        }

        /// <summary>
        /// Sets the desktop of the calling thread.
        /// NOTE: Function will fail if thread has hooks or windows in the current desktop.
        /// </summary>
        /// <param name="desktop">Desktop to put the thread in.</param>
        /// <returns>True if the threads desktop was successfully changed.</returns>
        public static bool SetCurrent(Desktop desktop)
        {
            // set threads desktop.
            if (!desktop.IsOpen) return false;

            return SetThreadDesktop(desktop.DesktopHandle);
        }

        /// <summary>
        /// Opens a desktop.
        /// </summary>
        /// <param name="name">The name of the desktop to open.</param>
        /// <returns>If successful, a Desktop object, otherwise, null.</returns>
        public static Desktop OpenDesktop(string name)
        {
            // open the desktop.
            Desktop desktop = new Desktop();
            bool result = desktop.Open(name);

            // somethng went wrong.
            if (!result) return null;

            return desktop;
        }

        /// <summary>
        /// Opens the current input desktop.
        /// </summary>
        /// <returns>If successful, a Desktop object, otherwise, null.</returns>
        public static Desktop OpenInputDesktop()
        {
            // open the desktop.
            Desktop desktop = new Desktop();
            bool result = desktop.OpenInput();

            // somethng went wrong.
            if (!result) return null;

            return desktop;
        }

        /// <summary>
        /// Opens the default desktop.
        /// </summary>
        /// <returns>If successful, a Desktop object, otherwise, null.</returns>
        public static Desktop OpenDefaultDesktop()
        {
            // opens the default desktop.
            return Desktop.OpenDesktop("Default");
        }

        /// <summary>
        /// Creates a new desktop.
        /// </summary>
        /// <param name="name">The name of the desktop to create.  Names are case sensitive.</param>
        /// <returns>If successful, a Desktop object, otherwise, null.</returns>
        public static Desktop CreateDesktop(string name)
        {
            // open the desktop.
            Desktop desktop = new Desktop();
            bool result = desktop.Create(name);

            // somethng went wrong.
            if (!result) return null;

            return desktop;
        }

        /// <summary>
        /// Gets the name of a given desktop.
        /// </summary>
        /// <param name="desktop">Desktop object whos name is to be found.</param>
        /// <returns>If successful, the desktop name, otherwise, null.</returns>
        public static string GetDesktopName(Desktop desktop)
        {
            // get name.
            if (desktop.IsOpen) return null;

            return GetDesktopName(desktop.DesktopHandle);
        }

        /// <summary>
        /// Gets the name of a desktop from a desktop handle.
        /// </summary>
        /// <param name="desktopHandle"></param>
        /// <returns>If successful, the desktop name, otherwise, null.</returns>
        public static string GetDesktopName(IntPtr desktopHandle)
        {
            // check its not a null pointer.
            // null pointers wont work.
            if (desktopHandle == IntPtr.Zero) return null;

            // get the length of the name.
            int needed = 0;
            string name = String.Empty;
            GetUserObjectInformation(desktopHandle, UOI_NAME, IntPtr.Zero, 0, ref needed);

            // get the name.
            IntPtr ptr = Marshal.AllocHGlobal(needed);
            bool result = GetUserObjectInformation(desktopHandle, UOI_NAME, ptr, needed, ref needed);
            name = Marshal.PtrToStringAnsi(ptr);
            Marshal.FreeHGlobal(ptr);

            // something went wrong.
            if (!result) return null;

            return name;
        }

        /// <summary>
        /// Checks if the specified desktop exists (using a case sensitive search).
        /// </summary>
        /// <param name="name">The name of the desktop.</param>
        /// <returns>True if the desktop exists, otherwise false.</returns>
        public static bool Exists(string name)
        {
            return Desktop.Exists(name, false);
        }

        /// <summary>
        /// Checks if the specified desktop exists.
        /// </summary>
        /// <param name="name">The name of the desktop.</param>
        /// <param name="caseInsensitive">If the search is case INsensitive.</param>
        /// <returns>True if the desktop exists, otherwise false.</returns>
        public static bool Exists(string name, bool caseInsensitive)
        {
            // enumerate desktops.
            string[] desktops = Desktop.GetDesktops();

            // return true if desktop exists.
            foreach (string desktop in desktops)
            {
                if (caseInsensitive)
                {
                    // case insensitive, compare all in lower case.
                    if (desktop.ToLower() == name.ToLower()) return true;
                }
                else
                {
                    if (desktop == name) return true;
                }
            }

            return false;
        }

        /// <summary>
        /// Creates a new process on the specified desktop.
        /// </summary>
        /// <param name="path">Path to application.</param>
        /// <param name="desktop">Desktop name.</param>
        /// <returns>A Process object for the newly created process, otherwise, null.</returns>
        public static Process CreateProcess(string path, string desktop)
        {
            if (!Desktop.Exists(desktop)) return null;

            // create the process.
            Desktop d = Desktop.OpenDesktop(desktop);
            return d.CreateProcess(path);
        }

        /// <summary>
        /// Gets an array of all the processes running on the Input desktop.
        /// </summary>
        /// <returns>An array of the processes.</returns>
        public static Process[] GetInputProcesses()
        {
            // get all processes.
            Process[] processes = Process.GetProcesses();

            ArrayList m_procs = new ArrayList();

            // get the current desktop name.
            string currentDesktop = GetDesktopName(Desktop.Input.DesktopHandle);

            // cycle through the processes.
            foreach (Process process in processes)
            {
                // check the threads of the process - are they in this one?
                foreach (ProcessThread pt in process.Threads)
                {
                    // check for a desktop name match.
                    if (GetDesktopName(GetThreadDesktop(pt.Id)) == currentDesktop)
                    {
                        // found a match, add to list, and bail.
                        m_procs.Add(process);
                        break;
                    }
                }
            }

            // put ArrayList into array.
            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
        /// <summary>
        /// Dispose Object.
        /// </summary>
        public void Dispose()
        {
            // dispose
            Dispose(true);

            // suppress finalisation
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// Dispose Object.
        /// </summary>
        /// <param name="disposing">True to dispose managed resources.</param>
        public virtual void Dispose(bool disposing)
        {
            if (!m_disposed)
            {
                // dispose of managed resources,
                // close handles
                Close();
            }

            m_disposed = true;
        }

        private void CheckDisposed()
        {
            // check if disposed
            if (m_disposed)
            {
                // object disposed, throw exception
                throw new ObjectDisposedException("");
            }
        }
        #endregion

        #region ICloneable
        /// <summary>
        /// Creates a new Desktop object with the same desktop open.
        /// </summary>
        /// <returns>Cloned desktop object.</returns>
        public object Clone()
        {
            // make sure object isnt disposed.
            CheckDisposed();

            Desktop desktop = new Desktop();

            // if a desktop is open, make the clone open it.
            if (IsOpen) desktop.Open(m_desktopName);

            return desktop;
        }
        #endregion

        #region Overrides
        /// <summary>
        /// Gets the desktop name.
        /// </summary>
        /// <returns>The desktop name, or a blank string if no desktop open.</returns>
        public override string ToString()
        {
            // return the desktop name.
            return m_desktopName;
        }
        #endregion









        public static void Log(string logMessage, TextWriter w)
        {
            //w.Write("\r\nLog Entry : ");
            //w.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(),
            //    DateTime.Now.ToLongDateString());
            //w.WriteLine("  :");
            //w.WriteLine("  :{0}", logMessage);
            w.WriteLine("  {0}", logMessage);
            //w.WriteLine("-------------------------------");
        }





        static void Main(string[] args)
        {

            //create desktop, add to it, then destroy

            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);





        }
    }
}

推荐答案


这篇关于适用于.net2.0的桌面交换示例代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-27 12:32