3

I'm trying to use the following code from th question "PowerShell: Running a command as Administrator" to not only self elevate my script to run automatically in an Administrator-level PowerShell, but also for the Administrator-level PowerShell session to be run with an ExecutionPolicy level of RemoteSigned. I'm assuming that I need to use something like -ExecutionPolicy RemoteSigned in $newProcess.Arguments but am completely lost as to if this is the case, and if it is then what the syntax do I use to create the the multiple arguments?

# Get the ID and security principal of the current user account
$myWindowsID = [System.Security.Principal.WindowsIdentity]::GetCurrent();
$myWindowsPrincipal = New-Object System.Security.Principal.WindowsPrincipal($myWindowsID);

# Get the security principal for the administrator role
$adminRole = [System.Security.Principal.WindowsBuiltInRole]::Administrator;

# Check to see if we are currently running as an administrator
if ($myWindowsPrincipal.IsInRole($adminRole)) {
    # We are running as an administrator, so change the title and background colour to indicate this
    $Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Elevated)";
    $Host.UI.RawUI.BackgroundColor = "DarkBlue";
    Clear-Host;
} else {
    # We are not running as an administrator, so relaunch as administrator

    # Create a new process object that starts PowerShell
    $newProcess = New-Object System.Diagnostics.ProcessStartInfo "PowerShell";

    # Specify the current script path and name as a parameter with added scope and support for scripts with spaces in it's path
    $newProcess.Arguments = "& '" + $script:MyInvocation.MyCommand.Path + "'"

    # Indicate that the process should be elevated
    $newProcess.Verb = "runas";

    # Start the new process
    [System.Diagnostics.Process]::Start($newProcess);

    # Exit from the current, unelevated, process
    Exit;
}

# Run your code that needs to be elevated here...

Write-Host -NoNewLine "Press any key to continue...";
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown");
2
  • self elevating script without security loopholes Commented Oct 23, 2016 at 21:24
  • Well it's not mine. Perhaps I should explain my overall objective. What I'm ultimately trying to do is to run a script from an non-Administrator Powershell session that will throttle internet bandwidth for a single executable. My understanding was that this can only be achieved from an Administrator level Powershell script. I also need this to be able to be run from a Windows 10 machine with default ExecutionPolicy set to Restricted. Hence, my desire to reduce the level of the ExecutionPolicy for the duration of the script. Commented Oct 23, 2016 at 21:34

2 Answers 2

4

$newProcess.Arguments is indeed where you add the relevant parameters. However, you may want to run the script via the parameter -File instead of using the call operator (&) in an implicit -Command parameter.

$newProcess = New-Object Diagnostics.ProcessStartInfo 'powershell.exe'
$newProcess.Arguments = '-ExecutionPolicy RemoteSigned -File "' +
                        $script:MyInvocation.MyCommand.Path + '"'
$newProcess.Verb = 'runas'
[Diagnostics.Process]::Start($newProcess)
Sign up to request clarification or add additional context in comments.

2 Comments

That's perfect - works exactly as I was hoping. After spending hours this morning tearing my hair out you've solved it for me in moments. Thank You :)
This is awesome. By far the most elegant and readable solution I've seen, including from Microsoft. Thank you!
0

Alternate approach - "entrypointing"

Use an entrypoint script for flexibility and ease of maintenance

Given my own experience in maintaining and developing PowerShell scripts, I propose an alternate solution which may prove more maintainer-friendly.

Basic idea

Instead of checking for admin rights, elevating if not, worrying about $MyInvocation variables and whatnot, worrying that code below your elevation block won't run right, I've often found it really helpful to offload my PowerShell checks into an 'Entrypoint' script that I put in front of any workhorse script, and by doing so, make sure the script you launch is always going to launch from the top with exactly the runtime arguments you'd expect.  

Example code

./Entrypoint.ps1

Start-Process pwsh.exe `
     -Verb RunAs -ArgumentList (
     '-NoExit', # Will make sure the script doesn't exit
     '-ExecutionPolicy RemoteSigned', # RemoteSigned
     '-File "./ActualScript.ps1"' # You could do command instead, etc
)

./ActualScript.ps1

Write-Host "Hello world, as admin!"

Pros:

  • The -ArgumentList parameter is really flexible and allows for credential passthrough, env variables, etc.
  • Instead of relying on a block of code within your workhorse script to make a check you want to apply to the entirety of the script, and having to relaunch, just make your script run the way you want to begin with; you can do a lot more than just elevation.

Caveats:

  • This doesn't auto-elevate an existing script. Which is not exactly what you asked. The answer provided is great and I have not seen one that's better.
  • There may be reasons you'd want to explicitly check the privileges of a shell, such that you do one thing if unelevated and another if not, rather than always just making sure to elevate. If, however, you only just want to make sure your processes run in an elevated shell, this is a far simpler solution.

(I've also played with shortcuts, modifying the target, etc, if you're not entirely opposed to the GUI, which are doubly nice because you can have them launch as an admin with a checkbox.)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.