我希望被启动的程序出现界面
现在的情况是,任务管理器里边可以看到进程,但是出不了程序界面
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
没有权限,应该任务管理器里边都没有进程。
现在 任务管理器 有进程
#3
你在资源管理器中双击程序能显示吗
#4
双击任何反应都没有
#5
上边的代码,放在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来打开
系统启动时,所有的系统后台服务(运行用户通常是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
东西有点多,慢慢消化下
#9
很简单,Process.Start("Update.exe");
这样就出来了!
记得全部给分我。
这样就出来了!
记得全部给分我。
#10
这样的方法,会弹出一个 无法和桌面交互 的窗口。
需要人工再去点击,显示消息,并且显示后,其它桌面要等关闭它才能用。 这样不行
#11
Application.Exit();
Process.Start("Update.exe");
那你这样看看,变通点!
Process.Start("Update.exe");
那你这样看看,变通点!
#12
谢谢,我把你的方法直接拷贝,就可以用。
#13
我也直接拷贝了,然后再OnStart方法里面去调用。
但,看上去好像并没有调用成功,没有log写到文件里面去。
本人刚开始接触windows 服务,还请大家给予帮助
但,看上去好像并没有调用成功,没有log写到文件里面去。
本人刚开始接触windows 服务,还请大家给予帮助
#1
赶脚是不是没得权限
#2
没有权限,应该任务管理器里边都没有进程。
现在 任务管理器 有进程
#3
你在资源管理器中双击程序能显示吗
#4
双击任何反应都没有
#5
上边的代码,放在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来打开
系统启动时,所有的系统后台服务(运行用户通常是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
东西有点多,慢慢消化下
#9
很简单,Process.Start("Update.exe");
这样就出来了!
记得全部给分我。
这样就出来了!
记得全部给分我。
#10
这样的方法,会弹出一个 无法和桌面交互 的窗口。
需要人工再去点击,显示消息,并且显示后,其它桌面要等关闭它才能用。 这样不行
#11
Application.Exit();
Process.Start("Update.exe");
那你这样看看,变通点!
Process.Start("Update.exe");
那你这样看看,变通点!
#12
谢谢,我把你的方法直接拷贝,就可以用。
#13
我也直接拷贝了,然后再OnStart方法里面去调用。
但,看上去好像并没有调用成功,没有log写到文件里面去。
本人刚开始接触windows 服务,还请大家给予帮助
但,看上去好像并没有调用成功,没有log写到文件里面去。
本人刚开始接触windows 服务,还请大家给予帮助