问题描述
我在64位计算机上有一个ASP .NET Web应用程序,需要运行旧的32位报表应用程序。
I have an ASP .NET web application on a 64-bit machine that needs to run a legacy 32-bit reporting application.
UseShellExecute = false
,程序退出并退出代码:
When I run the program with UseShellExecute = false
, the program exits with exit code:
-1073741502
我不能使用Shell Execute,因为我必须以其他用户身份运行该进程。但是,当Shell Execute为true时,该过程将运行正常(尽管我必须更改正在执行ASP .NET的用户)。
I can't use Shell Execute because I have to run the process as a different user. Yet, when Shell Execute is true, the process will run fine (although I have to change the user that ASP .NET is executing under).
如何启动此功能
这是我现在拥有的代码:
Here's the code I have right now:
var pxs = new ProcessStartInfo
{
Arguments = arguments,
CreateNoWindow = true,
Domain = ConfigurationManager.AppSettings["reportUserDomain"],
UserName = ConfigurationManager.AppSettings["reportUserName"],
Password = GetSecureString(ConfigurationManager.AppSettings["reportUserPassword"]),
LoadUserProfile = true,
FileName = ConfigurationManager.AppSettings["reportRuntime"],
UseShellExecute = false
};
var px = new Process
{
StartInfo = pxs
};
px.Start();
px.WaitForExit();
推荐答案
如果包围了代码,包括 UseShellExecute = true
,使用Windows本机 LogonUser方法?我已经在一些项目中成功地使用了它来做 like 。
What if you surrounded your code, including UseShellExecute = true
, with the windows native "LogonUser" method? I've used this successfully in a few projects to do something similar.
[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
public static extern bool LogonUser(String lpszUserName, String lpszDomain,
String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken
Fresh Click Media对此做了一篇文章,并编写了一个示例的Impersonate类:->
Fresh Click Media did an article about this and wrote a sample Impersonate class: --> http://www.freshclickmedia.com/blog/2008/11/programmatic-impersonation-in-c/
但是为了完整起见,这是我的版本:
But for completeness, here's my version of it:
public class Impersonator : IDisposable
{
private WindowsImpersonationContext _impersonatedUser = null;
private IntPtr _userHandle;
// constructor for a local account. username and password are arguments.
public Impersonator(string username, string passwd)
{
_userHandle = new IntPtr(0);
string user = username;
string userDomain = "."; // The domain for a local user is by default "."
string password = passwd;
bool returnValue = LogonUser(user, userDomain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref _userHandle);
if (!returnValue)
throw new ApplicationException("Could not impersonate user");
WindowsIdentity newId = new WindowsIdentity(_userHandle);
_impersonatedUser = newId.Impersonate();
}
// constructor where username, password and domain are passed as parameters
public Impersonator(string username, string passwd, string domain)
{
_userHandle = new IntPtr(0);
string user = username;
string userDomain = domain;
string password = passwd;
bool returnValue = LogonUser(user, userDomain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref _userHandle);
if (!returnValue)
throw new ApplicationException("Could not impersonate user");
WindowsIdentity newId = new WindowsIdentity(_userHandle);
_impersonatedUser = newId.Impersonate();
}
public void Dispose()
{
if (_impersonatedUser != null)
{
_impersonatedUser.Undo();
CloseHandle(_userHandle);
}
}
public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_LOGON_SERVICE = 3;
public const int LOGON32_PROVIDER_DEFAULT = 0;
[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
public static extern bool LogonUser(String lpszUserName, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public extern static bool CloseHandle(IntPtr handle);
}
在您的情况下使用的是:
Using it in your case would be:
var domain = ConfigurationManager.AppSettings["reportUserDomain"];
var username = ConfigurationManager.AppSettings["reportUserName"];
var password = ConfigurationManager.AppSettings["reportUserPassword"];
using (Impersonator impersonator = new Impersonator(username, password, domain))
{
var pxs = new ProcessStartInfo
{
Arguments = arguments,
CreateNoWindow = true,
LoadUserProfile = true,
FileName = ConfigurationManager.AppSettings["reportRuntime"],
UseShellExecute = true
};
var px = new Process
{
StartInfo = pxs
};
px.Start();
px.WaitForExit();
}
这篇关于如何在不使用Shell在64位计算机上执行的情况下在C#中启动32位进程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!