簡體   English   中英

WCF服務Process.Start在網絡服務帳戶下模擬為不同的用戶

[英]WCF service Process.Start under network service account impersonating as a different user

我使用帶有NETWORK SERVICE Identity的AppPool .NET 4.0在IIS,Windows Server 2008 R2中托管了Wcf服務。

我的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;
            }
        }

我必須添加對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。 因此,將您的服務帳戶更改為本地服務,無論如何,它可能是更合適的帳戶。

再次拒絕訪問 - Aargh,我以為我們解決了這個問題。 糟糕,請仔細檢查您嘗試啟動的應用程序的權限。 請記住,系統嘗試訪問應用程序文件作為將在其下運行進程的用戶帳戶,而不是服務帳戶。

目錄錯誤無效 - 什么? 所有路徑都是正確的。 所有目錄拼寫正確,沒有無效字符。 這是一個令人難以置信的惱人錯誤,並不是很一致。 通常當我們運行一個進程時,我們不打擾設置WorkingDirectory屬性,只接受父進程的默認值。 使用新憑據啟動進程時,您無法執行此操作,您必須顯式設置WorkingDirectory的路徑,否則您將獲得“目錄名無效”。 Win32Exception。

失敗 :沒有錯誤? - Process.Start可以很好地為新進程處理環境塊的創建。 所以只有在使用底層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中做的惡魔,所以你可能會發現這里的安全包裝類非常有用。

沒有更多的錯誤 - 真的,沒有更多的錯誤,你的過程現在應該順利運行。 根據用戶的身份(例如,管理員在某些情況下已經擁有正確的權限)或者您要啟動的會話類型,您可能需要做些什么變化。但是按照這些步驟應該讓您的生活變得更好順利而輕松(也許不是你的整個生命)。

參考文獻:

在新證書下啟動流程的危險和陷阱

Aspro Lock - 訪問控制

代碼示例

在備用憑據下創建新流程(createprocessasuser)

processstart-掛起

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM