CreateProcessAsUser,C#寫的windows服務彈框提示消息或者啟動子進程


 

服務(Service)對於大家來說一定不會陌生,它是Windows 操作系統重要的組成部分。我們可以把服務想像成一種特殊的應用程序,它隨系統的“開啟~關閉”而“開始~停止”其工作內容,在這期間無需任何用戶參與。Windows 服務在后台執行着各種各樣任務,支持着我們日常的桌面操作。有時候可能需要服務與用戶進行信息或界面交互操作,這種方式在XP 時代是沒有問題的,但自從Vista 開始你會發現這種方式似乎已不起作用。

現在有個需求需要服務程序彈框提示和啟動包含復雜UI的桌面程序,"穿透Session 0 隔離"這篇文章已經寫得很好了,看了之后非常有幫助,但是在最后啟動了cmd之后發現就只能啟動cmd,啟動其他類型的程序都會報錯。仔細看了評論發現還是沒有解決,只是照着抄了一遍,發現不仔細看還是不是自己的東西(知識)啊。

原文鏈接:

穿透Session 0 隔離(一)

穿透Session 0 隔離(二)

最后修改了一下程序,解決了問題。跟原博主李敬然寫的稍微有點區別。我的是抄的msdn的代碼。總之就是 CreateProcessAsUser 函數的申明和調用有些區別。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Security.Principal;

namespace WindowsService1
{
    public class WinAPI_Interop
    {
        public static IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero;
        /// <summary>
        /// 服務程序執行消息提示,前台MessageBox.Show
        /// </summary>
        /// <param name="message">消息內容</param>
        /// <param name="title">標題</param>
        public static void ShowServiceMessage(string message, string title)
        {
            int resp = 0;
            WTSSendMessage(WTS_CURRENT_SERVER_HANDLE, WTSGetActiveConsoleSessionId(), title, title.Length, message, message.Length, 0, 0, out resp, false);
        }

        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern int WTSGetActiveConsoleSessionId();

        [DllImport("wtsapi32.dll", SetLastError = true)]
        public static extern bool WTSSendMessage(IntPtr hServer, int SessionId, String pTitle, int TitleLength, String pMessage, int MessageLength,int Style, int Timeout, out int pResponse, bool bWait);
        #region P/Invoke WTS APIs
        private enum WTS_CONNECTSTATE_CLASS
        {
            WTSActive,
            WTSConnected,
            WTSConnectQuery,
            WTSShadow,
            WTSDisconnected,
            WTSIdle,
            WTSListen,
            WTSReset,
            WTSDown,
            WTSInit
        }

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        private struct WTS_SESSION_INFO
        {
            public UInt32 SessionID;
            public string pWinStationName;
            public WTS_CONNECTSTATE_CLASS State;
        }

        [DllImport("WTSAPI32.DLL", SetLastError = true, CharSet = CharSet.Auto)]
        static extern bool WTSEnumerateSessions(
            IntPtr hServer,
            [MarshalAs(UnmanagedType.U4)] UInt32 Reserved,
            [MarshalAs(UnmanagedType.U4)] UInt32 Version,
            ref IntPtr ppSessionInfo,
            [MarshalAs(UnmanagedType.U4)] ref UInt32 pSessionInfoCount
            );

        [DllImport("WTSAPI32.DLL", SetLastError = true, CharSet = CharSet.Auto)]
        static extern void WTSFreeMemory(IntPtr pMemory);

        [DllImport("WTSAPI32.DLL", SetLastError = true, CharSet = CharSet.Auto)]
        static extern bool WTSQueryUserToken(UInt32 sessionId, out IntPtr Token);
        #endregion

        #region P/Invoke CreateProcessAsUser
        /// <summary> 
        /// Struct, Enum and P/Invoke Declarations for CreateProcessAsUser. 
        /// </summary> 
        ///  

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        struct STARTUPINFO
        {
            public Int32 cb;
            public string lpReserved;
            public string lpDesktop;
            public string lpTitle;
            public Int32 dwX;
            public Int32 dwY;
            public Int32 dwXSize;
            public Int32 dwYSize;
            public Int32 dwXCountChars;
            public Int32 dwYCountChars;
            public Int32 dwFillAttribute;
            public Int32 dwFlags;
            public Int16 wShowWindow;
            public Int16 cbReserved2;
            public IntPtr lpReserved2;
            public IntPtr hStdInput;
            public IntPtr hStdOutput;
            public IntPtr hStdError;
        }

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        struct PROCESS_INFORMATION
        {
            public IntPtr hProcess;
            public IntPtr hThread;
            public int dwProcessId;
            public int dwThreadId;
        }

        /// <summary>
        /// 以當前登錄的windows用戶(角色權限)運行指定程序進程
        /// </summary>
        /// <param name="hToken"></param>
        /// <param name="lpApplicationName">指定程序(全路徑)</param>
        /// <param name="lpCommandLine">參數</param>
        /// <param name="lpProcessAttributes">進程屬性</param>
        /// <param name="lpThreadAttributes">線程屬性</param>
        /// <param name="bInheritHandles"></param>
        /// <param name="dwCreationFlags"></param>
        /// <param name="lpEnvironment"></param>
        /// <param name="lpCurrentDirectory"></param>
        /// <param name="lpStartupInfo">程序啟動屬性</param>
        /// <param name="lpProcessInformation">最后返回的進程信息</param>
        /// <returns>是否調用成功</returns>
        [DllImport("ADVAPI32.DLL", SetLastError = true, CharSet = CharSet.Auto)]
        static extern bool CreateProcessAsUser(IntPtr hToken,string lpApplicationName,string lpCommandLine,IntPtr lpProcessAttributes,IntPtr lpThreadAttributes,
                                                      bool bInheritHandles,uint dwCreationFlags,string lpEnvironment,string lpCurrentDirectory,
                                                      ref STARTUPINFO lpStartupInfo,out PROCESS_INFORMATION lpProcessInformation);

        [DllImport("KERNEL32.DLL", SetLastError = true, CharSet = CharSet.Auto)]
        static extern bool CloseHandle(IntPtr hHandle);
        #endregion

        /// <summary>
        /// 以當前登錄系統的用戶角色權限啟動指定的進程
        /// </summary>
        /// <param name="ChildProcName">指定的進程(全路徑)</param>
        public static void CreateProcess(string ChildProcName)
        {
            IntPtr ppSessionInfo = IntPtr.Zero;
            UInt32 SessionCount = 0;
            if (WTSEnumerateSessions(
                                    (IntPtr)WTS_CURRENT_SERVER_HANDLE,  // Current RD Session Host Server handle would be zero. 
                                    0,  // This reserved parameter must be zero. 
                                    1,  // The version of the enumeration request must be 1. 
                                    ref ppSessionInfo, // This would point to an array of session info. 
                                    ref SessionCount  // This would indicate the length of the above array.
                                    ))
            {
                for (int nCount = 0; nCount < SessionCount; nCount++)
                {
                    WTS_SESSION_INFO tSessionInfo = (WTS_SESSION_INFO)Marshal.PtrToStructure(ppSessionInfo + nCount * Marshal.SizeOf(typeof(WTS_SESSION_INFO)), typeof(WTS_SESSION_INFO));
                    if (WTS_CONNECTSTATE_CLASS.WTSActive == tSessionInfo.State)
                    {
                        IntPtr hToken = IntPtr.Zero;
                        if (WTSQueryUserToken(tSessionInfo.SessionID, out hToken))
                        {
                            PROCESS_INFORMATION tProcessInfo;
                            STARTUPINFO tStartUpInfo = new STARTUPINFO();
                            tStartUpInfo.cb = Marshal.SizeOf(typeof(STARTUPINFO));
                            bool ChildProcStarted = CreateProcessAsUser(
                                                                        hToken,             // Token of the logged-on user. 
                                                                        ChildProcName,      // Name of the process to be started. 
                                                                        null,               // Any command line arguments to be passed. 
                                                                        IntPtr.Zero,        // Default Process' attributes. 
                                                                        IntPtr.Zero,        // Default Thread's attributes. 
                                                                        false,              // Does NOT inherit parent's handles. 
                                                                        0,                  // No any specific creation flag. 
                                                                        null,               // Default environment path. 
                                                                        null,               // Default current directory. 
                                                                        ref tStartUpInfo,   // Process Startup Info.  
                                                                        out tProcessInfo    // Process information to be returned. 
                                                     );
                            if (ChildProcStarted)
                            {
                                CloseHandle(tProcessInfo.hThread);
                                CloseHandle(tProcessInfo.hProcess);
                            }
                            else
                            {
                                ShowServiceMessage("CreateProcessAsUser失敗", "CreateProcess");
                            }
                            CloseHandle(hToken);
                            break;
                        }
                    }
                }
                WTSFreeMemory(ppSessionInfo);
            }
        }
    }
}

  調用:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Windows.Forms;

namespace WindowsService1
{
    public partial class AlertService : ServiceBase
    {
        public AlertService()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            //Interop.ShowMessageBox("This a message from AlertService.","AlertService Message");
            WinAPI_Interop.CreateProcess(@"E:\work\box\GreenlandBox\BinFiles\ClientBin\BufferBox.exe");
            //Interop.CreateProcess("cmd.exe", @"C:\Windows\System32\");
        }

        protected override void OnStop()
        {
        }
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM