文章編號: 889251 - 上次校閱: 2005年6月2日 - 版次: 4.6

如何在 Microsoft ASP.NET 網頁中模擬的使用者內容下執行的處理序繁衍 (Spawn)

系統提示本文適用於您使用的作業系統之外的作業系統。與您不相關的文章內容已停用。

在此頁中

全部展開 | 全部摺疊

簡介

本文將逐步告訴您,如何在 Microsoft ASP.NET 網頁中模擬的使用者內容下執行的處理序繁衍 (Spawn)。若要模擬的使用者內容下執行的處理序繁衍 (Spawn),您不能使用 System.Diagnostics.Process.Start 方法。這是因為在執行緒層級,而不在程序層級,模擬執行 ASP.NET 中。因此,ASP.NET 背景工作處理序內容下並不在模擬的內容下,會執行任何從 ASP.NET 繁衍 (Spawn) 的處理序。

該技巧的描述

若要解決這個問題,您必須讓平台叫用 (P/Invoke) 呼叫至下列 Win32 API:
  • CreateProcessAsUser 函式會建立安全性語彙基元中的其中一個參數所指定的識別下一個程序。但是,對 CreateProcessAsUser 函式呼叫需要主要權杖。因此,您必須將模擬語彙基元 (Token) 轉換為主要權杖。
  • DuplicateTokenEx 函式會將模擬語彙基元轉換成主要權杖。CreateProcessAsUser 函式呼叫使用此主要權杖。
附註為工作 CreateProcessAsUser 函式呼叫,下列安全性使用者權限必須被指派到模擬的使用者:
  • 正在執行 Microsoft Windows 2000 電腦上指派 [取代處理程序等級的權杖] 使用者權限及 [增加配額 使用者權限,才能模擬的使用者]。
  • 將正在執行 Microsoft Windows Server 2003 或 Microsoft Windows XP 電腦上 [取代處理程序等級的權杖 使用者權利指派給模擬使用者。

繁衍處理序的步驟

Microsoft 僅,為了說明提供程式設計範例,不提供任何明示或默示的保證。這包括,但不限於適售性或適合某特定用途之默示擔保責任。本文假設您已熟悉使用我們所示範的程式設計語言以及建立和偵錯程序所使用的工具。Microsoft 技術支援工程師可以協助解釋特定程序的功能,但它們不會修改這些範例以提供附加功能或建構程序,以符合您特定需求。若要模擬的使用者內容下執行的處理序繁衍 (Spawn),請依照下列步驟執行:
  1. 在 Microsoft Visual Studio.NET 2003,建立新的 Visual C# ASP.NET Web 應用程式,並命名應用程式 Q889251。
  2. 在程式碼檢視中開啟的 WebForm1.aspx 檔案。
  3. WebForm1.aspx] 檔案中加入 使用 的程式碼區塊中的下列陳述式。
    using System.Runtime.InteropServices;
    using System.Security.Principal;
    
  4. 找出看起來類似下行程式碼的程式碼行。
    public class WebForm1 :  System.Web.UI.Page
  5. 步驟 4 中所識別的程式碼行後, 加入下列程式碼。
    	
    		[StructLayout(LayoutKind.Sequential)] public struct STARTUPINFO
    		{
    			public int cb;
    			public String lpReserved;
    			public String lpDesktop;
    			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 short wShowWindow;
    			public short 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;
    		}
    
    		[StructLayout(LayoutKind.Sequential)] public struct SECURITY_ATTRIBUTES
    		{
    			public int    Length;
    			public IntPtr lpSecurityDescriptor;
    			public bool   bInheritHandle;
    		}
    
    		[DllImport("kernel32.dll", EntryPoint="CloseHandle", SetLastError=true, CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
    		public extern static bool CloseHandle(IntPtr handle);
    
    		[DllImport("advapi32.dll", EntryPoint="CreateProcessAsUser", SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
    		public extern static bool CreateProcessAsUser(IntPtr hToken, String lpApplicationName, String lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes, 
    			ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandle, int dwCreationFlags, IntPtr lpEnvironment,
    			String lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
    
    		[DllImport("advapi32.dll", EntryPoint="DuplicateTokenEx")]
    		public extern static bool DuplicateTokenEx(IntPtr ExistingTokenHandle, uint dwDesiredAccess, 
    			ref SECURITY_ATTRIBUTES lpThreadAttributes, int TokenType,
    			int ImpersonationLevel, ref IntPtr DuplicateTokenHandle);
    
    
  6. 在 [方案總管] 中 WebForm1.aspx 上, 按一下滑鼠右鍵,然後按一下 [開啟舊檔]。Web 表單會在 [設計] 檢視中開啟。
  7. 按一下 [檢視] 功能表 HTML 原始檔
  8. 在 [HTML 原始碼] 視窗中所有現有的程式碼取代下列程式碼。
    <%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="Q889251.WebForm1" %>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
    <HTML>
    	<HEAD>
    		<title>WebForm1</title>
    		<meta name="GENERATOR" Content="Microsoft Visual Studio 7.0">
    		<meta name="CODE_LANGUAGE" Content="C#">
    		<meta name="vs_defaultClientScript" content="JavaScript">
    		<meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
    	</HEAD>
    	<body>
    		<form id="Form1" method="post" runat="server">
    			<P>&nbsp;</P>
    			<P>Enter Path of process to be run (with relevant parameters)
    				<asp:TextBox id="TextBox1" runat="server"></asp:TextBox></P>
    			<P>
    				<asp:Button id="Button1" runat="server" Text="CreateProcess"></asp:Button>
    			</P>
    			<P>
    				<asp:Label id="Label1" runat="server">Status:</asp:Label></P>
    			<P>
    				<asp:Label id="Label2" runat="server">Impersonated Identity:</asp:Label></P>
    		</form>
    	</body>
    </HTML>
    
  9. 按一下 [檢視] 功能表 設計
  10. 連按兩下 CreateProcessButton1_Click 方法插入程式碼,而且程式碼就會顯示在 [內容] 窗格中。
  11. 下列程式碼取代現有的 Button1_Click 方法。
    		private void Button1_Click(object sender, System.EventArgs e)
    		{
    			IntPtr Token = new IntPtr(0);
    			IntPtr DupedToken = new IntPtr(0);
    			bool      ret;
    			Label2.Text+=WindowsIdentity.GetCurrent().Name.ToString();
    			
    
    			SECURITY_ATTRIBUTES sa  = new SECURITY_ATTRIBUTES();
    			sa.bInheritHandle       = false;
    			sa.Length               = Marshal.SizeOf(sa);
    			sa.lpSecurityDescriptor = (IntPtr)0;
    			
    			Token = WindowsIdentity.GetCurrent().Token;
    
    			const uint GENERIC_ALL = 0x10000000;
    
    			const int SecurityImpersonation = 2;
    			const int TokenType = 1;
    
    			ret = DuplicateTokenEx(Token, GENERIC_ALL, ref sa, SecurityImpersonation, TokenType, ref DupedToken);
    			
    			if (ret == false)
    				Label1.Text +="DuplicateTokenEx failed with " + Marshal.GetLastWin32Error();
    				
    			else
    				Label1.Text+= "DuplicateTokenEx SUCCESS";
    
    			STARTUPINFO si          = new STARTUPINFO();
    			si.cb                   = Marshal.SizeOf(si);
    			si.lpDesktop            = "";
    			
    			string commandLinePath;
    			commandLinePath = TextBox1.Text;
    
    			PROCESS_INFORMATION pi  = new PROCESS_INFORMATION();
    			ret = CreateProcessAsUser(DupedToken,null,commandLinePath, ref sa, ref sa, false, 0, (IntPtr)0, "c:\\", ref si, out pi);
    			
    			if (ret == false)
    				Label1.Text +="CreateProcessAsUser failed with " + Marshal.GetLastWin32Error();
    			else
    			{
    				Label1.Text +="CreateProcessAsUser SUCCESS.  The child PID is" + pi.dwProcessId;
    
    				CloseHandle(pi.hProcess);
    				CloseHandle(pi.hThread);
    			}
    
    			ret = CloseHandle(DupedToken);
    			if (ret == false)
    				Label1.Text+=Marshal.GetLastWin32Error();
    			else
    				Label1.Text+="CloseHandle SUCCESS";
    		}
    
  12. 在 [建置] 功能表上按一下 [建置方案]。
  13. 在 [偵錯] 功能表上按一下 [開始]。
  14. 在 WebForm1] 頁面中輸入您想要啟動的處理程序的路徑。例如,輸入 SystemDriver \Windows\Notepad.exe
  15. 按一下 CreateProcess

?考

如需詳細資訊,請按一下下列的文件編號,檢視 「 Microsoft 知識庫 」 中的文件:
306158? (http://support.microsoft.com/kb/306158/ ) 如何在 ASP.NET 應用程式中實作模擬
321748? (http://support.microsoft.com/kb/321748/ ) 如何建立本機 Web 伺服器 ASP.NET 應用程式
842790? (http://support.microsoft.com/kb/842790/ ) 當您嘗試模擬從次要執行緒在 ASP.NET Web 應用程式中的使用者時,就會發生 System.Security.SecurityException 例外狀況

這篇文章中的資訊適用於:
  • Microsoft ASP.NET 1.1
  • Microsoft ASP.NET 1.0
  • Microsoft .NET Framework 2.0
關鍵字:?
kbmt kbhowtomaster kbinfo KB889251 KbMtzh
機器翻譯機器翻譯
重要:本文是以 Microsoft 機器翻譯軟體翻譯而成,而非使用人工翻譯而成。Microsoft 同時提供使用者人工翻譯及機器翻譯兩個版本的文章,讓使用者可以依其使用語言使用知識庫中的所有文章。但是,機器翻譯的文章可能不盡完美。這些文章中也可能出現拼字、語意或文法上的錯誤,就像外國人在使用本國語言時可能發生的錯誤。Microsoft 不為內容的翻譯錯誤或客戶對該內容的使用所產生的任何錯誤或損害負責。Microsoft也同時將不斷地就機器翻譯軟體進行更新。
按一下這裡查看此文章的英文版本:889251? (http://support.microsoft.com/kb/889251/en-us/ )
Microsoft及(或)其供應商不就任何在本伺服器上發表的文字資料及其相關圖表資訊的恰當性作任何承諾。所有文字資料及其相關圖表均以「現狀」供應,不負任何擔保責任。Microsoft及(或)其供應商謹此聲明,不負任何對與此資訊有關之擔保責任,包括關於適售性、適用於某一特定用途、權利或不侵權的明示或默示擔保責任。Microsoft及(或)其供應商無論如何不對因或與使用本伺服器上資訊或與資訊的實行有關而引起的契約、過失或其他侵權行為之訴訟中的特別的、間接的、衍生性的損害或任何因使用而喪失所導致的之損害、資料或利潤負任何責任。