Как запустить 32-битный процесс в C# без использования оболочки на 64-битном компьютере?

У меня есть веб-приложение ASP .NET на 64-разрядной машине, которое должно запускать устаревшее 32-разрядное приложение для создания отчетов.

Когда я запускаю программу с UseShellExecute = false, программа выходит с кодом выхода:

-1073741502

Я не могу использовать Shell Execute, потому что мне нужно запустить процесс от имени другого пользователя. Тем не менее, когда Shell Execute имеет значение true, процесс будет работать нормально (хотя мне нужно сменить пользователя, под которым выполняется ASP .NET).

Как я могу запустить эту 32-битную программу, используя C# без использования 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();

1 ответ

Решение

Что делать, если вы окружили свой код, в том числе UseShellExecute = trueс Windows родным методом "LogonUser"? Я успешно использовал это в нескольких проектах, чтобы сделать что-то подобное.

[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: -> http://www.freshclickmedia.com/blog/2008/11/programmatic-impersonation-in-c/

Но для полноты вот моя версия:

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();
}
Другие вопросы по тегам