2013-07-05 31 views
0

我在IIS,Windows Server 2008 R2中使用具有NETWORK SERVICE Identity的AppPool .NET 4.0託管Wcf服務。WCF服務Process.Start在網絡服務帳戶下以不同用戶身份扮演

我的Wcf服務有一個使用Process.Start調用命令EXE的方法。

我需要使用不同的用戶作爲執行命令EXE(域用戶帳戶)的憑據。

我嘗試執行它,但它不適用於我:它似乎不執行命令EXE。

更新:過程退出,但不執行代碼

我得到這樣的錯誤:

退出代碼-1073741502

和EVENTVWR:

  Process Information: 
      Process ID:   0xc50 
      Process Name:  C:\DeployTools\DeployTools.Commands.Ejecutar.exe 
      Exit Status:   0xc0000142 

的參加辦法無法正確啓動(0xC0000142)。點擊確定 關閉應用程序

有什麼建議嗎?

代碼:

 StreamReader sr = null; 
     StreamReader serr = null; 

     try 
     { 
      var psi = new ProcessStartInfo(MY_COMMAND_EXE); 
      psi.WorkingDirectory = Path.GetDirectoryName(MY_COMMAND_EXE); 
      psi.Arguments = arguments; 
      psi.Domain = DOMAIN; 
      psi.UserName = USER_IN_DOMAIN; 
      psi.Password = SecureStringHelper.ToSecureString(pwd); 

      psi.LoadUserProfile = true; 
      psi.UseShellExecute = false; 

      psi.ErrorDialog = false; 
      psi.RedirectStandardOutput = true; 
      psi.RedirectStandardInput = true; 
      psi.RedirectStandardError = true; 
      psi.CreateNoWindow = true; 
      psi.WindowStyle = ProcessWindowStyle.Minimized; 

      using (Process pr = Process.Start(psi)) 
      { 
       sr = pr.StandardOutput; 
       serr = pr.StandardError; 

       if (!pr.HasExited) 
       { 
        pr.WaitForExit(300000); 
       } 
       output = pr.StandardOutput.ReadToEnd(); 
       errors = pr.StandardError.ReadToEnd(); 
       exitCode = pr.ExitCode; 

       return output; 
      } 
     } 
     catch (Exception exc) 
     { 
      return "EXCEPCIÓN: " + exc.Message; 
     } 
     finally 
     { 
      if (sr != null) 
      { 
       sr.Close(); 
       sr.Dispose(); 
       sr = null; 
      } 

      if (serr != null) 
      { 
       serr.Close(); 
       serr.Dispose(); 
       serr = null; 
      } 
     } 
+0

你可以檢查喲您的事件日誌大小,因爲退出代碼'1502'的最後4位數表示事件日誌/錯誤日誌文件已滿。如果這是您可以解決的問題 - http://www.howtogeek.com/howto/windows/fixing-the-event-log-is-full-error-on-windows-xp/ –

+0

這不是問題。我檢查事件日誌,是空的。每次測試前清除日誌。 – Kiquenet

+0

程序集'AsproLock'有一個很強的名字? 程序集生成失敗 - 引用程序集「AsproLock」沒有強名稱\t https://github.com/cloudfoundry-incubator/if_warden/tree/master/lib/AsproLock – Kiquenet

回答

2

我不得不以允許用戶帳戶來訪問正在運行的資源添加到AsproLock.dll參考和相關的代碼。

  //The following security adjustments are necessary to give the new 
      //process sufficient permission to run in the service's window station 
      //and desktop. This uses classes from the AsproLock library also from 
      //Asprosys. 
      IntPtr hWinSta = NativeMethods.GetProcessWindowStation(); 
      WindowStationSecurity ws = new WindowStationSecurity(hWinSta, 
       System.Security.AccessControl.AccessControlSections.Access); 
      ws.AddAccessRule(new WindowStationAccessRule(userPassDto.Usuario, 
       WindowStationRights.AllAccess, System.Security.AccessControl.AccessControlType.Allow)); 
      ws.AcceptChanges(); 

      IntPtr hDesk = NativeMethods.GetThreadDesktop(NativeMethods.GetCurrentThreadId()); 
      DesktopSecurity ds = new DesktopSecurity(hDesk, 
       System.Security.AccessControl.AccessControlSections.Access); 
      ds.AddAccessRule(new DesktopAccessRule(userPassDto.Usuario, 
       DesktopRights.AllAccess, System.Security.AccessControl.AccessControlType.Allow)); 
      ds.AcceptChanges(); 

[DllImport("user32.dll", SetLastError = true)] 
public static extern IntPtr GetProcessWindowStation(); 

[DllImport("user32.dll", SetLastError = true)] 
public static extern IntPtr GetThreadDesktop(int dwThreadId); 

[DllImport("kernel32.dll", SetLastError = true)] 
public static extern int GetCurrentThreadId(); 

的危險和Asprosys啓動在新建憑據過程

這不是一個普遍的需求,但它也並非罕見的陷阱,所以我想我最好張貼此一步一步指導如何解決啓動模擬憑證下的流程。這基於使用.Net Process類的Start方法,但它也適用於底層API調用:CreateProcessWithLogonW和CreateProcessWithTokenW。

訪問被拒絕 - 第一次嘗試和訪問被拒絕的異常立即關閉。這是最常見的初始問題,並且是由服務在LOCAL SYSTEM帳戶下運行引起的。奇怪的是,SYSTEM帳戶是計算機上功能最強大的帳戶,但它不能做的少數事情之一是使用CreateProcessWithLogonW啓動進程,這是調用Process.Start的基礎API。因此,將您的服務帳戶更改爲本地服務,無論如何它可能是更合適的帳戶。

再次拒絕訪問 - 我認爲我們解決了這個問題。糟糕,請仔細檢查您嘗試啓動的應用程序的權限。請記住,系統嘗試以應用程序文件的身份訪問應用程序文件,而不是服務帳戶。

無效的目錄錯誤 - 什麼?所有的路徑都是正確的。所有的目錄拼寫正確,沒有無效的字符。這是一個令人難以置信的煩人的錯誤,並不是非常一致。通常,當我們運行一個進程時,我們不打擾設置WorkingDirectory屬性,只接受來自父進程的缺省值。當使用新憑據啓動進程時,您不能這樣做,您必須爲WorkingDirectory明確設置路徑,否則您將得到「目錄名稱無效」。 Win32Exception。

失敗:沒有錯誤? - Process.Start很好地處理了新流程的Environment塊的創建。所以只有在使用底層API時,這是一個問題。在調用其中一個CreateProcess * API時,將lpEnvironment參數保留爲NULL是正常的,並讓系統使用從父進程複製塊的默認值。但是,在新憑據下啓動時,必須手動或使用CreateEnvironmentBlock顯式創建環境塊。更糟糕的是,如果你不這樣做,CreateProcess *調用將失敗,但GetLastError將返回ERROR_SUCCESS,並且如果創建環境塊時發生錯誤,那麼不會有錯誤,但該進程可能根本就不會運行。

應用程序未能正確初始化 - 沒有更多的例外,你已經解決了所有的問題,並且啓動了這個過程。再次糟糕,過程在哪裏?檢查事件日誌(或者您可能收到了應用程序錯誤彈出窗口)。應用程序錯誤應該有一個條目,表示您的進程是錯誤應用程序,或者user32.dll或kernel32.dll是錯誤模塊,並且異常爲:0xC0000142。這可能有一些小的變化,但基本上它是說你的應用程序無法初始化。原因是在初始化時,在運行任何應用程序代碼之前,所有進程都附加到Window Station,並且所有線程都連接到桌面,但是您正在啓動的用戶無權訪問Window Station和Desktop在其中你的進程正在啓動,但它不能初始化。 Window Station和Desktop的安全描述符必須進行調整,以允許進程在其下啓動的用戶獲得AllAccess權限。這是一個在.Net中直接做的惡魔,所以你可能會發現這裏的安全包裝類很有用。

沒有更多的錯誤 - 真的,沒有更多的錯誤,你的過程應該現在順利運行。根據用戶的身份(例如,管理員在某些情況下已經擁有正確的權限)或您正在啓動的會話類型,您需要做的事情可能會有所不同。但遵循這些步驟應該會讓您的生活順利和容易(也許不是你的整個生活)。

參考文獻:

The Perils and Pitfalls of Launching a Process Under New Credentials

Aspro Lock - Access Control

Code Samples

Creating New Process Under Alternate Credentials (createprocessasuser)

processstart-hangs