如何从.NETWeb服务启动应用程序?

如何从.NETWeb服务启动应用程序?,.net,web-services,process,.net,Web Services,Process,我使用System.Diagnostic.Process类在使用.Net WCF web服务的服务器pc上启动进程。它们启动平稳,我可以看到它们在任务管理器中运行,但没有显示任何窗口。你们认为我怎样才能克服这个问题呢?你们说的是一个web服务,所以它也可能作为Windows服务运行? 在这种情况下,您可以启动流程,但永远看不到任何表单 Windows服务设计为在您的计算机上运行,即使没有用户登录。 因此,它永远不知道在哪里显示要运行的应用程序 您可以随意使用一个名为“允许与桌面交互”或类似的设置

我使用System.Diagnostic.Process类在使用.Net WCF web服务的服务器pc上启动进程。它们启动平稳,我可以看到它们在任务管理器中运行,但没有显示任何窗口。你们认为我怎样才能克服这个问题呢?

你们说的是一个web服务,所以它也可能作为Windows服务运行? 在这种情况下,您可以启动流程,但永远看不到任何表单

Windows服务设计为在您的计算机上运行,即使没有用户登录。 因此,它永远不知道在哪里显示要运行的应用程序


您可以随意使用一个名为“允许与桌面交互”或类似的设置,但服务不应该以这种方式使用。

您指的是web服务,因此它可能也作为Windows服务运行? 在这种情况下,您可以启动流程,但永远看不到任何表单

Windows服务设计为在您的计算机上运行,即使没有用户登录。 因此,它永远不知道在哪里显示要运行的应用程序


您可以随意使用一个名为“允许与桌面交互”或类似的设置,但服务并不打算以这种方式使用。

如果您想显示GUI并让用户能够与之交互,您必须启动一个交互过程。您的web服务目前可能不是这样


请参见

如果要显示GUI并让用户能够与之交互,则必须启动交互过程。您的web服务目前可能不是这样


你不应该这样做,但是

您可以作为当前会话中的用户在中启动程序

IntPtr UserTokenHandle = IntPtr.Zero;
WTSQueryUserToken ( WTSGetActiveConsoleSessionId(), ref UserTokenHandle);

PROCESS_INFORMATION ProcInfo = new PROCESS_INFORMATION();
STARTUPINFOW StartInfo = new STARTUPINFOW();
StartInfo.cb = Convert.ToUInt32(System.Runtime.InteropServices.Marshal.SizeOf(StartInfo));


CreateProcessAsUser ( UserTokenHandle, @"C:\dir\MyApp.exe",
    IntPtr.Zero,
    IntPtr.Zero,
    IntPtr.Zero,
    false,
    0,
    IntPtr.Zero,
    null,
    ref StartInfo,
    ref ProcInfo);

if (!(UserTokenHandle == IntPtr.Zero))
{
    CloseHandle ( UserTokenHandle);
}
所需的导入和结构:

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

[DllImport("Wtsapi32.dll", EntryPoint = "WTSQueryUserToken", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool WTSQueryUserToken ( uint SessionId, ref IntPtr phToken );

[DllImport("kernel32.dll", EntryPoint = "CloseHandle", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseHandle ( [InAttribute()]
    IntPtr hObject );

[DllImport("advapi32.dll", EntryPoint = "CreateProcessAsUserW", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CreateProcessAsUser (
    [InAttribute()]
    IntPtr hToken,
    [InAttribute(), MarshalAs(UnmanagedType.LPWStr)]
    string lpApplicationName, System.IntPtr lpCommandLine,
    [InAttribute()]
    IntPtr lpProcessAttributes,
    [InAttribute()]
    IntPtr lpThreadAttributes,
    [MarshalAs(UnmanagedType.Bool)]
    bool bInheritHandles, uint dwCreationFlags,
    [InAttribute()]
    IntPtr lpEnvironment,
    [InAttribute(), MarshalAsAttribute(UnmanagedType.LPWStr)]
    string lpCurrentDirectory,

ref STARTUPINFOW lpStartupInfo,

ref PROCESS_INFORMATION lpProcessInformation );

[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
    public uint nLength;
    public IntPtr lpSecurityDescriptor;
    [MarshalAs(UnmanagedType.Bool)]
    public bool bInheritHandle;
}

[StructLayout(LayoutKind.Sequential)]
public struct STARTUPINFOW
{
    public uint cb;
    [MarshalAs(UnmanagedType.LPWStr)]
    public string lpReserved;
    [MarshalAs(UnmanagedType.LPWStr)]
    public string lpDesktop;
    [MarshalAs(UnmanagedType.LPWStr)]
    public string lpTitle;
    public uint dwX;
    public uint dwY;
    public uint dwXSize;
    public uint dwYSize;
    public uint dwXCountChars;
    public uint dwYCountChars;
    public uint dwFillAttribute;
    public uint dwFlags;
    public ushort wShowWindow;
    public ushort 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 uint dwProcessId;
    public uint dwThreadId;
}

你不应该这么做,但是

您可以作为当前会话中的用户在中启动程序

IntPtr UserTokenHandle = IntPtr.Zero;
WTSQueryUserToken ( WTSGetActiveConsoleSessionId(), ref UserTokenHandle);

PROCESS_INFORMATION ProcInfo = new PROCESS_INFORMATION();
STARTUPINFOW StartInfo = new STARTUPINFOW();
StartInfo.cb = Convert.ToUInt32(System.Runtime.InteropServices.Marshal.SizeOf(StartInfo));


CreateProcessAsUser ( UserTokenHandle, @"C:\dir\MyApp.exe",
    IntPtr.Zero,
    IntPtr.Zero,
    IntPtr.Zero,
    false,
    0,
    IntPtr.Zero,
    null,
    ref StartInfo,
    ref ProcInfo);

if (!(UserTokenHandle == IntPtr.Zero))
{
    CloseHandle ( UserTokenHandle);
}
所需的导入和结构:

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

[DllImport("Wtsapi32.dll", EntryPoint = "WTSQueryUserToken", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool WTSQueryUserToken ( uint SessionId, ref IntPtr phToken );

[DllImport("kernel32.dll", EntryPoint = "CloseHandle", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseHandle ( [InAttribute()]
    IntPtr hObject );

[DllImport("advapi32.dll", EntryPoint = "CreateProcessAsUserW", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CreateProcessAsUser (
    [InAttribute()]
    IntPtr hToken,
    [InAttribute(), MarshalAs(UnmanagedType.LPWStr)]
    string lpApplicationName, System.IntPtr lpCommandLine,
    [InAttribute()]
    IntPtr lpProcessAttributes,
    [InAttribute()]
    IntPtr lpThreadAttributes,
    [MarshalAs(UnmanagedType.Bool)]
    bool bInheritHandles, uint dwCreationFlags,
    [InAttribute()]
    IntPtr lpEnvironment,
    [InAttribute(), MarshalAsAttribute(UnmanagedType.LPWStr)]
    string lpCurrentDirectory,

ref STARTUPINFOW lpStartupInfo,

ref PROCESS_INFORMATION lpProcessInformation );

[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
    public uint nLength;
    public IntPtr lpSecurityDescriptor;
    [MarshalAs(UnmanagedType.Bool)]
    public bool bInheritHandle;
}

[StructLayout(LayoutKind.Sequential)]
public struct STARTUPINFOW
{
    public uint cb;
    [MarshalAs(UnmanagedType.LPWStr)]
    public string lpReserved;
    [MarshalAs(UnmanagedType.LPWStr)]
    public string lpDesktop;
    [MarshalAs(UnmanagedType.LPWStr)]
    public string lpTitle;
    public uint dwX;
    public uint dwY;
    public uint dwXSize;
    public uint dwYSize;
    public uint dwXCountChars;
    public uint dwYCountChars;
    public uint dwFillAttribute;
    public uint dwFlags;
    public ushort wShowWindow;
    public ushort 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 uint dwProcessId;
    public uint dwThreadId;
}


由于许多原因,首先是安全性和健壮性,服务无法交互。检查解决方法。您是否可以发布一些代码,说明如何启动processServices。由于许多原因,首先是安全性和健壮性,processServices无法交互。检查解决方法。你能发布一些代码来说明你是如何启动进程的吗?我建议使用该设置解决方案,但我也不喜欢它:/你听起来好像我不应该这样做,那么在远程机器上启动应用程序的替代方法是什么?顺便说一下,我使用的远程计算机是WindowsServer2008。如果我使用批处理文件启动应用程序,并通过web服务启动批处理文件,会怎么样?可能也不会工作,因为启动的进程将是不可见批处理文件的子进程!但事实上我并不知道这一点。我建议使用该设置解决方案,但我也不喜欢它:/听起来我不应该这样做,那么在远程机器上启动应用程序的替代方法是什么?顺便说一下,我使用的远程计算机是WindowsServer2008。如果我使用批处理文件启动应用程序,并通过web服务启动批处理文件,会怎么样?可能也不会工作,因为启动的进程将是不可见批处理文件的子进程!但事实上我并不知道这一点……啊,你几乎以同样的答案击败了我啊,你几乎以同样的答案击败了我即使我写了这段代码,它仍将作为一项服务工作,对我没有任何用处。我应该用别的策略。不。该代码将以当前登录会话中的用户身份执行应用程序。我已经尝试过该代码,但它也不起作用:/process start without any gui:/该服务需要作为LocalSystem运行。对不起,这不适合你。它适用于我tm。即使我写了这段代码,它仍将作为一项服务工作,对我来说没有任何用处。我应该用别的策略。不。该代码将以当前登录会话中的用户身份执行应用程序。我已经尝试过该代码,但它也不起作用:/process start without any gui:/该服务需要作为LocalSystem运行。对不起,这不适合你。它对我有用。