博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
CreateProcessAsUser,C#写的windows服务弹框提示消息或者启动子进程
阅读量:6859 次
发布时间:2019-06-26

本文共 9371 字,大约阅读时间需要 31 分钟。

 

服务(Service)对于大家来说一定不会陌生,它是Windows 操作系统重要的组成部分。我们可以把服务想像成一种特殊的应用程序,它随系统的“开启~关闭”而“开始~停止”其工作内容,在这期间无需任何用户参与。Windows 服务在后台执行着各种各样任务,支持着我们日常的桌面操作。有时候可能需要服务与用户进行信息或界面交互操作,这种方式在XP 时代是没有问题的,但自从Vista 开始你会发现这种方式似乎已不起作用。

现在有个需求需要服务程序弹框提示和启动包含复杂UI的桌面程序,"穿透Session 0 隔离"这篇文章已经写得很好了,看了之后非常有帮助,但是在最后启动了cmd之后发现就只能启动cmd,启动其他类型的程序都会报错。仔细看了评论发现还是没有解决,只是照着抄了一遍,发现不仔细看还是不是自己的东西(知识)啊。

原文链接:

最后修改了一下程序,解决了问题。跟原博主写的稍微有点区别。我的是抄的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;        ///         /// 服务程序执行消息提示,前台MessageBox.Show        ///         /// 消息内容        /// 标题        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        ///          /// Struct, Enum and P/Invoke Declarations for CreateProcessAsUser.         ///          ///          [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;        }        ///         /// 以当前登录的windows用户(角色权限)运行指定程序进程        ///         ///         /// 指定程序(全路径)        /// 参数        /// 进程属性        /// 线程属性        ///         ///         ///         ///         /// 程序启动属性        /// 最后返回的进程信息        /// 
是否调用成功
[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 /// /// 以当前登录系统的用户角色权限启动指定的进程 /// /// 指定的进程(全路径) 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()        {        }    }}

 

转载地址:http://nbxyl.baihongyu.com/

你可能感兴趣的文章
删除MySQL中冗余字段
查看>>
linux基础—课堂随笔_03 SHELL脚本编程基础
查看>>
【Win7快捷键启动程序有哪些妙招】
查看>>
MS DOS 命令大全
查看>>
College student reflects on getting started in open source(一)
查看>>
Windows下初次手动安装composer详细教学
查看>>
Oracle 查询库中所有表名、字段名、字段名说明,查询表的数据条数、表名、中文表名、...
查看>>
JAVA入门到精通-第53讲-数据库概念
查看>>
升级10.10 Yosemite 后,cocoapods 出现错误(解决方案)
查看>>
[Microsoft][ODBC 驱动程序管理器] 在指定的 DSN 中,驱动程序和应用程序之间的体系结构不匹配...
查看>>
SQL ROW_NUMBER() 分页使用示例
查看>>
UEditor编辑器两个版本任意文件上传漏洞分析
查看>>
Redis分布式锁服务(八)
查看>>
MySQL的引入
查看>>
C++单例模式
查看>>
bower安装报错”Cannot be run with sudo”解决办法
查看>>
android平台中编写jni模块的方法(3)
查看>>
软件工程网络15结对编程1——四则运算优化
查看>>
进程、应用程序域,线程和上下文之间的关系
查看>>
c++作业:递归调用,例题4.5 求第五个人的年龄
查看>>