如何在C#中启动32位进程而不在64位机器上使用shell execute?
我在64位计算机上有一个ASP.NET web应用程序,它需要运行一个旧的32位报告应用程序 当我使用如何在C#中启动32位进程而不在64位机器上使用shell execute?,c#,32bit-64bit,startprocessinfo,start-process,C#,32bit 64bit,Startprocessinfo,Start Process,我在64位计算机上有一个ASP.NET web应用程序,它需要运行一个旧的32位报告应用程序 当我使用UseShellExecute=false运行程序时,程序将使用退出代码退出: -1073741502 我不能使用Shell Execute,因为我必须以其他用户的身份运行该进程。然而,当Shell Execute为true时,进程将正常运行(尽管我必须更改ASP.NET正在执行的用户) 如何使用C#启动此32位程序而不使用shell execute 以下是我现在掌握的代码: var pxs =
UseShellExecute=false运行程序时,程序将使用退出代码退出:
-1073741502
我不能使用Shell Execute,因为我必须以其他用户的身份运行该进程。然而,当Shell Execute为true时,进程将正常运行(尽管我必须更改ASP.NET正在执行的用户)
如何使用C#启动此32位程序而不使用shell execute
以下是我现在掌握的代码:
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();
如果使用windows本机的“LogonUser”方法包围代码,包括UseShellExecute=true
,会怎么样?我已经在一些项目中成功地使用它来做类似的事情
Fresh Click Media为此撰写了一篇文章,并编写了一个模拟类示例:-->
但为了完整起见,以下是我的版本:
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);
}
在您的案例中使用它将是:
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();
}
您强调这是一个32位进程。这是因为它适用于64位进程吗?从64位应用程序启动进程并不确定子应用程序是否为64位。子应用程序是一个单独的进程,其32/64位的确定方式与其他程序相同。未显式编译为64或32的Net应用程序将是操作系统的本机应用程序。64位操作系统将以64位运行,但32位操作系统将以32位运行。如果ASP.NET以LocalSystem帐户运行,则对CreateProcessWithLogonW
(在场景后使用)的函数调用将失败:@Gabe-在回答第一个问题时,我没有尝试在此上下文中启动64位进程(主要是因为我没有必要这么做),尽管我在过去成功地启动了ShellExecute=false的进程。因此,我不知道它是否适用于64位进程,但我认为它可以。是否有完整源代码示例的最终解决方案可以解决此问题?OP需要UseShellExecute=false
@Gabe:如果进程作为结果以不同的用户启动,则不需要lt模拟。@Ryan-很高兴它有帮助!Happy Codeing;-)如果我重定向Outputo:System.InvalidOperationException:Process对象必须将UseShellExecute属性设置为false才能重定向IO流,则会出现此错误。
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();
}