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

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

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

-1073741502

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

Как запустить эту 32-разрядную программу с использованием C # без использования shellвыполнить?

Вот код, который я сейчас имею:

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 Ответ

3 голосов
/ 28 апреля 2011

Что, если вы окружили свой код, включая 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();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...