ASP.NET网站启动进程出现访问被拒绝的错误

5

我有一个ASP.NET MVC4网站,我正在尝试在服务器上执行一个进程。 代码如下:

ProcessStartInfo startInfo = new ProcessStartInfo()
{
    FileName = ExeLocation,
    Arguments = string.Format("\"{0}\"{1}", ScriptLocation, Arguments),
    UseShellExecute = false,
    RedirectStandardOutput = true,
    RedirectStandardError = true,
    WorkingDirectory = AppDir,
    CreateNoWindow = true,
    UserName = ExeUsername,
    Password = ExePassword,
    Domain = ExeDomain
};

using (Process process = Process.Start(startInfo))
{
    using (StreamReader reader = process.StandardOutput)
    {
        output = reader.ReadToEnd();
    }
    using (StreamReader reader = process.StandardError)
    {
        error = reader.ReadToEnd();
    }
    process.WaitForExit();
    if (process.ExitCode != 0)
    {
        throw new Exception(string.IsNullOrEmpty(output) ? error : output);
    }
}

在我的本地机器上使用Visual Studio很好,但是当我部署到我的服务器(W2K12)时,会出现以下错误:

Access is denied   
at System.Diagnostics.Process.StartWithCreateProcess(ProcessStartInfo startInfo)

我在服务器上的AdministratorsIIS_IUSRS组中都有被引用为ExeUsername的帐户。
应用程序池正在以不同的帐户运行(因此需要分配特定帐户来运行该进程),该帐户也是服务器上的管理员和IIS_IUSRS的成员。
当我以ExeUsername身份登录服务器并运行命令提示符时,我能够执行该进程,因此问题必须与从IIS执行有关。
还有什么可能阻止此访问?

可能的答案在这里:https://dev59.com/Y2gu5IYBdhLWcg3wGjdF - Brendan Green
1
你的应用程序池身份是否有访问“ExeLocation”的权限? - kapsiR
另一种方法是将权限授予内置组IIS_IUSERS以访问您想要访问的文件夹。这将给所有默认应用程序池访问权限,因此请考虑您的使用情况。 - ste-fu
@kapsiR 应用程序池的身份验证也在 Administrators 和 IIS_IUSRS 中。 - Paul
1
@Paul 是的,但是这个身份有访问可执行文件的权限并且有执行该进程的权限吗?请看这个问题/答案 - kapsiR
3个回答

1
  1. 右键单击应用程序池
  2. 单击“高级设置”
  3. 身份验证
  4. 自定义帐户
  5. 设置用户名和密码

如果您有域,请注意使用domain\username作为用户名,并确保可以访问部署文件夹。


1
我认为这几乎回答了问题,但与评论中链接的已接受答案没有任何区别。 - ste-fu
我已经将应用程序池运行在自定义帐户下。但是该进程需要以不同的帐户运行。这就是为什么我正在为该进程设置特定的用户名和密码。 - Paul

0

也许使用这个可以帮助你。

ProcessStartInfo startInfo = new ProcessStartInfo()
{
   //...
   UseShellExecute = true,                
   Verb = "runas"
};

如果出现错误,您也可以检查this


0
我会尝试不同的方法。首先模拟一个自定义用户(具有运行命令权限的用户),然后在模拟用户的上下文中启动进程:
SafeAccessTokenHandle safeAccessTokenHandle;  
bool returnValue = LogonUser(ExeUsername, ExeDomain, ExePassword,  
        LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,  
        out safeAccessTokenHandle);

if (false == returnValue)  
{  
    int ret = Marshal.GetLastWin32Error();  
    throw new System.ComponentModel.Win32Exception(ret);  
}  

WindowsIdentity.RunImpersonated(safeAccessTokenHandle, () =>  
{  
     var startInfo = new ProcessStartInfo()
     {
         FileName = ExeLocation,
         Arguments = string.Format("\"{0}\"{1}", ScriptLocation, Arguments),
         UseShellExecute = false,
         RedirectStandardOutput = true,
         RedirectStandardError = true,
         WorkingDirectory = AppDir,
         CreateNoWindow = true,
         UserName = ExeUsername,
         Password = ExePassword,
         Domain = ExeDomain
     };

     using (Process process = Process.Start(startInfo))
     {
         using (StreamReader reader = process.StandardOutput)
         {
             output = reader.ReadToEnd();
         }

         using (StreamReader reader = process.StandardError)
         {
             error = reader.ReadToEnd();
         }

         process.WaitForExit();
         if (process.ExitCode != 0)
         {
             throw new Exception(string.IsNullOrEmpty(output) ? error : output);
         }
     } 
);  

而 LogonUser 方法看起来像这样:

[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]  
public static extern bool LogonUser(String lpszUsername, String lpszDomain, 
String lpszPassword, int dwLogonType, int dwLogonProvider, 
out SafeAccessTokenHandle phToken);

在 .NET 中有关模拟的更多信息,请参见此处:https://learn.microsoft.com/en-gb/dotnet/api/system.security.principal.windowsidentity.runimpersonated?view=netframework-4.7.2


我尝试了类似的方法,但仍然没有成功。exe文件仍然以应用程序池标识运行。我的代码是在.NET 4.0中编写的:https://learn.microsoft.com/en-us/dotnet/api/system.security.principal.windowsimpersonationcontext?redirectedfrom=MSDN&view=netframework-4.0 - Paul
所以模拟身份已经可以工作,但是当您在模拟用户的上下文中调用Process.Start时,应用程序仍会抛出访问被拒绝的错误?您可以将池的临时标识更改为本地系统并查看是否仍存在错误。 - Lesmian
如果我将AppPool运行为LocalSystem,当提供用户名/密码给Process.Start时,仍然会出现访问被拒绝的错误。如果我从Process.Start中删除用户名/密码,则可以成功运行,但是作为AppPool帐户。我的目标是在指定帐户下运行进程,而我的AppPool则以不同的帐户运行(由于环境的另一个要求)。 - Paul
2
好的,你可以再试一件事情...创建一个简单的控制台应用程序,只包含你在问题中发布的代码(ProcessStartInfo with ExeUsername),并尝试在服务器上运行它。它能正常工作吗? - Lesmian
我在服务器上使用AppPool帐户运行控制台应用程序,并使用原始代码,没有出现错误。因此,这似乎与应用程序在启用ASP.NET模拟的IIS下运行的方式有关。 - Paul

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接