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

StackOverflow https://stackoverflow.com/questions/5812598

Вопрос

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

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

-1073741502

Я не могу использовать Shell Execute, потому что я должен запустить процесс как другого пользователя. Тем не менее, когда выполняется Shell 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();
Это было полезно?

Решение

Что если вы окружили свой код, включая 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 сделал статью об этом и написал образец подчиненного класса: -> 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();
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top