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.
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'
)
Related
I would like to know exactly what is the difference between an administrator account and a user with administrator privileges ? I ask you this because when I run a script by GPO as an Administrator, the scrpit works but when I run the GPO with a user account of the domain that has administrator privileges, the script does not run.
Here is the script with the administrator account:
$username = 'labo\Administrator'
$password = 'Qzerty13.'
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential $username, $securePassword
$Command =
{
if ((get-tpm).TpmPresent -eq $True ) # test if puce tpm present
{
write-host "Puce tpm présente"
if ((get-tpm).TpmReady -eq $True) # test if puce tpm ready
{
write-host "Puce tpm prête"
if((Get-BitLockerVolume -MountPoint $env:SystemDrive).VolumeStatus -eq "FullyDecrypted") # test the disk is not encrypted
{
write-host "Unencrypted disk"
Add-BitLockerKeyProtector -MountPoint $env:SystemDrive -TpmProtector
Enable-BitLocker -MountPoint $env:SystemDrive -RecoveryPasswordProtector -SkipHardwareTest
write-host "Disk Encryption with TPM"
}
}
}
}
Start-Process powershell.exe -Credential $Credential -ArgumentList "-NoExit -Command & {$($Command -replace '"', '\"')} -ExecutionPolicy Bypass"
When I run this script through a gpo, it works, but when I want to change the admin account by putting a user account that has admin privileges, it doesn’t start.
here is the error message when I wish to run the script with a user account with administration privileges:
Start-Process : Impossible d’exécuter cette commande en raison de l’erreur : Nom de répertoire non valide.
Au caractère C:\Users\testeur\Desktop\tpm 30_05_2022.ps1:26 : 3
+ Start-Process powershell.exe -Credential $Credential -ArgumentList ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation : (:) [Start-Process], InvalidOperationException
+ FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessCommand
Can you enlighten me on that, please.
my best regards.
Nordine
Try adding the RunAs option to your Start-Process
Start-Process powershell.exe -Verb RunAs -ArgumentList "-NoExit -Command & {$($Command -replace '"', '\"')} -ExecutionPolicy Bypass"
When I am running a PowerShell script normally it's working fine, issue is raising when calling the same script from batch file.
Unt1.ps1 script:
$linux_app_user="ORXXXX\"+$args[0]
$pass_win=$args[1]
$path=$args[2]
$pass = ConvertTo-SecureString -AsPlainText $pass_win -Force
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList
$linux_app_user, $pass
$Invoke-Command -ComputerName XXXXXXXX.XXXX.XXX.XXXX -Credential $cred -ErrorAction
Stop -ScriptBlock {
param($path)
Invoke-Expression $path
} -Arg $path
cal.bat script:
#echo off
SET Server=slXXXXXXXX.XXX.XXXX.com
SET PowerShellDir=C:\Windows\System32\WindowsPowerShell\v1.0
CD /D "%PowerShellDir%
powershell.exe -ExecutionPolicy RemoteSigned -File
C:\Users\chaj\Documents\String\Unt1.ps1 'XXXX' 'XXXX#321' 'C:\cal.bat'
Error:
[xxxxxx.xx.xxxxx.xxx] Connecting to remote server xxxxxx.xx.xxxxx.xxx failed
with the following error message : The user name or password is incorrect.
For more information, see the about_Remote_Troubleshooting Help topic.
At C:\Users\chafg\Documents\String\Unt1.ps1:7 char:1
+ $Result=Invoke-Command -ComputerName xxxxxx.xx.xxxxx.xxx -Credenti ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OpenError: (xxxxxx.xx.xxxxx.xxx) [], PSRemotingTransportException
+ FullyQualifiedErrorId : LogonFailure,PSSessionStateBroken
When using the PowerShell CLI with the -File parameter, all arguments are used verbatim - except if enclosed in "..." (double quotes): unlike when you use -Command, '...' (single quotes) are not recognized as string delimiters.
Therefore, your command (simplified here):
powershell.exe -File C:\path\to\Unt1.ps1 'XXXX' 'XXXX#321' 'C:\cal.bat'
causes the Unt1.ps1 script to see the arguments with the enclosing ', which is not your intent; e.g., instead of $args[0] receiving XXXX, as intended, it receives 'XXXX', verbatim.
The fix is to use "..." (double quotes):
powershell.exe -File C:\path\to\Unt1.ps1 "XXXX" "XXXX#321" "C:\cal.bat"
Alternatively, given that your specific sample arguments don't require quoting (though the real ones may):
powershell.exe -File C:\path\to\Unt1.ps1 XXXX XXXX#321 C:\cal.bat
I am new to Powershell and trying to run a PS script using another PS script to run it as admin in Jenkins, the script gives its desired output but it also gives the error in the output.
Powershell : Start-Process : A positional parameter cannot be found
that accepts argument At line:4 char:1
+ Powershell -Command "Start-Process powershell ""cd "F:\RiskLink\RiskL ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (Start-Process :...cepts argument :String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
Code:
Set-Location -Path F:\abd\abc
$path = ".\xyz.ps1"
Powershell -Command "Start-Process powershell ""cd "F:\abd\abc"; & $path"" -Verb RunAs"
Long ago, I have created a simple command line parser (scripts cliparser.ps1 and cli parser.ps1):
PS D:\PShell> Get-Content ".\cliparser.ps1"
if ( $args -ne $null ) { $aLen=$args.Count } else { $aLen=0 }
"$(Split-Path -Path $PSCommandPath -Leaf): $aLen parameters"
for ( $i = 0; $i -lt $aLen ; $i++ ) { "{0}. [{1}]" -f $i, $args[$i] }
Used instead of yours xyz.ps1, it shows that something must go wrong not only with Start-Process arguments but with quoting as well (shows supplied values -Verb and RunAs). Fixed with some little effort… Improved for space(s) in paths and file names, see the following script:
$cd = (Get-Location -PSProvider Filesystem).Path
$path = ".\cliparser.ps1"
'... original (known error)'
Write-Host Powershell -Command "Start-Process powershell ""pushd "$cd"; & $path"" -Verb RunAs"
Powershell -Command "Start-Process powershell ""pushd "$cd"; & $path"" -Verb RunAs"
pause
'... fixed'
Write-Host Powershell -NoProfile -Command "Start-Process powershell -ArgumentList '-NoProfile', '-noexit', '-command', 'pushd `'`'$cd`'`'; & `'`'$path`'`';' -Verb RunAs"
$path = ".\cli parser.ps1"
Powershell -NoProfile -Command "Start-Process powershell -ArgumentList '-NoProfile', '-noexit', '-command', 'pushd `'`'$cd`'`'; & `'`'$path`'`';' -Verb RunAs"
'done'
Note that PShell's parameters -NoProfile and -NoExit are here merely for debugging purposes.
Result:
PS D:\PShell> D:\PShell\SO\53638416.ps1
... original (known error)
Powershell -Command Start-Process powershell "pushd D:\PShell; & .\cliparser.ps1" -Verb RunAs
Start-Process : A positional parameter cannot be found that accepts argument 'D:\PShell'.
At line:1 char:1
+ Start-Process powershell pushd D:\PShell; & .\cliparser.ps1 -Verb Ru ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Start-Process], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.Start
ProcessCommand
cliparser.ps1: 2 parameters
0. [-Verb]
1. [RunAs]
Press Enter to continue...:
... fixed
Powershell -NoProfile -Command Start-Process powershell -ArgumentList '-NoProfile', '-noexit', '-command', 'pushd ''D:\PShell''; & ''.\cliparser.ps1'';' -Verb RunAs
done
PS D:\PShell>
Called (elevated) Powershell window looks as follows (Pop-Location used to ensure that popd ran well):
To run from a cmd prompt and pass arguments to the called script:
powershell -NoProfile -Command "Start-Process powershell -ArgumentList '-NoProfile', '-noexit', '-command', 'pushd ''D:\PShell''; & ''.\cliparser.ps1'' a b c;' -Verb RunAs"
Works for pwsh instead of powershell as well:
pwsh -NoProfile -Command "Start-Process pwsh -ArgumentList '-NoProfile', '-noexit', '-command', 'pushd ''D:\PShell''; & ''.\cliparser.ps1'' a b c;' -Verb RunAs"
I want to pass a cmdlet to be executed immediately in child Process.
---> $cmd = $(Get-Item -FORCE "PATH\to\Folder").Attributes= "Normal"
Start-Process powershell -ArgumentList " multiple $cmd Here"
PS : when i use { } , () or " " in -ArgumentList i get different behaviour anyone care to explain why ?.
I'm having to construct some paths before attempting to invoke the script which is present on the remote computer. I'm adapting something we have working in TeamCity, but I'm currently getting the following error:
The command cannot be run because the File parameter requires a file path. Supply a path for the File parameter and then try the command again.
+ CategoryInfo : NotSpecified: (The command can... command again.:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
Relevant code below:
$stageScript = "D:\pkg\${dir}\stage.ps1"
$options = "production \\192.168.0.x\staging \\${server}\staging"
Invoke-Command -computername server.domain.com { powershell.exe -noprofile -executionpolicy Bypass -file $stageScript $options } -Credential $credential
You need to pass local variables to the script block as an argument list
$stageScript = "D:\pkg\${dir}\stage.ps1"
$options = "production \\192.168.0.x\staging \\${server}\staging"
Invoke-Command -computername server.domain.com { powershell.exe -noprofile -executionpolicy Bypass -file $args[0] $args[1] } -ArgumentList $stageScript,$options -Credential $credential