How to pass arguments to MSI file with PowerShell - powershell

I've read that you can pass arguments to a .msi file, but I have no idea how to do it correctly. I've tried the following, where $ArgumentList is an array.
$ArgumentList = #("/i .\NSClient v67.msi", "/norestart", "/quiet", "/l*v '$directory'", "token=$token", "host=$_host", "mode=$mode")
Start-Process "msiexec" -ArgumentList $ArgumentList -Wait -NoNewWindow
This is part of my script, where I'm trying to install NetSkope on my machine by executing a command.
In theory, the command should look like msiexec /i "NSClient v67.msi" token=loremipsum host=bryan.goskope.com mode=peruserconfig /norestart /quiet /l*v "C:\Temp\NetskopeInstallation.log.
#Find file path
$rawPath = Invoke-Expression -Command 'C:\Windows\System32\WHERE /r C:\Users\ /f NSClient*.msi'
#Extract the directory
$filePath = Invoke-Expression -Command "cmd.exe --% /c FOR /f ""tokens=1"" %A IN ($rawPath) DO (ECHO
'%~dpA')"
#Cast $filePath to work with string methods
$filePath = Out-String -InputObject $filePath
$filePath = $filePath.split("'")[1]
Invoke-Expression -Command "cmd.exe --% /c cd $filePath"
$ArgumentList = #("/i .\NSClient v67.msi", "/norestart", "/quiet", "/l*v '$directory'",
"token=$token", "host=$_host", "mode=$mode")
Start-Process "msiexec" -ArgumentList $ArgumentList -Wait -NoNewWindow

I would also recommend using the Powershell MSI Module
Concerning Start-Process:
-Argumentlist expects string as a type. I don't think you can just pass an array.
You also need to surround the parameters that require a space with escaped double quotes. The escape character is powershell is the grave-accent(`).
Another problem is that the variable $directory will never be expanded, because it is surrounded with single quotes. You need to remove those.
The following should work for your example, but I personally would just remove the space in the file name, since you don't need to do weird stuff with escaping.
Without escaping:
$ArgumentList = "/i .\NSClientv67.msi /norestart /quiet /l*v $directory token=$token host=$_host mode=$mode"
With escaping:
$ArgumentList = "/i `".\NSClient v67.msi`" /norestart /quiet /l*v $directory token=$token host=$_host mode=$mode"

Here's a slightly different syntax:
$MSIArguments = #(
"/x"
"`"C:\path with spaces\test.msi`""
"/qb"
"/norestart"
"/l*v"
"`"C:\path with spaces\test.log`""
)
Start-Process "msiexec.exe" -ArgumentList $MSIArguments -Wait -NoNewWindow

Related

How to add variables in a call to Start-Process

I'm building a PowerShell script to run the following command on various servers:
arapx acc, Export ExportFile=\"C:\\Temp\\DEV_Refresh\\AccExport.txt\"
This code works:
Start-Process -FilePath '\\<fileserver>\Bin\arapx' -argumentList 'acc, Export ExportFile=\"C:\\Temp\\DEV_Refresh\\AccExport.txt\"'
Different servers have different paths for the output file so I tried to set a variable. But this fails:
$Dest_Folder="DEV_Refresh"
Start-Process -FilePath '\\<fileserver>\Bin\arapx' -argumentList 'acc, Export ExportFile=\"C:\\Temp\\${Dest_Folder}\\AccExport.txt\"'
This fails:
$Dest_Folder="DEV_Refresh"
Start-Process -FilePath '\\<fileserver>\Bin\arapx' -argumentList 'acc, Export ExportFile=\"C:\\Temp\\$(Dest_Folder)\\AccExport.txt\"'
And this fails:
$Dest_Folder="DEV_Refresh"
$argumentList = "'acc, Export ExportFile=\""C:\\Temp\\" + $Dest_Folder + "\\AccExport.txt\""'"
Start-Process -FilePath '\\<fileserver>\Bin\arapx' -argumentList $argumentList
Can anyone help me get the command to work with a varable?
The solution from zett42 works:
$Dest_Folder="DEV_Refresh"
Start-Process -FilePath '\\<fileserver>\Bin\arapx' -argumentList ('acc, Export ExportFile=\"C:\\Temp\\' + $Dest_Folder + '\\AccExport.txt\"')

PowerShell verbose Start-Process command

I have a PowerShell script that starts a process:
$pythodDir, $argsOriginalList = $args
$pythonExePath = Join-Path $pythodDir "python.exe"
$argsList = #("--no-render") + $argsOriginalList
Start-Process -FilePath $pythonExePath -ArgumentList $argsList
I wish to see the full command line of the Start-Process for example:
C:\python\python.exe --no-render --arg1 value
I didn't find a flag to render the full command that Start-Process creates. Is there any way to verbose it?
You can get the command line by grabbing two properties from the ProcessInfo of the process you started:
# Capture the process object using -PassThru
$p = Start-Process -FilePath $pythonExePath -ArgumentList $argsList -PassThru
# Output the command line
($p.StartInfo.FileName,$p.StartInfo.Arguments) -join ' '
For example:
$p = Start-Process -FilePath 'Notepad.exe' -ArgumentList 'c:\folder\file.txt' -PassThru
($p.StartInfo.FileName,$p.StartInfo.Arguments) -join ' '
C:\WINDOWS\system32\notepad.exe C:\folder\file.txt

How to passing external argument by call other powershell script?

I want to call another powershell script with external argument. I try this but return error. anyone can help please
$direct = "D:\Learn"
Start-Process powershell.exe -WindowStyle Minimized ".\Testing.exe" -Path $direct
Testing.exe
Param(
[parameter(mandatory=$true)][string]$Loc
)
Get-Content $Loc\API.txt
Pause
The Start-Process cmdlet has a -AgumentList parameter:
$direct = "D:\Learn"
Start-Process powershell.exe -WindowStyle Minimized ".\Testing.exe" -ArgumentList "-Path $direct"
If you want to just run a File with some arguments
$filepath = ".\Testing.exe"
$direct = "D:\Learn"
Start-Process -FilePath $filepath -ArgumentList $direct -Wait -NoNewWindow
I think they all were arguments of powershell.exe.
The whole argument can be wrapped in one double quote in argumentlist.
Start-Process "powershell.exe" -ArgumentList "-windowstyle minimized '.\testing.exe' -path $direct"
Or even it can be done without start-process:
& "powershell.exe -windowstyle minimized '.\testing.exe' -path $direct"

Trouble with Expanding $Env:TEMP in start-process MSIEXEC

I have been unable to understand why the following command don't trigger the silent installation of Power-Bi -
Start-Process msiexec -wait -ArgumentList '/i $ENV:Temp\PBIDesktop_x64.msi /qn /norestart ACCEPT_EULA=1'
where as the following works -
Start-Process msiexec -wait -ArgumentList '/i C:\Users\ADMINI~1\AppData\Local\Temp\PBIDesktop_x64.msi /qn /norestart ACCEPT_EULA=1
'
I am using an elevated ISE but the first command generates no errors and does nothing. I think that the $ENV:TEMP is not expanding. Please help.
regards,
Prateek
Powershell won't extend anything in a string if you're using single-quoted-ticks instead of double quotes. So change your code to:
Start-Process msiexec -wait -ArgumentList "/i $ENV:Temp\PBIDesktop_x64.msi /qn /norestart ACCEPT_EULA=1"
This link describes the quotation rules.
In short:
> $i = 1
> "Double quotes: $i + $i"
Double quotes: 1 + 1
> 'Single quotes: $i + $i'
Single quotes: $i + $i
Hope that helps

In Powershell how can I pass an array as an argument, which is one of multiple arguments to Start-Process -ArgumentList

ScriptToInvoke.ps1:
[CmdletBinding()]
param (
[Parameter(Mandatory=$True)]
[string[]]$StringArray,
[ValidateSet('Mode1', 'Mode2', 'Mode3')]
[string]$Mode = 'Mode1'
)
$count = $StringArray.Count
Write-Verbose ("String array count ($count): $StringArray")
ScriptCallingStartProcess.ps1:
$stringArray = #('String1','String2','String3')
Start-Process powershell -Verb RunAs
-ArgumentList "-NoExit -File ScriptToInvoke.ps1 -StringArray ""$stringArray"" -Mode Mode3 -Verbose"
In this case the $stringArray is treated as an array containing one element:
screen capture of script run output
I have tried multiple variations passing the $stringArray argument:
-StringArray $stringArray
-StringArray #($stringArray)
-StringArray #(,#($stringArray))
each with the same error:
A positional parameter cannot be found that accepts argument 'String2'
As I understand it the double quotes around the ArgumentList value result in any variable being parsed. Is it possible to prevent this from happening? Or is there an alternative approach?
My use case involves attempting to re-run the Powershell script with elevated permissions to uninstall a Windows update, which is why I use Start-Process with -Verb RunAs.
Here's one way. ScriptCallingStartProcess.ps1:
$stringArray = #('String1','String2','String3')
$OFS=","
Start-Process powershell.exe -Verb Runas "-NoExit -File \ScriptToInvoke.ps1 $stringArray -Mode Mode3 -Verbose"
ScriptToInvoke.ps1:
[CmdletBinding()]
param (
[Parameter(Mandatory=$True)]
[String] $InputData,
[ValidateSet('Mode1', 'Mode2', 'Mode3')]
[string]$Mode = 'Mode1'
)
$StringArray = $InputData -split ','
$count = $StringArray.Count
Write-Verbose ("String array count ($count): $StringArray")
(that is, pass a comma-delimited string as first parameter, then split inside second script)
I escaped the double quotes, and it seems to work ok:
Start-Process powershell -Verb RunAs -ArgumentList "-NoExit -File test.ps1 -StringArray `"$stringArray`" -Mode Mode3 -Verbose"