process.Start(); 进程启动

时间:2022-08-29 14:45:44

我希望被启动的程序出现界面

现在的情况是,任务管理器里边可以看到进程,但是出不了程序界面




        private void MTimedEvent(object source, System.Timers.ElapsedEventArgs e)
        {
            //你要实现的方法
            if (!CheckProcess("GSM串口调试助手"))
            {
                WriteMsg("线程不存在,准备重启");
                ProcessStart("C:\\Users\\Administrator\\Desktop\\短信猫\\GSM串口调试助手\\GSM串口调试助手.exe");
            }
        }


        public Process ProcessStart(string fileName, string command=null)
        {
            try
            {
                Process process = new Process();
                process.StartInfo.FileName = fileName;
                process.StartInfo.Arguments = command;
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.RedirectStandardInput = true;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardError = true;
                process.StartInfo.CreateNoWindow = false;
                process.Start();
                return process;
            }
            catch (Exception ex)
            {
                throw (ex);
            }
        }











13 个解决方案

#1


赶脚是不是没得权限

#2


引用 1 楼 ly12530 的回复:
赶脚是不是没得权限


没有权限,应该任务管理器里边都没有进程。  

现在 任务管理器 有进程

#3


你在资源管理器中双击程序能显示吗

#4


引用 3 楼 bdmh 的回复:
你在资源管理器中双击程序能显示吗


双击任何反应都没有

#5


引用 3 楼 bdmh 的回复:
你在资源管理器中双击程序能显示吗



上边的代码,放在windows service里边就不会出现窗口。

但是放到winform里边,就会弹出窗口

但是我需要在windows service里边用,service做成一个守护进程

#6


Session0隔离造成的,你可以自己看下任务管理器子进程的用户会和服务一样
系统启动时,所有的系统后台服务(运行用户通常是System Network Service==)都将运行在Session0中
系统桌面(explorer)可以理解为一个特殊的窗口,用户程序的窗口全部都是它的子窗口(这个可以从Spy++的窗口树结构中看出来)
在vista之前的系统,没有采取隔离,第一个登陆的用户的SessionID(任务管理器的选择列里可以调出)也是0,也就是他们共用一个桌面环境(可通过Win API GetDesktopWindow)来获得桌面窗口句柄

在XP、2003里面,将服务设置为“允许与用户桌面进行交互式访问”,再用你上面的方法就不会有问题了
但是win7上即使设置了,也一样会警告后台有消息(窗口)弹出,并且在用户点开查看那个消息之前,服务线程将一直阻塞

再来说解决办法,你搜一下穿透Session0隔离,方法有很多种
针对你的问题,由于子进程默认会使用父进程的用户(system)来打开(没有前台线程消息循环)。所以只需要模拟用户程序来打开就不会有问题了。以模拟指定会话ID的explore进程(登陆的用户)的UserToken来打开

#7



class RunAsUser
    {
        #region 获取/复制用户令牌,启动进程
        internal const int GENERIC_ALL_ACCESS = 0x10000000; //访问权限

        [StructLayout(LayoutKind.Sequential)]
        public 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 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)]
        public struct Process_Information
        {
            public IntPtr hProcess;
            public IntPtr hThread;
            public Int32 dwProcessID;
            public Int32 dwThreadID;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct SecurityAttributes
        {
            public Int32 Length;
            public IntPtr lpSecurityDescriptor;
            public bool bInheritHandle;
        }

        public enum SecurityImpersonationLevel
        {
            SecurityAnonymous,
            SecurityIdentification,
            SecurityImpersonation,
            SecurityDelegation
        }

        public enum TokenType
        {
            TokenPrimary = 1,
            TokenImpersonation
        }

        [DllImport("advapi32", SetLastError = true)]
        public static extern bool OpenProcessToken(IntPtr processHandle, TokenAccessLevels desiredAccess, ref IntPtr htok);

        [DllImport("advapi32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool CreateProcessAsUser(
            IntPtr hToken,
            string lpApplicationName,
            string lpCommandLine,
            ref SecurityAttributes lpProcessAttributes,
            ref SecurityAttributes lpThreadAttributes,
            bool bInheritHandle,
            Int32 dwCreationFlags,
            IntPtr lpEnvrionment,
            string lpCurrentDirectory,
            ref StartUpInfo lpStartupInfo,
            ref Process_Information lpProcessInformation);

        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern bool DuplicateTokenEx(
            IntPtr hExistingToken,
            Int32 dwDesiredAccess,
            ref SecurityAttributes lpThreadAttributes,
            Int32 ImpersonationLevel,
            Int32 dwTokenType,
            ref IntPtr phNewToken);

        [DllImport("userenv.dll", SetLastError = true)]
        public static extern bool CreateEnvironmentBlock(out IntPtr lpEnvironment, IntPtr hToken, bool bInherit);

        [DllImport("kernel32.dll")]
        public static extern int WTSGetActiveConsoleSessionId();

        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool CloseHandle(IntPtr handle);
        #endregion        

        #region 模拟用户进程
        /// <summary>
        /// 调用方必须具备System权限
        /// </summary>
        /// <param name="sessionId"></param>
        /// <param name="appFullName"></param>
        /// <param name="args"></param>
        public static void CreateProcess(int sessionId, string appFullName, string args)
        {            
            if (!System.IO.File.Exists(appFullName))
            {
                throw new System.IO.FileNotFoundException(appFullName);
            }
            bool sucess = false;
            IntPtr hToken = IntPtr.Zero, hDupedToken = IntPtr.Zero;
            Process_Information pi = new Process_Information();
            SecurityAttributes sa;
            try
            {
                //服务程序中,通过桌面进程的SessionId来获得
                Process explorer = null;
                foreach(var process in Process.GetProcessesByName("explorer"))
                {
                    if (process.SessionId == sessionId)
                    {
                        explorer = process;
                        break;
                    }
                }
                if (explorer == null)
                {
                    TraceWin32Error("There has no Explorer process running yet!");
                    return;
                }                
                Process.EnterDebugMode();
                sucess = OpenProcessToken(explorer.Handle, TokenAccessLevels.Duplicate | TokenAccessLevels.Read | TokenAccessLevels.Impersonate, ref hToken);
                if (!sucess)
                {
                    TraceWin32Error("OpenProcessToken");                    
                    return;
                }
                sa = new SecurityAttributes();
                sa.Length = Marshal.SizeOf(sa);
                var si = new StartUpInfo();
                si.cb = Marshal.SizeOf(si);
                sucess = DuplicateTokenEx(
                        hToken,
                        GENERIC_ALL_ACCESS,
                        ref sa,
                        (int)SecurityImpersonationLevel.SecurityIdentification,
                        (int)TokenType.TokenPrimary,
                        ref hDupedToken
                );
                if (!sucess)
                {
                    TraceWin32Error("DuplicateTokenEx");
                    return;
                }                
                IntPtr lpEnvironment = IntPtr.Zero;
                sucess = CreateEnvironmentBlock(out lpEnvironment, hDupedToken, false);
                if (!sucess)
                {
                    TraceWin32Error("CreateEnvironmentBlock");
                    return;
                }
                sucess = CreateProcessAsUser(
                    hDupedToken,
                    appFullName,
                    args,
                    ref sa, ref sa,
                    false, 0, IntPtr.Zero,
                    null,
                    ref si,
                    ref pi
                );
                if (!sucess)
                {
                    TraceWin32Error("CreateProcessAsUser");
                }
            }
            finally
            {
                if (hDupedToken != IntPtr.Zero) CloseHandle(hDupedToken);
                if (pi.hProcess != IntPtr.Zero) CloseHandle(pi.hProcess);
                if (pi.hThread != IntPtr.Zero) CloseHandle(pi.hThread);
                Process.LeaveDebugMode();
            }
        }

        static void TraceWin32Error(string error)
        {
            WriteLog("{0}\t{1}:Last Error Code[{2}]", DateTime.Now.ToString(), error, Marshal.GetLastWin32Error().ToString());
        }
        #endregion
    }

多用户登陆时,以当前活动用户启动可以用WTSGetActiveConsoleSessionId();取得作为第一个参数

#8


引用 7 楼 dongxinxi 的回复:
多用户登陆时,以当前活动用户启动可以用WTSGetActiveConsoleSessionId();取得作为第一个参数


东西有点多,慢慢消化下

#9


很简单,Process.Start("Update.exe");
这样就出来了!
记得全部给分我。

#10


引用 9 楼 qingfeng_wu 的回复:
很简单,Process.Start("Update.exe");
这样就出来了!
记得全部给分我。


这样的方法,会弹出一个 无法和桌面交互 的窗口。

需要人工再去点击,显示消息,并且显示后,其它桌面要等关闭它才能用。  这样不行

#11


Application.Exit();
Process.Start("Update.exe");

那你这样看看,变通点!

#12


引用 6 楼 dongxinxi 的回复:
Session0隔离造成的,你可以自己看下任务管理器子进程的用户会和服务一样
系统启动时,所有的系统后台服务(运行用户通常是System Network Service==)都将运行在Session0中
系统桌面(explorer)可以理解为一个特殊的窗口,用户程序的窗口全部都是它的子窗口(这个可以从Spy++的窗口树结构中看出来)
在vista之前的系统,没有采取隔离,第一个登陆的用户的SessionID(任务管理器的选择列里可以调出)也是0,也就是他们共用一个桌面环境(可通过Win API GetDesktopWindow)来获得桌面窗口句柄

在XP、2003里面,将服务设置为“允许与用户桌面进行交互式访问”,再用你上面的方法就不会有问题了
但是win7上即使设置了,也一样会警告后台有消息(窗口)弹出,并且在用户点开查看那个消息之前,服务线程将一直阻塞

再来说解决办法,你搜一下穿透Session0隔离,方法有很多种
针对你的问题,由于子进程默认会使用父进程的用户(system)来打开(没有前台线程消息循环)。所以只需要模拟用户程序来打开就不会有问题了。以模拟指定会话ID的explore进程(登陆的用户)的UserToken来打开



谢谢,我把你的方法直接拷贝,就可以用。

#13


我也直接拷贝了,然后再OnStart方法里面去调用。
但,看上去好像并没有调用成功,没有log写到文件里面去。
本人刚开始接触windows 服务,还请大家给予帮助

#1


赶脚是不是没得权限

#2


引用 1 楼 ly12530 的回复:
赶脚是不是没得权限


没有权限,应该任务管理器里边都没有进程。  

现在 任务管理器 有进程

#3


你在资源管理器中双击程序能显示吗

#4


引用 3 楼 bdmh 的回复:
你在资源管理器中双击程序能显示吗


双击任何反应都没有

#5


引用 3 楼 bdmh 的回复:
你在资源管理器中双击程序能显示吗



上边的代码,放在windows service里边就不会出现窗口。

但是放到winform里边,就会弹出窗口

但是我需要在windows service里边用,service做成一个守护进程

#6


Session0隔离造成的,你可以自己看下任务管理器子进程的用户会和服务一样
系统启动时,所有的系统后台服务(运行用户通常是System Network Service==)都将运行在Session0中
系统桌面(explorer)可以理解为一个特殊的窗口,用户程序的窗口全部都是它的子窗口(这个可以从Spy++的窗口树结构中看出来)
在vista之前的系统,没有采取隔离,第一个登陆的用户的SessionID(任务管理器的选择列里可以调出)也是0,也就是他们共用一个桌面环境(可通过Win API GetDesktopWindow)来获得桌面窗口句柄

在XP、2003里面,将服务设置为“允许与用户桌面进行交互式访问”,再用你上面的方法就不会有问题了
但是win7上即使设置了,也一样会警告后台有消息(窗口)弹出,并且在用户点开查看那个消息之前,服务线程将一直阻塞

再来说解决办法,你搜一下穿透Session0隔离,方法有很多种
针对你的问题,由于子进程默认会使用父进程的用户(system)来打开(没有前台线程消息循环)。所以只需要模拟用户程序来打开就不会有问题了。以模拟指定会话ID的explore进程(登陆的用户)的UserToken来打开

#7



class RunAsUser
    {
        #region 获取/复制用户令牌,启动进程
        internal const int GENERIC_ALL_ACCESS = 0x10000000; //访问权限

        [StructLayout(LayoutKind.Sequential)]
        public 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 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)]
        public struct Process_Information
        {
            public IntPtr hProcess;
            public IntPtr hThread;
            public Int32 dwProcessID;
            public Int32 dwThreadID;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct SecurityAttributes
        {
            public Int32 Length;
            public IntPtr lpSecurityDescriptor;
            public bool bInheritHandle;
        }

        public enum SecurityImpersonationLevel
        {
            SecurityAnonymous,
            SecurityIdentification,
            SecurityImpersonation,
            SecurityDelegation
        }

        public enum TokenType
        {
            TokenPrimary = 1,
            TokenImpersonation
        }

        [DllImport("advapi32", SetLastError = true)]
        public static extern bool OpenProcessToken(IntPtr processHandle, TokenAccessLevels desiredAccess, ref IntPtr htok);

        [DllImport("advapi32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool CreateProcessAsUser(
            IntPtr hToken,
            string lpApplicationName,
            string lpCommandLine,
            ref SecurityAttributes lpProcessAttributes,
            ref SecurityAttributes lpThreadAttributes,
            bool bInheritHandle,
            Int32 dwCreationFlags,
            IntPtr lpEnvrionment,
            string lpCurrentDirectory,
            ref StartUpInfo lpStartupInfo,
            ref Process_Information lpProcessInformation);

        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern bool DuplicateTokenEx(
            IntPtr hExistingToken,
            Int32 dwDesiredAccess,
            ref SecurityAttributes lpThreadAttributes,
            Int32 ImpersonationLevel,
            Int32 dwTokenType,
            ref IntPtr phNewToken);

        [DllImport("userenv.dll", SetLastError = true)]
        public static extern bool CreateEnvironmentBlock(out IntPtr lpEnvironment, IntPtr hToken, bool bInherit);

        [DllImport("kernel32.dll")]
        public static extern int WTSGetActiveConsoleSessionId();

        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool CloseHandle(IntPtr handle);
        #endregion        

        #region 模拟用户进程
        /// <summary>
        /// 调用方必须具备System权限
        /// </summary>
        /// <param name="sessionId"></param>
        /// <param name="appFullName"></param>
        /// <param name="args"></param>
        public static void CreateProcess(int sessionId, string appFullName, string args)
        {            
            if (!System.IO.File.Exists(appFullName))
            {
                throw new System.IO.FileNotFoundException(appFullName);
            }
            bool sucess = false;
            IntPtr hToken = IntPtr.Zero, hDupedToken = IntPtr.Zero;
            Process_Information pi = new Process_Information();
            SecurityAttributes sa;
            try
            {
                //服务程序中,通过桌面进程的SessionId来获得
                Process explorer = null;
                foreach(var process in Process.GetProcessesByName("explorer"))
                {
                    if (process.SessionId == sessionId)
                    {
                        explorer = process;
                        break;
                    }
                }
                if (explorer == null)
                {
                    TraceWin32Error("There has no Explorer process running yet!");
                    return;
                }                
                Process.EnterDebugMode();
                sucess = OpenProcessToken(explorer.Handle, TokenAccessLevels.Duplicate | TokenAccessLevels.Read | TokenAccessLevels.Impersonate, ref hToken);
                if (!sucess)
                {
                    TraceWin32Error("OpenProcessToken");                    
                    return;
                }
                sa = new SecurityAttributes();
                sa.Length = Marshal.SizeOf(sa);
                var si = new StartUpInfo();
                si.cb = Marshal.SizeOf(si);
                sucess = DuplicateTokenEx(
                        hToken,
                        GENERIC_ALL_ACCESS,
                        ref sa,
                        (int)SecurityImpersonationLevel.SecurityIdentification,
                        (int)TokenType.TokenPrimary,
                        ref hDupedToken
                );
                if (!sucess)
                {
                    TraceWin32Error("DuplicateTokenEx");
                    return;
                }                
                IntPtr lpEnvironment = IntPtr.Zero;
                sucess = CreateEnvironmentBlock(out lpEnvironment, hDupedToken, false);
                if (!sucess)
                {
                    TraceWin32Error("CreateEnvironmentBlock");
                    return;
                }
                sucess = CreateProcessAsUser(
                    hDupedToken,
                    appFullName,
                    args,
                    ref sa, ref sa,
                    false, 0, IntPtr.Zero,
                    null,
                    ref si,
                    ref pi
                );
                if (!sucess)
                {
                    TraceWin32Error("CreateProcessAsUser");
                }
            }
            finally
            {
                if (hDupedToken != IntPtr.Zero) CloseHandle(hDupedToken);
                if (pi.hProcess != IntPtr.Zero) CloseHandle(pi.hProcess);
                if (pi.hThread != IntPtr.Zero) CloseHandle(pi.hThread);
                Process.LeaveDebugMode();
            }
        }

        static void TraceWin32Error(string error)
        {
            WriteLog("{0}\t{1}:Last Error Code[{2}]", DateTime.Now.ToString(), error, Marshal.GetLastWin32Error().ToString());
        }
        #endregion
    }

多用户登陆时,以当前活动用户启动可以用WTSGetActiveConsoleSessionId();取得作为第一个参数

#8


引用 7 楼 dongxinxi 的回复:
多用户登陆时,以当前活动用户启动可以用WTSGetActiveConsoleSessionId();取得作为第一个参数


东西有点多,慢慢消化下

#9


很简单,Process.Start("Update.exe");
这样就出来了!
记得全部给分我。

#10


引用 9 楼 qingfeng_wu 的回复:
很简单,Process.Start("Update.exe");
这样就出来了!
记得全部给分我。


这样的方法,会弹出一个 无法和桌面交互 的窗口。

需要人工再去点击,显示消息,并且显示后,其它桌面要等关闭它才能用。  这样不行

#11


Application.Exit();
Process.Start("Update.exe");

那你这样看看,变通点!

#12


引用 6 楼 dongxinxi 的回复:
Session0隔离造成的,你可以自己看下任务管理器子进程的用户会和服务一样
系统启动时,所有的系统后台服务(运行用户通常是System Network Service==)都将运行在Session0中
系统桌面(explorer)可以理解为一个特殊的窗口,用户程序的窗口全部都是它的子窗口(这个可以从Spy++的窗口树结构中看出来)
在vista之前的系统,没有采取隔离,第一个登陆的用户的SessionID(任务管理器的选择列里可以调出)也是0,也就是他们共用一个桌面环境(可通过Win API GetDesktopWindow)来获得桌面窗口句柄

在XP、2003里面,将服务设置为“允许与用户桌面进行交互式访问”,再用你上面的方法就不会有问题了
但是win7上即使设置了,也一样会警告后台有消息(窗口)弹出,并且在用户点开查看那个消息之前,服务线程将一直阻塞

再来说解决办法,你搜一下穿透Session0隔离,方法有很多种
针对你的问题,由于子进程默认会使用父进程的用户(system)来打开(没有前台线程消息循环)。所以只需要模拟用户程序来打开就不会有问题了。以模拟指定会话ID的explore进程(登陆的用户)的UserToken来打开



谢谢,我把你的方法直接拷贝,就可以用。

#13


我也直接拷贝了,然后再OnStart方法里面去调用。
但,看上去好像并没有调用成功,没有log写到文件里面去。
本人刚开始接触windows 服务,还请大家给予帮助