Just laying this out there. Here is my code for downloading an application and installing it.
# File Download and Install Function
function FDL($url){
# set to the default download directory; obviously can be wherever one wants
$DL = set-location $env:USERPROFILE\downloads\
# using this to capture just the filename
$FN = $url -split("/")
$FD = $FN[$FN.Length-1]
# Download File
Start-BitsTransfer -source $url -destination $DL\$FD
# Install File
Start-Process -NoNewWindow $DL\$FD -ArgumentList $args
}
PS:> FDL "https://www.kymoto.org/downloads/ISStudio_Latest.exe"
This function works perfectly every time assuming that the URL is correct!
Then I thought, what if I were to have the functionality to place the correct arguments for the installer type. So I came up with this:
# File Download and Install Function
function FDL($url,$p){
# set to the default download directory; obviously can be whereever one wants
$DL = set-location $env:USERPROFILE\downloads\
# using this to capture just the filename
$FN = $url -split("/")
$FD = $FN[$FN.Length-1]
switch ($p){
1 {" /passive /qb /norestart";break}
2 {" /sp- /silent /norestart /SUPPRESSMSGBOXES /CURRENTUSERS /NORESTART /NOCANCEL /FORCECLOSEAPPLICATION /RESTARTAPPLICATIONS";break}
3 {" /SILENT";break}
4 {" /quiet";break}
5 {" /S";break}
6 {" /Q";break}
}
Start-BitsTransfer -source $url -destination $DL\$FD
Start-Process -NoNewWindow $DL\$FD -ArgumentList $p
}
# 2 because this is an InnoSetup installer type
PS:> FDL 'https://www.kymoto.org/downloads/ISStudio_Latest.exe', 2
FAIL
Start-BitsTransfer : The number of items specified in the Source parameter do not match the number of items specified in the Destination parameter. Verify that the same
number of items is specified in the Source and Destination parameters.
At [dir]\FileDownloader Function.ps1:17 char:1
+ Start-BitsTransfer -source $url -destination $DL\$FD
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Start-BitsTransfer], ArgumentException
+ FullyQualifiedErrorId : StartBitsTransferArgumentException,Microsoft.BackgroundIntelligentTransfer.Management.NewBitsTransferCommand
Start-BitsTransfer :
At [dir]\FileDownloader Function.ps1:17 char:1
+ Start-BitsTransfer -source $url -destination $DL\$FD
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Start-BitsTransfer], Exception
+ FullyQualifiedErrorId : System.Exception,Microsoft.BackgroundIntelligentTransfer.Management.NewBitsTransferCommand
Start-Process : Cannot validate argument on parameter 'ArgumentList'. The argument is null or empty. Provide an argument that is not null or empty, and then try the
command again.
At [dir]\FileDownloader Function.ps1:20 char:50
+ Start-Process -NoNewWindow $DL\$FD -ArgumentList ($p)
+ ~~~~
+ CategoryInfo : InvalidData: (:) [Start-Process], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.StartProcessCommand
No matter how I adjust this code it comes out with the same error. Any suggestions or assistance here will be greatly appreciated!
Might not be exactly what you're looking for but it should give you a hint as to approach the code for a function in PowerShell.
A few pointers, parameters in PowerShell are either Positional or Named, about_Parameters explains both concepts. Most importantly, each argument is separated by a space and not by a comma.
You can parse an URL using the Uri Class, so, for getting the file name from your address, is as simple as:
# Last segment from this Uri (index -1 from the segment array)
([uri] 'https://www.kymoto.org/downloads/ISStudio_Latest.exe').Segments[-1]
-ArgumentList from Start-Process expects string[], you can pass an array of arguments instead of a single string as shown in Example 7.
You're never capturing the output from your switch ($p), which explains the error:
Start-Process : Cannot validate argument on parameter 'ArgumentList'. The argument is null or empty.
A hash table can be used instead of a switch.
Lastly, I have added a -PassThru switch, now if you call the function with the switch activated (DownloadFile -PassThru -Uri ...), the function will output the Process instance representing the started process.
function DownloadFile {
[cmdletbinding()]
param(
[parameter(Mandatory)]
[uri] $Uri,
[parameter()]
[ValidateSet(1,2,3,4,5,6)]
[int] $Arguments,
[parameter()]
[string] $Destination = "$env:USERPROFILE\Downloads",
[parameter()]
[switch] $PassThru
)
$arg = #{
1 = '/passive', '/qb', '/norestart'
2 = #(
'/sp-', '/silent', '/norestart', '/SUPPRESSMSGBOXES'
'/CURRENTUSERS', '/NORESTART', '/NOCANCEL'
'/FORCECLOSEAPPLICATION', '/RESTARTAPPLICATIONS'
)
3 = '/SILENT'
4 = '/quiet'
5 = '/S'
6 = '/Q'
}
$destFile = Join-Path $Destination -ChildPath $Uri.Segments[-1]
Start-BitsTransfer -Source $Uri -Destination $destFile
$param = #{
FilePath = $destFile
ArgumentList = $arg[$Arguments]
NoNewWindow = $true
PassThru = $PassThru.IsPresent
}
Start-Process #param
}
DownloadFile -Uri 'https://www.kymoto.org/downloads/ISStudio_Latest.exe' -Arguments 2
Related
I am trying to test the uninstallation of a program that is installed on my device. I am not sure what I need to do to specify the file path to this exe located on my device. Eventually this will need to be deployed organization wide, that's why I am attempting to use $PSScriptRoot. How do I specify the filepath to the exe I need deleted? It's a simple script but I keep getting the below error:
Transcript started, output file is C:\WINDOWS\TEMP\Python3.7.8Install.log
2022-10-26-03-08-47 - Install
Start-Process : Cannot validate argument on parameter 'FilePath'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.
At C:\Users\grayvi02\Downloads\UpdatePython.ps1:13 char:27
+ $Process1 = Start-Process $Install_Path -ArgumentList $Install_Args - ...
+ ~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Start-Process], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.StartProcessCommand
2022-10-26-03-08-47 - Error - Install error with exitcode
Transcript stopped, output file is C:\WINDOWS\TEMP\Python3.7.8Install.log
$OutputFile = "$env:WINDIR\TEMP\Python3.7.8Install.log"
Writelog $Install_File = "python-3.7.8-amd64.exe"
Writelog $Install_Path = "`"$PSScriptRoot\$Install_File`""
$Install_Args = " /quiet /uninstall"
##########ERROR LOGGING#####
Function Set-WriteToLog ($Write1)
{
Write-Host "$(Get-Date -format yyyy-MM-dd-hh-mm-ss)`t-`t$Write1"
}
#########START OF SCRIPT BODY#############
Start-Transcript -Path $OutputFile
set-WriteToLog "Install $Install_File"
$Process1 = Start-Process $Install_Path -ArgumentList $Install_Args -Wait -NoNewWindow -passthru
$ErrorVal = $Process1.exitcode
If (#(0,1641,3010) -contains $Process1.exitcode)
{
Set-WriteToLog "Success - Install $Install_File with exitcode $ErrorVal"
}
else
{
Set-WriteToLog "Error - Install error with exitcode $ErrorVal"
}
Stop-Transcript
Exit $LASTEXITCODE
I'm running SSISDeploy command (documentation is here) in my CMD:
SSISDeploy.exe -s:"download\Integration Services.ispac" -d:catalog;/SSISDB/TEST/DEVOPS;"TEST03,1234" -at:win
all working good, and now I need to run it thought powershell script (against windows server 2019 slave), so I tried this syntax:
$SSISDeploy = Start-Process -FilePath SSISDeploy.exe -ArgumentList '/source:"download\Integration Services.ispac"',"/destination:catalog;${Target};"${Env}"" -at:win -wait -PassThru -Credential $cred -RedirectStandardOutput ssisstdout.txt -RedirectStandardError ssisstderr.txt
but it fails with exception:
Start-Process : A positional parameter cannot be found that accepts argument 'TEST03,1234'.
+ ... SISDeploy = Start-Process -FilePath SSISDeploy.exe -ArgumentList '/so ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Start-Process], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.StartProcessCommand
Can you suggest what's wrong with the syntax?
$StartProcessProps = #{
FilePath = 'SSISDeploy.exe'
ArgumentList = '-s:"download\Integration Services.ispac" -d:catalog;{0};{1} -at:win' -f $Target, $Env
Wait = $true
PassThru = $true
Credential = $cred
RedirectStandardOutput = 'ssisstdout.txt'
RedirectStandardError = 'ssisstderr.txt'
}
$SSISDeploy = Start-Process #StartProcessProp
Long story short, I'm trying to dynamically use a parameter -Directory or -File in PowerShell's Get-ChildItem. Guess what? I'm unable to.
Here's the deal (note: pseudo-code):
Param(
[string]$filter = $(throw "Error: name"),
[string]$type = $(throw "error: file or directory")
)
if( $type -eq "file" ) {
$mode = '-File'
}
elseif( $type -eq "directory" ) {
$mode = '-Directory'
}
Function Find_Plugin_folder {
Write-Host "look for: '$($filter)'"
Invoke-Command -ComputerName (Get-Content servers.txt ) -ScriptBlock {
(Get-ChildItem -Path "z:\www" -Depth 5 $Using:mode -Filter $Using:filter -Recurse ) | %{$_.FullName}
} -ThrottleLimit 80
}
Find_Plugin_folder
$Using:mode is where it throws an error, either:
PS C:\Users\janreilink> v:\test.ps1 vevida-optimizer file
look for: 'vevida-optimizer'
A positional parameter cannot be found that accepts argument '-File'.
+ CategoryInfo : InvalidArgument: (:) [Get-ChildItem], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
+ PSComputerName : webserver-01.example.net
Or
PS C:\Users\janreilink> v:\test.ps1 vevida-optimizer directory
look for: 'vevida-optimizer'
A positional parameter cannot be found that accepts argument '-Directory'.
+ CategoryInfo : InvalidArgument: (:) [Get-ChildItem], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
+ PSComputerName : webserver-01.example.net
I've been reading about Dynamic Parameter sets all afternoon, but can't wrap my head around it yet. Any points are much (much, much) appreciated.
You'll want to use splatting for this instead. Start by creating a hashtable with some or all of the parameters you want to pass:
$dynamicArgs = #{}
if( $type -eq "file" ) {
$dynamicArgs['File'] = $true
}
elseif( $type -eq "directory" ) {
$dynamicArgs['Directory'] = $true
}
Then, inside Invoke-Command, prefix the variable name with # to indicate that you want to "splat" the arguments:
Get-ChildItem -Path "z:\www" -Depth 5 #Using:dynamicArgs -Filter $Using:filter -Recurse
If the splatting table contains the key File with a value of $true, it's the equivalent of adding -File:$true on the command line, and vice versa for the Directory argument
Basically I have file in my Windows machine of UTF8 code. Similar to this path directory and file "G:\这是一\个令人沮". And I am trying to write EICAR string (X5O!P%#AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*) to the file using PowerShell.
For regular file path it is being done like following:
#Base64 of Eicar string
[string] $EncodedEicar = 'WDVPIVAlQEFQWzRcUFpYNTQoUF4pN0NDKTd9JEVJQ0FSLVNUQU5EQVJELUFOVElWSVJVUy1URVNULUZJTEUhJEgrSCo='
if (!(Test-Path -Path $FilePath)) {
try {
[byte[]] $EicarBytes = [System.Convert]::FromBase64String($EncodedEicar)
[string] $Eicar = [System.Text.Encoding]::UTF8.GetString($EicarBytes)
Set-Content -Value $Eicar -Encoding ascii -Path $FilePath -Force
}
Tried the following suggestions didnt help :(
Executed powershell.exe "& {Import-Module C:\PROGRA~1\WindowsPowershell\Modules\new_eicar.psm1 -Force -DisableNameChecking ;New-Eicar -Path 'N:\这是一\个令人沮' -FileName 'eicar.com'; if ($?) {exit 0} else {exit 1}}". Result: {'status': 1, 'stderr': '', 'stdout': 'New-Eicar : Cannot validate argument on parameter \'Path\'. The "Test-Path $_ \r\n-PathType \'Container\'" validation script for the argument with value \r\n"N:\\\x8a\xa8T\x91~_\x84,?\\\x84,\xa6\x84\xaf\x0f\x84\xa7\xa7\x91\xfdr" did not return a result of True. Determine why the \r\nvalidation script failed, and then try the command again.\r\nAt line:1 char:116\r\n+ ... ew-Eicar -Path \'N:\\\x8a\xa8T\x91~_\x84,?\\\x84,\xa6\x84\xaf\x0f\x84\xa7\xa7\x91\xfdr\' -FileName \'eicar.com\'; if \r\n($?) {exit ...\r\n+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n + CategoryInfo : InvalidData: (:) [New-Eicar], ParameterBindingVa \r\n lidationException\r\n + FullyQualifiedErrorId : ParameterArgumentValidationError,New-Eicar\r\n \r\n'}
2017-08-30 23:31:12 DEBUG ssh.py:228 (TB) 10.5.22.4>> 'powershell.exe "& {Import-Module C:\PROGRA~1\WindowsPowershell\Modules\new_eicar.psm1 -Force -DisableNameChecking ;New-Eicar -Path 'N:\这是一\个令人沮' -FileName 'eicar.com'; if ($?) {exit 0} else {exit 1}}"', timeout: 300
2017-08-30 23:31:13 DEBUG ssh.py:306 (TB) 10.5.22.4<< '{
status: 1,
stderr: ,
stdout: New-Eicar : Cannot validate argument on parameter 'Path'. The "Test-Path $_
-PathType 'Container'" validation script for the argument with value
"N:\T~_,?\,r" did not return a result of True. Determine why the
validation script failed, and then try the command again.
At line:1 char:116
+ ... ew-Eicar -Path 'N:\T~_,?\,r' -FileName 'eicar.com'; if
($?) {exit ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [New-Eicar], ParameterBindingVa
lidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,New-Eicar
}'
Here's the code
$tool = "E:\Experiments\Popup\latest\xperf.exe"
$toolOutput = "XPerfOutput.log"
$toolError = "XPerfError.log"
$command = "-stop"
$x = Start-Process -FilePath $tool -ArgumentList $command -RedirectStandardOutput $toolOutput -RedirectStandardError $toolError -WindowStyle Hidden -PassThru -Wait
And Here's there error:
Start-Process : Parameter set cannot be resolved using the specified named parameters. At E:\Experiments\Popup\asd.ps1:9 char:1
+ Start-Process -FilePath $tool -ArgumentList $command -RedirectStandardOutput $toolOutput RedirectStandardError $toolError -WindowStyle Hidden
-PassThru -Wait
+ ~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Start-Process], ParameterBindingException
+ FullyQualifiedErrorId : AmbiguousParameterSet,Microsoft.PowerShell.Commands.StartProcessCommand
I want to run the process in a hidden window, wait for it to return and get the error, output and exit code.
According to the documentation for Start-Process, the combination of the redirection parameters (RedirectStandardOutput and RedirectStandardError) and the WindowStyle parameter is invalid since they exist in separate parameter sets.
This means that they cannot be used together. This is why you're receiving that particular error.