PS: Relaunch Script As Admin

1 minute read

Description:

The following code can be used to relaunch unelevated scripts as elevated automatically inserting all parameters as required. Admittedly, I don’t use this as much as I should and plan to look into this as the need arises.

To Resolve:

  1. Either put these functions in your begin block, dot source them, or put them in a helpers module.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    
    # Helper - Test if admin
    function Test-IsAdmin() 
    {
       # Get the current ID and its security principal
       $windowsID = [System.Security.Principal.WindowsIdentity]::GetCurrent()
       $windowsPrincipal = new-object System.Security.Principal.WindowsPrincipal($windowsID)
       # Get the Admin role security principal
       $adminRole = [System.Security.Principal.WindowsBuiltInRole]::Administrator
       # Are we an admin role?
       if ($windowsPrincipal.IsInRole($adminRole))
       {
          $true
       }
       else
       {
          $false
       }
    }
    
    # Helper - Get UNC path from mapped drive
    function Get-UNCFromPath
    {
       Param
       (
          [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)][String]$Path
       )
       if ($Path.Contains([io.path]::VolumeSeparatorChar)) 
       {
          $psdrive = Get-PSDrive -Name $Path.Substring(0, 1) -PSProvider 'FileSystem'
          # Is it a mapped drive?
          if ($psdrive.DisplayRoot) 
          {
                $Path = $Path.Replace($psdrive.Name + [io.path]::VolumeSeparatorChar, $psdrive.DisplayRoot)
          }
       }
       return $Path
    }
    
    # Main Function - Relaunch the script if not admin
    function Invoke-RequireAdmin
    {
       Param
       (
          [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)][System.Management.Automation.InvocationInfo]$MyInvocation
       )
    
       if (-not (Test-IsAdmin))
       {
          # Get the script path
          $scriptPath = $MyInvocation.MyCommand.Path
          $scriptPath = Get-UNCFromPath -Path $scriptPath
          # Need to quote the paths in case of spaces
          $scriptPath = '"' + $scriptPath + '"'
          # Build base arguments for powershell.exe
          [string[]]$argList = @('-NoLogo -NoProfile', '-ExecutionPolicy Bypass', '-File', $scriptPath)
          # Add 
          $argList += $MyInvocation.BoundParameters.GetEnumerator() | ForEach-Object {"-$($_.Key)", "$($_.Value)"}
          $argList += $MyInvocation.UnboundArguments
          try
          {    
                Start-Process PowerShell.exe -PassThru -Verb Runas -WorkingDirectory $pwd -ArgumentList $argList
                exit $process.ExitCode
          }
          catch
          {
          }
          exit 1 
       }
    }
    
  2. Then in your script’s begin block, you will just add this one line:

    1
    
    Invoke-RequireAdmin $script:MyInvocation
    
  3. For version 4+, just place the following at the top of your script => Source :

    1
    
    #Requires -RunAsAdministrator
    

Comments