El TecnoBaúl de Kiquenet

Kiquenet boring stories

UAC, Run As Administrator, Elevated Process

Posted by kiquenet en 22 agosto 2014

cmd.RedirectStandardInput = true;
cmd.RedirectStandardOutput = true;
cmd.RedirectStandardError = true;
cmd.UseShellExecute = false; // true ???
cmd.Verb = “runas”

The Verb only works with UseShellExecute set to true

You must use ShellExecute. ShellExecute is the only API that knows how to launch Consent.exe in order to elevate.
In C#, the way you call ShellExecute is to use Process.Start along with UseShellExecute = true:






const int ERROR_CANCELLED = 1223; //The operation was canceled by the user. ProcessStartInfo info = new ProcessStartInfo(@"C:\Windows\Notepad.exe"); info.UseShellExecute = true; info.Verb = "runas"; try { Process.Start(info); } catch (Win32Exception ex) { if (ex.NativeErrorCode == ERROR_CANCELLED) MessageBox.Show("Why you no select Yes?"); else throw; }

You can indicate the new process should be started with elevated permissions by setting the Verb property of your startInfo object to ‘runas’, as follows:

startInfo.Verb = "runas";

This will cause Windows to behave as if the process has been started from Explorer with the "Run as Administrator" menu command.

This does mean the UAC prompt will come up and will need to be acknowledged by the user: if this is undesirable (for example because it would happen in the middle of a lengthy process), you’ll need to run your entire host process with elevated permissions by embedding the appropriate manifest in your application to require the ‘highestAvailable’ execution level: this will cause the UAC prompt to appear as soon as your app is started, and cause all child processes to run with elevated permissions without additional prompting.

Edit: I see just just edited your question to state that "runas" didn’t work for you. That’s really strange, as it should (and does for me in several production apps). Requiring the parent process to run with elevated rights by embedding the manifest should definitely work, though.

Manifest for Application: http://msdn.microsoft.com/en-us/library/bb756929.aspx

<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />

Executable: IsUserAdmin.exe 
Manifest:IsUserAdmin.exe.manifest
Sample application manifest file:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
  <assemblyIdentity version="1.0.0.0"
     processorArchitecture="X86"
     name="IsUserAdmin"
     type="win32"/> 
  <description>Description of your application</description> 
  <!-- Identify the application security requirements. -->
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel
          level="requireAdministrator"
          uiAccess="false"/>
        </requestedPrivileges>
       </security>
  </trustInfo>
</assembly>

Update: The app manifest way is preferred:

Right click project in visual studio, add, new application manifest file, change the file so you have requireAdministrator set as shown in the above.

(Properties Project –> Application –> Resources –> Icon and manifest (embed, first add it and then select)

How to set UAC settings in manifest (VS 2008)

http://justinyue.wordpress.com/2008/12/19/how-to-set-uac-settings-in-manifest-for-vs-2008/

if (IsAdministrator() == false)
{
    // Restart program and run as admin
    var exeName = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
    ProcessStartInfo startInfo = new ProcessStartInfo(exeName);
    startInfo.Verb = "runas";
    System.Diagnostics.Process.Start(startInfo);
    Application.Current.Shutdown();
    return;
}

private static bool IsAdministrator()
{
    WindowsIdentity identity = WindowsIdentity.GetCurrent();
    WindowsPrincipal principal = new WindowsPrincipal(identity);
    return principal.IsInRole(WindowsBuiltInRole.Administrator);
}


// To run as admin, alter exe manifest file after building.
// Or create shortcut with "as admin" checked.
// Or ShellExecute(C# Process.Start) can elevate - use verb "runas".
// Or an elevate vbs script can launch programs as admin.
// (does not work: "runas /user:admin" from cmd-line prompts for admin pass)


this error

The Process object must have the UseShellExecute property set to false in order to redirect IO streams.

The Process object must have the UseShellExecute property set to false in order to start a process as a user

you cannot have it both ways. UAC prevents an unelevated process from hi-jacking the capabilities of an elevated one. The only way you can redirect is to elevate yourself first.

You need to set UseShellExecute to true for the Verb to be respected and it must be set to ‘false’ to redirect standard output. You can’t do both.

I’m pretty sure Windows also won’t allow you to redirect standard input/output/error across the admin/non-admin security boundary. You’ll have to find a different way to get output from the program running as admin.

According to this article, only ShellExecute checks the embedded manifest and prompts the user for elevation if needed, while CreateProcess and other APIs don’

http://www.codeproject.com/KB/vista-security/UAC__The_Definitive_Guide.aspx

  • UAC – What. How. Why.. The architecture of UAC, explaining that CreateProcess cannot do elevation, only create a process. ShellExecute is the one who knows how to launch Consent.exe, and Consent.exe is the one who checks group policy options.


Check out this code (I was inspired by the code here, but I’ve improved it – in my version there is no directory created and removed to check for admin privileges):

:::::::::::::::::::::::::::::::::::::::::

:: Automatically check & get admin rights

:::::::::::::::::::::::::::::::::::::::::

@echo off

CLS

ECHO.

ECHO =============================

ECHO Running Admin shell

ECHO =============================

:checkPrivileges

NET FILE 1>NUL 2>NUL

if '%errorlevel%' == '0' ( goto gotPrivileges ) else ( goto getPrivileges )

:getPrivileges

if '%1'=='ELEV' (shift & goto gotPrivileges) 
ECHO.

ECHO **************************************

ECHO Invoking UAC for Privilege Escalation

ECHO **************************************

setlocal DisableDelayedExpansion

set "batchPath=%~0"

setlocal EnableDelayedExpansion

ECHO Set UAC = CreateObject^("Shell.Application"^) > "%temp%\OEgetPrivileges.vbs"

ECHO UAC.ShellExecute "!batchPath!", "ELEV", "", "runas", 1 >> "%temp%\OEgetPrivileges.vbs"

"%temp%\OEgetPrivileges.vbs"

exit /B

:gotPrivileges

::::::::::::::::::::::::::::

:START

::::::::::::::::::::::::::::

setlocal & pushd .

REM Run shell as admin (example) - put here code as you like

cmd /k

The script takes advantage of the fact that NET FILE requires admin privilege and returns errorlevel 1 if you don’t have it. The elevation is achieved by creating a script which re-launches the batch file to obtain privileges. This causes Windows to present the UAC dialog and asks you for the admin account and password.

I have tested it with Windows 7 and with Windows XP – works fine for both. Advantage is, after the start point you can place anything that requires admin privileges, e.g. if you intend to re-install and re-run a Windows service for debugging purpose (assumed that mypackage.msi is a service installer package):

msiexec /passive /x mypackage.msi
msiexec /passive /i mypackage.msi
net start myservice

Without this privilege elevating script UAC would ask you three times for your admin user and password – now you’re asked only once at the beginning, and only if required.


Update: If your script just needs to show an error message and exit if there are no admin privilegesinstead of auto-elevating, this is even simpler: You can achieve this by adding the following at the beginning of your script:

@ECHO OFF & CLS & ECHO.
NET FILE 1>NUL 2>NUL & IF ERRORLEVEL 1 (ECHO You must right-click and select &
  ECHO "RUN AS ADMINISTRATOR"  to run this batch. Exiting... & ECHO. & 
  PAUSE & EXIT /D)
REM ... proceed here with admin rights ...

This way, the user has to right-click and select "Run as administrator". The script will proceed after the REM statement if it detects admin rights, otherwise exit with an error. If you don’t require the PAUSE, just remove it. Important: NET FILE [...] EXIT /D) must be in the same line, it is displayed here in multiple lines for better readability!


Update: On some machines, I’ve encountered issues, which are solved in the new version above already. One was due to different double quote handling, the other issue was due to the fact that UAC was disabled (set to lowest level) on a Windows 7 machine, hence the script calls itself again and again.

I have fixed this now by stripping the quotes in the path and re-adding them later and I’ve added an extra parameter which is added when the script re-launches with elevated rights.

The double quotes are removed by the following (details are here):

setlocal DisableDelayedExpansion
set "batchPath=%~0"
setlocal EnableDelayedExpansion

You can then access the path by using !batchPath!, it contains no double quotes so it is safe to say "!batchPath!" later in the script.

The line

if '%1'=='ELEV' (shift & goto gotPrivileges)  

checks if the script has already been called by the VBS to elevate rights, hence avoiding endless recursions. It removes the parameter using shift.


Mt.exe Tool

Common Errors:

Exited with code 9009 (Post Build Event)

Values of attribute "name" not equal in different manifest snippets. mt.exe


http://stackoverflow.com/questions/4677055/visual-studio-post-build-event-mt-exe-command-fails-with-code-9009?rq=1#4865696

"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\mt.exe"
"C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\mt.exe" -manifest "$(ProjectDir)$(TargetName).exe.manifest" -updateresource:"$(TargetDir)$(TargetName).exe;#1"

References:

http://stackoverflow.com/questions/8690552/run-elevated-process

http://stackoverflow.com/questions/16926232/run-process-as-administrator-from-a-non-admin-application/20872219#20872219

http://stackoverflow.com/questions/133379/elevating-process-privilege-programatically

http://msdn.microsoft.com/en-us/magazine/cc163486.aspx

http://stackoverflow.com/questions/7044985/how-can-i-auto-elevate-my-batch-file-so-that-it-requests-from-uac-admin-rights?answertab=votes#tab-top

http://justinyue.wordpress.com/2008/12/19/how-to-set-uac-settings-in-manifest-for-vs-2008/

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

 
A %d blogueros les gusta esto: