.NET Start Process с более высокими правами

Я пытаюсь выполнить программу с правами администратора через приложение C #, которое вызывается только с правами пользователя.

Код

<code>        ProcessStartInfo psi;
        try
        {
            psi = new ProcessStartInfo(@"WINZIP32.EXE");

            psi.UseShellExecute = false;
            SecureString pw = new SecureString();
            pw.AppendChar('p');
            pw.AppendChar('a');
            pw.AppendChar('s');
            pw.AppendChar('s');   
            pw.AppendChar('w');
            pw.AppendChar('o');
            pw.AppendChar('r');
            pw.AppendChar('d');
            psi.Password = pw;
            psi.UserName = "administrator";

            Process.Start(psi);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
</code>

Он запускает winzip, но только с правами пользователя. Есть ли что-то, что я делаю неправильно или вообще возможно запустить процесс с более высокими правами?

благодарю вас!

Редактировать: Вот причина вопроса, может быть, это помогает понять, что мне действительно нужно.

I used winzip for example to get a general idea what's incorrect with my code. The actual problem is, our company uses 2 versions of a program. But before you start any of the versions you need to import a dll file with regsvr32 (with admin rights). Now I would like to write a program that let the user select the version, import the dll and starts the correct application.

 KenavR12 апр. 2012 г., 12:50
Вы имеете в виду, что я должен запустить свое приложение с правами администратора, тогда да, я попробовал это, и это странно, но это также открывает winzip с правами пользователя. Но в любом случае программа c # будет выполняться от пользователя без прав администратора.EDIT: Комментарий, на который я ответил, был удален.

Ответы на вопрос(3)


Как запустить процесс в режиме администратора в C #
Повышение привилегий процесса программно?

  var psi = ,new ProcessStartInfo
    {
        FileName = "notepad",
        UserName = "admin",
        Domain = "",
        Password = pass,
        UseShellExecute = true,
        RedirectStandardOutput = true,
        RedirectStandardError = true,
        Verb = "runas";
    };
    Process.Start(psi);

//

var pass = new SecureString();
pass.AppendChar('s');
pass.AppendChar('e');
pass.AppendChar('c');
pass.AppendChar('r');
pass.AppendChar('e');
pass.AppendChar('t');
Process.Start("notepad", "admin", pass, "");

//Vista or higher check

if (System.Environment.OSVersion.Version.Major >= 6)
{
   p.StartInfo.Verb = "runas";
}

Как запустить / запустить новый процесс с правами администратора?  Форум ASP.net

Another way is to impersonate the admin user. You can do this by calling the Logon function and impersonate the user whose token you will get then. For impersonating a user in code, look at: WindowsImpersonationContext Class . Use the check http://www.csharpfriends.com/Forums/ShowPost.aspx?PostID=31611 for GetCurrentUser to see whether impersonation succeeded.

Фрагмент кода:

System.Diagnostics.Process process = null;
System.Diagnostics.ProcessStartInfo processStartInfo;

processStartInfo = new System.Diagnostics.ProcessStartInfo();

processStartInfo.FileName = "regedit.exe";

if (System.Environment.OSVersion.Version.Major >= 6)  // Windows Vista or higher
{
   processStartInfo.Verb = "runas";
}
else
{
   // No need to prompt to run as admin
}

processStartInfo.Arguments = "";
processStartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
processStartInfo.UseShellExecute = true;

try
{
   process = System.Diagnostics.Process.Start(processStartInfo);
}
catch (Exception ex)
{
   MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
   if (process != null)
   {
      process.Dispose();
   }
}

//Try this with administrator login, i have not tested yet..

[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
            int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public extern static bool CloseHandle(IntPtr handle);

        // Test harness.
        // If you incorporate this code into a DLL, be sure to demand FullTrust.
        [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
        private void button1_Click(object sender, EventArgs e)
        {
            SafeTokenHandle safeTokenHandle;
            const int LOGON32_PROVIDER_DEFAULT = 0;
            //This parameter causes LogonUser to create a primary token.
            const int LOGON32_LOGON_INTERACTIVE = 2;
            bool returnValue = LogonUser("administrator", "", "password",
                LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
                out safeTokenHandle);

            Console.WriteLine("LogonUser called.");

            if (false == returnValue)
            {
                int ret = Marshal.GetLastWin32Error();
                Console.WriteLine("LogonUser failed with error code : {0}", ret);
                throw new System.ComponentModel.Win32Exception(ret);
            }
            using (safeTokenHandle)
            {
                Console.WriteLine("Did LogonUser Succeed? " + (returnValue ? "Yes" : "No"));
                Console.WriteLine("Value of Windows NT token: " + safeTokenHandle);

                // Check the identity.
                Console.WriteLine("Before impersonation: "
                    + WindowsIdentity.GetCurrent().Name);
                // Use the token handle returned by LogonUser.
                WindowsIdentity newId = new WindowsIdentity(safeTokenHandle.DangerousGetHandle());
                using (WindowsImpersonationContext impersonatedUser = newId.Impersonate())
                {
                    System.Diagnostics.Process process = null;
                    System.Diagnostics.ProcessStartInfo processStartInfo;


                    processStartInfo = new System.Diagnostics.ProcessStartInfo();

                    processStartInfo.FileName = "regedit.exe";

                    //if (System.Environment.OSVersion.Version.Major >= 6)  // Windows Vista or higher
                    //{
                    //    processStartInfo.Verb = "runas";
                    //}
                    //else
                    //{
                    //    // No need to prompt to run as admin
                    //}

                    processStartInfo.Arguments = "";
                    processStartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
                    processStartInfo.UseShellExecute = true;

                    try
                    {
                        process = System.Diagnostics.Process.Start(processStartInfo);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                    finally
                    {
                        if (process != null)
                        {
                            process.Dispose();
                        }
                    }

                    // Check the identity.
                    Console.WriteLine("After impersonation: "
                        + WindowsIdentity.GetCurrent().Name);
                }
                // Releasing the context object stops the impersonation
                // Check the identity.
                Console.WriteLine("After closing the context: " + WindowsIdentity.GetCurrent().Name);
            }
        }
 KenavR12 апр. 2012 г., 14:44
Первый способ точно такой же, как и я, и он не работает. Второй открывает UAC, это не то, что мне нужно. Когда я использую функцию олицетворения, я получаю & quot; доступ запрещен & quot; исключение.
 13 апр. 2012 г., 10:05
UAC делает то, для чего он был разработан. Вы должны были бы отключить UAC, чтобы обойти это. Его дизайн. Вы не должны запускать повышенные процессы без одобрения пользователя.

ProcessStartInfo.UseShellExecute вtrue а такжеProcessStartInfo.Verb вrunas:

Process process = null;
ProcessStartInfo processStartInfo = new ProcessStartInfo();

processStartInfo.FileName = "WINZIP32.EXE";

processStartInfo.Verb = "runas";
processStartInfo.WindowStyle = ProcessWindowStyle.Normal;
processStartInfo.UseShellExecute = true;

process = Process.Start(processStartInfo);

Это приведет к запуску приложения от имени администратора. UAC, однако, предложит пользователю подтвердить. Если это нежелательно, вам нужно добавитьманифест навсегда повысить привилегии хост-процесса.

 KenavR12 апр. 2012 г., 13:00
Пользователю не нужно вводить пароль администратора. Winzip должен начинаться с учетной записи администратора, которую я определяю внутри кода.
 KenavR13 апр. 2012 г., 09:59
Например, я использовал winzip, чтобы получить общее представление о том, что не так с моим кодом. Актуальная проблема заключается в том, что наша компания использует 2 версии программы. Но перед запуском любой из версий вам необходимо импортировать файл dll с regsvr32 (с правами администратора). Теперь я хотел бы написать программу, которая позволит пользователю выбрать версию, импортировать dll и запустить правильное приложение.
 12 апр. 2012 г., 18:23
UAC существует по причине. Ни одно хорошо спроектированное приложение не должно запускать процесс распаковки от имени администратора.
 09 сент. 2014 г., 10:50
Но установка UseShellExecute = true не позволяет перенаправить вывод. Есть ли способ получить результаты процесса администрирования в процессе без прав администратора?

р), используяФункция CreateProcessAsUser (Win32 API). CreateProcessAsUser принимает токен пользователя в качестве первого параметра, то есть токен олицетворения.

Вы должны использовать DLLImport для загрузки функции из Windows DLL.

Посмотрите на этот пример реализации, который я использовал в одном из моих проектов:

    [StructLayout(LayoutKind.Sequential)]
internal struct PROCESS_INFORMATION
{
    public IntPtr hProcess;
    public IntPtr hThread;
    public uint dwProcessId;
    public uint dwThreadId;
}

[StructLayout(LayoutKind.Sequential)]
internal struct SECURITY_ATTRIBUTES
{
    public uint nLength;
    public IntPtr lpSecurityDescriptor;
    public bool bInheritHandle;
}

[StructLayout(LayoutKind.Sequential)]
public struct STARTUPINFO
{
    public uint cb;
    public string lpReserved;
    public string lpDesktop;
    public string lpTitle;
    public uint dwX;
    public uint dwY;
    public uint dwXSize;
    public uint dwYSize;
    public uint dwXCountChars;
    public uint dwYCountChars;
    public uint dwFillAttribute;
    public uint dwFlags;
    public short wShowWindow;
    public short cbReserved2;
    public IntPtr lpReserved2;
    public IntPtr hStdInput;
    public IntPtr hStdOutput;
    public IntPtr hStdError;

}

internal enum SECURITY_IMPERSONATION_LEVEL
{
    SecurityAnonymous,
    SecurityIdentification,
    SecurityImpersonation,
    SecurityDelegation
}

internal enum TOKEN_TYPE
{
    TokenPrimary = 1,
    TokenImpersonation
}

public class ProcessAsUser
{

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool CreateProcessAsUser(
    IntPtr hToken,
    string lpApplicationName,
    string lpCommandLine,
    ref SECURITY_ATTRIBUTES lpProcessAttributes,
    ref SECURITY_ATTRIBUTES lpThreadAttributes,
    bool bInheritHandles,
    uint dwCreationFlags,
    IntPtr lpEnvironment,
    string lpCurrentDirectory,
    ref STARTUPINFO lpStartupInfo,
    out PROCESS_INFORMATION lpProcessInformation);

    [DllImport("advapi32.dll", EntryPoint = "DuplicateTokenEx", SetLastError = true)]
    private static extern bool DuplicateTokenEx(
    IntPtr hExistingToken,
    uint dwDesiredAccess,
    ref SECURITY_ATTRIBUTES lpThreadAttributes,
    Int32 ImpersonationLevel,
    Int32 dwTokenType,
    ref IntPtr phNewToken);

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool OpenProcessToken(
    IntPtr ProcessHandle,
    UInt32 DesiredAccess,
    ref IntPtr TokenHandle);

    [DllImport("userenv.dll", SetLastError = true)]
    private static extern bool CreateEnvironmentBlock(
    ref IntPtr lpEnvironment,
    IntPtr hToken,
    bool bInherit);

    [DllImport("userenv.dll", SetLastError = true)]
    private static extern bool DestroyEnvironmentBlock(
    IntPtr lpEnvironment);

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool CloseHandle(
    IntPtr hObject);

    private const short SW_SHOW = 5;
    private const uint TOKEN_QUERY = 0x0008;
    private const uint TOKEN_DUPLICATE = 0x0002;
    private const uint TOKEN_ASSIGN_PRIMARY = 0x0001;
    private const int GENERIC_ALL_ACCESS = 0x10000000;
    private const int STARTF_USESHOWWINDOW = 0x00000001;
    private const int STARTF_FORCEONFEEDBACK = 0x00000040;
    private const uint CREATE_UNICODE_ENVIRONMENT = 0x00000400;
    private const int STARTF_RUNFULLSCREEN = 0x00000020;

    private static bool LaunchProcessAsUser(string cmdLine, IntPtr token, IntPtr envBlock)
    {
        bool result = false;

        PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
        SECURITY_ATTRIBUTES saProcess = new SECURITY_ATTRIBUTES();
        SECURITY_ATTRIBUTES saThread = new SECURITY_ATTRIBUTES();
        saProcess.nLength = (uint)Marshal.SizeOf(saProcess);
        saThread.nLength = (uint)Marshal.SizeOf(saThread);

        STARTUPINFO si = new STARTUPINFO();
        si.cb = (uint)Marshal.SizeOf(si);

        //if this member is NULL, the new process inherits the desktop
        //and window station of its parent process. If this member is
        //an empty string, the process does not inherit the desktop and
        //window station of its parent process; instead, the system
        //determines if a new desktop and window station need to be created.
        //If the impersonated user already has a desktop, the system uses the
        //existing desktop.

        si.lpDesktop = @"WinSta0\Default"; //Modify as needed
        si.dwFlags = STARTF_USESHOWWINDOW | STARTF_FORCEONFEEDBACK;
        si.wShowWindow = SW_SHOW;

        //Set other si properties as required.

        result = CreateProcessAsUser(
        token,
        null,
        cmdLine,
        ref saProcess,
        ref saThread,
        false,
        CREATE_UNICODE_ENVIRONMENT,
        envBlock,
        null,
        ref si,
        out pi);

        if (result == false)
        {
            int error = Marshal.GetLastWin32Error();
            string message = String.Format("CreateProcessAsUser Error: {0}", error);
            Debug.WriteLine(message);

        }

        return result;
    }

    /// <summary>
    /// LaunchProcess As User Overloaded for Window Mode 
    /// </summary>
    /// <param name="cmdLine"></param>
    /// <param name="token"></param>
    /// <param name="envBlock"></param>
    /// <param name="WindowMode"></param>
    /// <returns></returns>
    private static bool LaunchProcessAsUser(string cmdLine, IntPtr token, IntPtr envBlock,uint WindowMode)
    {
        bool result = false;

        PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
        SECURITY_ATTRIBUTES saProcess = new SECURITY_ATTRIBUTES();
        SECURITY_ATTRIBUTES saThread = new SECURITY_ATTRIBUTES();
        saProcess.nLength = (uint)Marshal.SizeOf(saProcess);
        saThread.nLength = (uint)Marshal.SizeOf(saThread);

        STARTUPINFO si = new STARTUPINFO();
        si.cb = (uint)Marshal.SizeOf(si);

        //if this member is NULL, the new process inherits the desktop
        //and window station of its parent process. If this member is
        //an empty string, the process does not inherit the desktop and
        //window station of its parent process; instead, the system
        //determines if a new desktop and window station need to be created.
        //If the impersonated user already has a desktop, the system uses the
        //existing desktop.

        si.lpDesktop = @"WinSta0\Default"; //Default Vista/7 Desktop Session
        si.dwFlags = STARTF_USESHOWWINDOW | STARTF_FORCEONFEEDBACK;

        //Check the Startup Mode of the Process 
        if (WindowMode == 1)
            si.wShowWindow = SW_SHOW;
        else if (WindowMode == 2)
        { //Do Nothing
        }
        else if (WindowMode == 3)
            si.wShowWindow = 0; //Hide Window 
        else if (WindowMode == 4)
            si.wShowWindow = 3; //Maximize Window
        else if (WindowMode == 5)
            si.wShowWindow = 6; //Minimize Window
        else
            si.wShowWindow = SW_SHOW;


        //Set other si properties as required.
        result = CreateProcessAsUser(
        token,
        null,
        cmdLine,
        ref saProcess,
        ref saThread,
        false,
        CREATE_UNICODE_ENVIRONMENT,
        envBlock,
        null,
        ref si,
        out pi);

        if (result == false)
        {
            int error = Marshal.GetLastWin32Error();
            string message = String.Format("CreateProcessAsUser Error: {0}", error);
            Debug.WriteLine(message);

        }

        return result;
    }

    private static IntPtr GetPrimaryToken(int processId)
    {
        IntPtr token = IntPtr.Zero;
        IntPtr primaryToken = IntPtr.Zero;
        bool retVal = false;
        Process p = null;

        try
        {
            p = Process.GetProcessById(processId);
        }

        catch (ArgumentException)
        {

            string details = String.Format("ProcessID {0} Not Available", processId);
            Debug.WriteLine(details);
            throw;
        }

        //Gets impersonation token
        retVal = OpenProcessToken(p.Handle, TOKEN_DUPLICATE, ref token);
        if (retVal == true)
        {

            SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
            sa.nLength = (uint)Marshal.SizeOf(sa);

            //Convert the impersonation token into Primary token
            retVal = DuplicateTokenEx(
            token,
            TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_QUERY,
            ref sa,
            (int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
            (int)TOKEN_TYPE.TokenPrimary,
            ref primaryToken);

            //Close the Token that was previously opened.
            CloseHandle(token);
            if (retVal == false)
            {
                string message = String.Format("DuplicateTokenEx Error: {0}", Marshal.GetLastWin32Error());
                Debug.WriteLine(message);
            }

        }

        else
        {

            string message = String.Format("OpenProcessToken Error: {0}", Marshal.GetLastWin32Error());
            Debug.WriteLine(message);

        }

        //We'll Close this token after it is used.
        return primaryToken;

    }

    private static IntPtr GetEnvironmentBlock(IntPtr token)
    {

        IntPtr envBlock = IntPtr.Zero;
        bool retVal = CreateEnvironmentBlock(ref envBlock, token, false);
        if (retVal == false)
        {

            //Environment Block, things like common paths to My Documents etc.
            //Will not be created if "false"
            //It should not adversley affect CreateProcessAsUser.

            string message = String.Format("CreateEnvironmentBlock Error: {0}", Marshal.GetLastWin32Error());
            Debug.WriteLine(message);

        }
        return envBlock;
    }

    public static bool Launch(string appCmdLine /*,int processId*/)
    {

        bool ret = false;

        //Either specify the processID explicitly
        //Or try to get it from a process owned by the user.
        //In this case assuming there is only one explorer.exe

        Process[] ps = Process.GetProcessesByName("explorer");
        int processId = -1;//=processId
        if (ps.Length > 0)
        {
            processId = ps[0].Id;
        }

        if (processId > 1)
        {
            IntPtr token = GetPrimaryToken(processId);

            if (token != IntPtr.Zero)
            {

                IntPtr envBlock = GetEnvironmentBlock(token);
                ret = LaunchProcessAsUser(appCmdLine, token, envBlock);
                if (envBlock != IntPtr.Zero)
                    DestroyEnvironmentBlock(envBlock);

                CloseHandle(token);
            }

        }
        return ret;
    }
 19 нояб. 2013 г., 09:46
Как вы подписываетесь наProcess.Exited msdn.microsoft.com/en-us/library/… с таким подходом? Кроме того, кажется, не в состоянии принять обычайEnvironmentBlock в .net дружественном формате, как этоmsdn.microsoft.com/en-us/library/… В идеале я ищу решение, которое делает все, что может делать стандартный процесс, но также принимает токен. Похоже, мне придется создать его самому.

Ваш ответ на вопрос