0

I have a script that takes in a max of 3 parameters - username, password and distro.

The script needs to run as administrator since it checks certain things are enabled and can only be done as an admin.

# the command line is:
# linux-docker <username> <password> <distro>
# if no distro is specified then Debian is used.
param ([Parameter(Mandatory)]$username, [Parameter(Mandatory)]$password,  $distro='Debian')

# check if we are in admin mode and switch if we aren't
$currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
if (-Not $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
    if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
        Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs; 
        Read-Host -Prompt "Failure: Press Enter to exit"
        exit;
    }
}

# ... rest of script

However restarting the script prompts the user for username and password. I would like to pass the arguments to the promoted script.

I first thought that adding $username,$password and $distro to the Start-Process command.

Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`" $username $password $debian" -Verb RunAs;

but that exits with the "Failure" message.

So I looked at -ArgumentList but that dies processing that line:

Start-Process : A positional parameter cannot be found that accepts argument '-NoProfile -ExecutionPolicy Bypass -File "C:\Users\Graham Reeds\Documents\linux-docker.ps1"'.
At C:\Users\Graham Reeds\Documents\linux-docker.ps1:15 char:9
+         Start-Process powershell.exe "-NoProfile -ExecutionPolicy Byp ...
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Start-Process], ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.StartProcessCommand
 
Failure: Press Enter to exit:

It is probably something simple but I am a noob with Powershell.

1 Answer 1

1

Using the -ArgumentList parameter should work, but for the parameters sent to the script, you need to get their names and values from the BoundParameters hash:

$currentPrincipal = [Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()
$isAdmin = $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)

if (!$isAdmin) {
    $argList = '-NoLogo', '-NoProfile', '-NoExit', '-ExecutionPolicy Bypass', '-File', ('"{0}"' -f $PSCommandPath)
    # Add script arguments
    $argList += $MyInvocation.BoundParameters.GetEnumerator() | ForEach-Object {"-$($_.Key)", "$($_.Value)"}
    try {
        Start-Process PowerShell.exe -WorkingDirectory $pwd.ProviderPath -ArgumentList $argList -Verb Runas -ErrorAction Stop
        # exit the current script
        exit
    }
    catch {
        Write-Warning "Failed to restart script '$PSCommandPath' with runas"
    }
}
# rest of the script

P.S. Personally I like to always type-cast parameters and when possible make it clear in what order the mandatory parameters should be given if not used Named:

param (
    [Parameter(Mandatory = $true, Position = 0)][string] $username, 
    [Parameter(Mandatory = $true, Position = 1)][string] $password,  
    [string] $distro='Debian'
)
Sign up to request clarification or add additional context in comments.

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.