本文介绍了在网络服务帐户冒充WCF服务的Process.Start作为不同用户的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有WCF服务托管在IIS和Windows Server 2008 R2,使用的应用程序池的.NET 4.0与网络服务标识。



我的WCF服务具有调用一个方法使用的Process.Start的命令EXE。



我需要使用一个不同的用户,作为执行命令的EXE,一个域用户帐户凭据。



我试着执行它,但它不为我工作:好像没有执行命令EXE



更新:退出的过程,但不执行代码



我得到这样的错误:



退出代码-1073741502



和EVENTVWR:

 进程信息:
进程ID:0xc50
进程名称: C:\DeployTools\DeployTools.Commands.Ejecutar.exe
退出状态:0xc0000142





有什么建议?



代码:

  StreamReader的SR = NULL; 
StreamReader的SERR = NULL;


{
变种PSI =新的ProcessStartInfo(MY_COMMAND_EXE);
psi.WorkingDirectory = Path.GetDirectoryName(MY_COMMAND_EXE);
psi.Arguments =参数;
psi.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;使用(过程PR =的Process.Start(PSI))
{
SR = pr.StandardOutput

;
SERR = pr.StandardError;

如果(pr.HasExited!)
{
pr.WaitForExit(300000);
}
输出= pr.StandardOutput.ReadToEnd();
错误= pr.StandardError.ReadToEnd();
EXITCODE = pr.ExitCode;

返回输出;
}
}
赶上(例外EXC)
{
返回EXCEPCIÓN:+ exc.Message;
}
终于
{
如果(SR!= NULL)
{
sr.Close();
sr.Dispose();
SR = NULL;
}

如果(SERR!= NULL)
{
serr.Close();
serr.Dispose();
SERR = NULL;
}
}


解决方案

我不得不为了加入到参考,相关的代码允许用户帐户来访问正在运行的资源。

  //下面的安全调整是必要赋予新的
//过程足够的权限来在服务的窗口站
//和台式机上运行。它使用类从AsproLock库还从
// Asprosys。
IntPtr的hWinSta = NativeMethods.GetProcessWindowStation();
WindowStationSecurity WS =新WindowStationSecurity(hWinSta,
System.Security.AccessControl.AccessControlSections.Access);
ws.AddAccessRule(新WindowStationAccessRule(userPassDto.Usuario,
WindowStationRights.AllAccess,System.Security.AccessControl.AccessControlType.Allow));
ws.AcceptChanges();

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

函数[DllImport(user32.dll中,SetLastError = TRUE)]
公共静态外部的IntPtr GetProcessWindowStation();

函数[DllImport(user32.dll中,SetLastError = TRUE)]
公共静态外部的IntPtr GetThreadDesktop(INT dwThreadId);

函数[DllImport(KERNEL32.DLL,SetLastError = TRUE)]
公共静态外部INT GetCurrentThreadId();



的危险和Asprosys启动在新凭证的过程中陷阱



这是不是一个普遍的需求,但它也并不罕见,所以我想我最好寄这一步一步的指导,排查过程中下启动模拟凭据。这是基于使用.net Process类的启动方法,但它也可以适用于底层的API调用:CreateProcessWithLogonW和CreateProcessWithTokenW。



访问被拒绝 - 第一次尝试,并拒绝访问异常马上蝙蝠。这是最常见的首要问题,是由该服务在本地系统帐户下运行的事实造成的。奇怪的是,SYSTEM帐户是计算机,但的几件事情不能做一上最强大的帐户使用推出这CreateProcessWithLogonW是调用的Process.Start基础的API的过程。因此,改变你的服务帐户本地服务,它可能是更合适的帐户反正。



访问被拒绝再次 - AARGH,我认为我们解决了这个。哎呀,仔细检查你正在尝试启动应用程序的权限。请记住,系统试图访问应用程序文件作为该进程将被下运行的用户帐户,而不是服务帐户。



无效目录错误 - 什么?所有的路径是正确的。所有目录拼写是否正确,没有无效字符。这是一个令人难以置信的恼人的错误,也不是很一致的。通常,当我们运行过程中,我们也懒得设置工作目录属性,只是接受来自父进程的缺省值。当开始使用新的凭证,你不能这样做的过程,你必须明确地设定一个路径,工作目录,否则你会得到一个目录名称是无效的。 Win32Exception。



失败:否错误? - 处理的Process.Start为您新的进程环境块的创建相当不错。因此,这是唯一的,如果你使用的是底层API的一个问题。当调用CreateProcess的将* API中的一个是正常离开lpEnvironment参数为NULL,并让系统使用复制从父进程块的默认值。但在新的凭据启动时你必须明确,无论是手动或使用CreateEnvironmentBlock创造一个环境块。是什么让这个更糟糕的是,如果你离开了这一点,在CreateProcess的*调用将失败,但GetLastError函数将返回ERROR_SUCCESS,如果你做了错误创建环境块就没有错误,但这个过程可能只是无法运行。



应用程序未能正确初始化 - 没有更多的异常,你已经解决了所有的问题,这个过程已经启动。哎呀再次,在哪里处理?检查事件日志(或者您可能会收到应用程序错误弹出)。应该有应用程序错误的条目,说你的程序是错误应用程序,无论是user32.dll中或kernel32.dll中是错误模块和例外是:0xC0000142。有可能在这一些小的变化,但基本上它是说,你的应用程序无法初始化。这样做的原因是,在初始化,运行任何应用程序代码之前,所有进程都连接到一个窗口站和所有线程都连接到桌面,但你在启动用户没有权限访问该窗口站和桌面在你的进程正在启动,ERGO就不能初始化。为窗口站和桌面的安全描述符必须调整以得到AllAccess权限的过程被下发起的用户。这是一个魔鬼直接在净做,所以你可能在这里找到有用的安全包装类。



没有更多的错误 - 说真的,没有更多的错误,你的过程中应平稳正在运行。有可能是你需要根据用户是谁做的一些变化(例如管理员将已经在某些情况下,正确的权限),或者你正在推出什么样的会议。但是以下步骤应该让您的生活顺利和容易(也许不是你的整个生活)。



参考文献:





的陷阱








I have Wcf Service hosted in IIS, Windows Server 2008 R2, using an AppPool .NET 4.0 with NETWORK SERVICE Identity.

My Wcf Service has a method that calls an command EXE using Process.Start.

I need use an different user as credentials for execute command EXE, an domain user account.

I try execute it but it doesn't works for me: it seems not execute the command EXE.

update: process exited, but not execute code

I get errors like:

exit code -1073741502

and eventvwr:

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

Any suggestions?

Code:

        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;
            }
        }
解决方案

I had to add a reference to AsproLock.dll and associated code in order to permit the user account to have access to the running resource.

            //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();

The Perils and Pitfalls of Launching a Process Under New Credentials by Asprosys

This isn't a common need but it also isn't that rare, so I thought I had better post this step by step guide to troubleshooting the launching of a process under impersonated credentials. This is based on using the Start method of the .Net Process class but it is also applicable to the underlying API calls: CreateProcessWithLogonW and CreateProcessWithTokenW.

Access Denied - The first attempt and an access denied exception right off the bat. This is the most common initial problem and is caused by the fact that the service is running under the LOCAL SYSTEM account. Strangely, the SYSTEM account is the most powerful account on the computer but one of the few things it cannot do is launch a process using CreateProcessWithLogonW which is the API underlying the call to Process.Start. So change your service account to Local Service, it's probably the more appropriate account anyway.

Access Denied Again - Aargh, I thought we solved this. Oops, double check the permissions on the application that you are trying to launch. Remember that the system tries to access the application file as the user account that the process will be running under, not the service account.

Invalid Directory Error - What? All the paths are correct. All the directories are spelled correctly, no invalid characters. This is an incredibly annoying error and is not very consistent. Usually when we run a process we don't bother setting the WorkingDirectory property and just accept the default from the parent process. When starting a process with new credentials you can't do that, you must explicitly set a path for the WorkingDirectory or you'll get a "The directory name is invalid." Win32Exception.

Failure: No Error? - Process.Start handles the creation of the Environment block for the new process for you quite well. So this is a problem only if you are using the underlying API. When calling one of the CreateProcess* APIs it is normal to leave the lpEnvironment parameter as NULL and have the system use the default of copying the block from the parent process. But when launching under new credentials you must create an environment block explicitly, either manually or using CreateEnvironmentBlock. What makes this worse is, if you leave this out the CreateProcess* call will fail but GetLastError will return ERROR_SUCCESS and if you make an error creating your environment block there will be no error but the process may just not run at all.

Application Failed to Initialize Properly - No more exceptions, you've solved all the problems and the process has been launched. Oops again, where is the process? Check the event log (or you may have received an Application Error pop-up). There should be an entry for Application Error that says that your process was the faulting application, either user32.dll or kernel32.dll was the faulting module and the exception was: 0xC0000142. There may be some minor variation in this but basically it is saying that your application could not initialize. The reason for this is that on initialization, before any application code is run, all processes are attached to a Window Station and all threads are attached to a Desktop but the user you are launching under does not have permission to access the Window Station and Desktop in which your process is being launched, ergo it can't initialize. The security descriptors for the Window Station and Desktop must be adjusted to give AllAccess permission to the user the process is being launched under. This is a devil to do directly in .Net, so you might find the security wrapper classes here useful.

No More Errors - Really, no more errors, your process should be running smoothly now. There may be some variations in what you need to do based on who the user is (for instance an administrator will already have the correct permissions in some cases) or what kind of session you are launching in. But following these steps should make your life smooth and easy (well maybe not your whole life).

References:

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

这篇关于在网络服务帐户冒充WCF服务的Process.Start作为不同用户的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-22 23:11