近日因工作需要,要在NT 服务中启动一个进程,因为Service属于System用户,直接调用CreateProcess产生的进程是用户见不到的。以下文章给出了一个解决方法。
The reason that you don't see it in the desktop is because the process created under aspnet_wp.exe has its own Workstation and Desktop under NT/W2K/XP.
In order to bring the process the current visible workstation and desktop, you have to open the current interative logon workstation
and desktop, and at the same time aspnet_wp.exe which is run under a/c ASPNET must have privilege to access the current interative
logon user desktop because you are trying to create in a different user desktop (from ASPNET --> the current logon user desktop).
I did not find an API in the current .NET classes ,(System.Diagnostics.ProcessStartupInfo, Process etc) that allow you to do that.
You have to resort to the Win32 API to do it.
I have the following and find it to be working.
Compile the following C file into a SpawnProcess.dll with the SpawnProcess.def module definition file
SpawnProcess.def
LIBRARY SpawnProcess
EXPORTS
SpawnProcessInNTDesktop @1
// SpawnProcess.cpp : Defines the entry point for the DLL application.
//
//#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
#include <process.h>
#include <rpcdce.h>
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
BOOL APIENTRY SpawnProcessInNTDesktop(LPSTR exeName,LPSTR parameters,LPSTR currDirectory)
{
DWORD dwThreadId;
HWINSTA hwinstaSave;
HDESK hdeskSave;
HWINSTA hwinstaUser;
HDESK hdeskUser;
RPC_BINDING_HANDLE h = NULL;
char buffer[256];
char desktopName[80];
STARTUPINFO startInfo;
PROCESS_INFORMATION processInfo;
// Ensure connection to service window station and desktop, and
// save their handles.
hwinstaSave = GetProcessWindowStation();
dwThreadId = GetCurrentThreadId();
hdeskSave = GetThreadDesktop(dwThreadId);
// Impersonate the client and connect to the User's
// window station and desktop.
RpcImpersonateClient(h);
hwinstaUser = OpenWindowStation("WinSta0", TRUE, MAXIMUM_ALLOWED);
if (hwinstaUser == NULL)
{
RpcRevertToSelf();
return 0;
}
SetProcessWindowStation(hwinstaUser);
hdeskUser = OpenDesktop("Default", 0, TRUE, MAXIMUM_ALLOWED);
RpcRevertToSelf();
if (hdeskUser == NULL)
{
SetProcessWindowStation(hwinstaSave);
CloseWindowStation(hwinstaUser);
return 0;
}
SetThreadDesktop(hdeskUser);
//Use CreateProcess to spawn process
//
lstrcpy(desktopName,"WinSta0\\Default");
memset(&startInfo,0,sizeof startInfo);
startInfo.cb = sizeof startInfo;
startInfo.lpDesktop = desktopName;
wsprintf(buffer,"%s %s",exeName, parameters);
if(!CreateProcess(NULL,
buffer,
NULL,
NULL,
TRUE,
CREATE_NO_WINDOW|CREATE_DEFAULT_ERROR_MODE|NORMAL_PRIORITY_CLASS,
NULL,
currDirectory,
&startInfo,
&processInfo))
{
LPVOID lpMsgBuf;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL );
LocalFree( lpMsgBuf );
return 0;
}
//
SetThreadDesktop(hdeskSave);
SetProcessWindowStation(hwinstaSave);
CloseDesktop(hdeskUser);
CloseWindowStation(hwinstaUser);
return TRUE;
}
compile the following Spawn1.cs into an assembly:
using System;
using System.Reflection;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
namespace Spawn
{
public class SwitchWorkStationToDefault
{
[DllImport("SpawnProcess.dll")]
static extern bool SpawnProcessInNTDesktop(String exeName,String parameters,String currDirectory) ;
public static void SpawnWithout(String exeName)
{
try
{
Process.Start(exeName);
}
catch(Exception ex)
{
// dump exception to somewhere
}
}
public static void SpawnIntoDesktop(String exeName,String parameters,String currDirectory)
{
SpawnProcessInNTDesktop(exeName,parameters,currDirectory);
}
public static void Main(String[] args)
{
//if(args.Length <= 0)
// return;
//Console.WriteLine("Running {0}",args[0]);
SpawnWithout("calc.exe");
SpawnIntoDesktop("notepad.exe", "",".\\");
}
}
}
Create this test.aspx at your IIS root directory , and remember to copy Spawn1.exe and SpawnProcess.dll into bin directory and don't
forget to raise the privilege of ASPNET account (for instance Administrator though this is extremely dangerous) for this to work.
<%@Page Language="C#" Trace="false" %>
<%@ Assembly Name="Spawn1" %>
<%@ Import Namespace="Spawn" %>
<html>
<script language="C#" runat="server">
void Page_Load(Object sender, EventArgs E) {
Spawn.SwitchWorkStationToDefault.SpawnWithout("calc.exe");
Spawn.SwitchWorkStationToDefault.SpawnIntoDesktop("notepad.exe", "",".\\");
}
</script>
<title>Test page </title>
<body>
this is nothing
</body>
</html>
You should see that notepad appears on the desktop but not calc.exe
Best Regards,
Hun Boon Teo,
16/07/2002
01:03PM (GMT+0800)
----- Original Message -----
From: "prashanth g" <prashag@YAHOO.COM>
To: <ADVANCED-DOTNET@DISCUSS.DEVELOP.COM>
Sent: Monday, July 15, 2002 7:02 AM
Subject: [ADVANCED-DOTNET] Start Process in ASP.Net
Quotation:
> Hi, > I have an ASP.Net Application. From this application I need to start > a process which will run a Visual Test File (Something like a Setup > File with some UI). When I run this, the processes are getting > created, but the UI does not appear. I am not sure if the UI will come > or not but the newly created process(processes are created, I can see > in Task Manager) looks like does nothing. > > But if I start the same process with a Windows Application the Wizard > kicks off. > Since the process is created newly I assume whether Windows App or Web > App should not matter as it is a new process. > > I also tried by putting the Create Process Class in COM+ and run as > server. It works fine with Win App but not with Web App. > > Can somebody tell me if this is possible or if I am missing something. > > I apologize for putting this in IIS group also. I just thought may be > some IIS funda is also there. > > Any help, pointers.. will be highly appreciated. > > Thanks > PrashanthG > > > __________________________________________________ > Do You Yahoo!? > Yahoo! Autos - Get free new car price quotes > http://autos.yahoo.com > > You can read messages from the Advanced DOTNET archive, unsubscribe from Advanced DOTNET, or > subscribe to other DevelopMentor lists at http://discuss.develop.com. > You can read messages from the Advanced DOTNET archive, unsubscribe from Advanced DOTNET, or |
|