近日因工作需要,要在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 workstationand desktop, and at the same time aspnet_wp.exe which is run under a/c ASPNET must have privilege to access the current interativelogon 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 fileSpawnProcess.defLIBRARY SpawnProcessEXPORTSSpawnProcessInNTDesktop @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'tforget 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.exeBest Regards,Hun Boon Teo,16/07/200201:03PM (GMT+0800)----- Original Message -----From: "prashanth g" <prashag@YAHOO.COM>To: <ADVANCED-DOTNET@DISCUSS.DEVELOP.COM>Sent: Monday, July 15, 2002 7:02 AMSubject: [ADVANCED-DOTNET] Start Process in ASP.NetQuotation: