Passing parameters between Powershell scripts - powershell

I simply want to be able to pass one parameter from one PS script to another, currently my script (script1) is as follows (all thanks to user CB):
$filepath = Resolve-Path "script2.ps1"
start-process -FilePath powershell.exe -ArgumentList "-file `"$($filepath.path)`""
This succesfully opens another script in via another powershell instance. Now i want to be able to carry across a parameter to the 'script2.ps1' script. I have tried the following but this doesnt not work:
script1.ps1
$name = read-host "The name"
$filepath = Resolve-Path "script2.ps1"
start-process -FilePath powershell.exe -ArgumentList "-file `"$($filepath.path)`"-name $name"
script2.ps1
Param(
[string]$name
)
write-host $name
This should simply pass over $name from script1 into $name in script2. I think im close but not quite close enough!
Thanks for any help!

The only problem I see is that you are missing a space after the last escaped ", try this:
start-process -FilePath powershell.exe -ArgumentList "-file `"$($filepath.path)`" -name $name"

Is there a specific reason why you want to run the second script in a separate instance of Powershell? If not, you would do much better just to run the script directly:
$name = read-host "The name"
.\script2.ps1 -name $name
This way you don't have to worry about escaping any of the parameters.
The way you were doing it forces all of the parameters to be converted to strings and processed by Windows command line processing. That can be a nightmare to ensure values get through in a usable form. If instead you just invoke the script directly you can pass objects as parameters and Powershell is all about using objects rather than strings.

Related

Problem using a for loop and start-process to call powershell script

Could someone please help me on this. I have created two powershell script one is suppose to call the other one lets call it script2.ps1
script2.ps1 - accepts two arguments computername and the type of remediation
example:
list=get-content c:\computer.txt
foreach ($pc in $list){
start-process powershell.exe -ArgumentList "-noexit", "-file `C:\temp\client fix\script2.ps1`", "-type install", "-computer $i"
}
The intention is for each computer in the list to execute script2.ps1 on separate process. The script runs fine if start-process is not being used example:
powershell.exe -file 'C:\temp\client fix\Script2.ps1' -type install -computer $i
The Start-Process help explains:
Specifies parameters or parameter values to use when this cmdlet starts the process. If parameters or parameter values contain a space, they need surrounded with escaped double quotes.
Your file paramater does not have an escaped double quote, but a backtick that is doing nothing.
start-process powershell.exe -ArgumentList "-noexit", "-file `"C:\temp\client fix\script2.ps1`"", "-type install", "-computer $i"
Furthermore you mix arguments for powershell.exe (-noexit, -file) with arugments for your script (-type, -computer). Also your variable $i is never assigned.
Anyways, more important is to know, that there is no reason for start-process. Simplify your script by using the call operator &.
$list=get-content c:\computer.txt
foreach ($pc in $list){
& "C:\temp\client fix\script2.ps1" -type install -computer $pc
}

Passing arguments as a variable when installing an MSI using Start-Process

I am new to Powershell and, of course, trying to learn on the fly for a project- No pressure, right! :-)
I am working on a script to run an MSI package in quiet mode, passing it an activation code as an argument, that I have to extract from an XML file.
So far, I have everything working except for getting Start-Process to run the MSI with the arguments being passed in a Variable.
Set-ExecutionPolicy Bypass -Force
[System.Xml.XmlDocument]$XML_Doc = new-object System.Xml.XmlDocument
$XML_Doc.load('c:\myfolder\Configinfo.XML')
$ActivationID = $XML_Doc.CONFIGINFO.SITEINFO.ACTIVATEID
write-host "Activation Id is: $ActivationID"
$InstallString = "`'/I C:\myfolder\myinstaller.msi akey="+'"'+$ActivationID+'"'''
#$InstallString = "`'/I C:\myfolder\myinstaller.msi akey=`"$($ActivationID)`"'"
write-host "$InstallString"'''
Start-Process msiexec.exe -ArgumentList $InstallString -Wait -NoNewWindow
#Start-Process msiexec.exe -ArgumentList '/I C:\myfolder\myinstaller.msi akey="12345678-abcd-1a1b-x9x1-a1b2c3d4e5f6"' -Wait -NoNewWindow
Above is the code I am working with now. The last line that is commented out is an activation string that works.
I have verified that $ActivationID is pulling back the correct value, and that $InstallString mirrors the argument list in the commented version of the Start-Process string.
Any help would be appreciated!
The Start-Process commands aren't necessary. PowerShell is a shell. It can run commands. Just put the commands you want to run directly in the script.
msiexec /i "C:\myfolder\myinstaller.msi" "AKEY=$ActivationID"
I quoted the parameters to msiexec.exe in case any of them contain spaces. PowerShell will automatically expand the $ActivationID variable into the string inside the double quotes.
Your ArgumentList is being passed incorrectly.
[Xml]$XML_Doc = Get-Content -Path 'C:\myfolder\Configinfo.xml'
$ActivationID = $XML_Doc.CONFIGINFO.SITEINFO.ACTIVATEID
Write-Host "Activation Id is: $ActivationID"
$Path = 'msiexec'
$ArgList = #('/i','"C:\path\file.msi"',"akey=`"$ActivationID`"")
Write-Host "$Path $ArgList"
Start-Process -FilePath $Path -ArgumentList $ArgList -Wait -NoNewWindow
First off, let me welcome you to Powershell! It's a great language and a great community gathered around a common cause.
Since you're new to the language, you can still learn new tricks and that's a good thing, because it's generally accepted that the Write-Host cmdlet is nearly always a poor choice. If you don't trust me, you should trust the inventor of Powershell.
Now that that's out of the way, we should look at your MSI command. With Powershell, we don't have to directly open msiexec, and we can call the MSI directly. I would break the path to the installer into its own variable, and then we can add all of our arguments on top of it. Also, don't forget the "/qn" switch which will actually make all of this silent. All in all, your new script will look something like this:
[System.Xml.XmlDocument]$XML_Doc = new-object System.Xml.XmlDocument
$XML_Doc.load('c:\myfolder\Configinfo.XML')
$ActivationID = $XML_Doc.CONFIGINFO.SITEINFO.ACTIVATEID
Write-Verbose "Activation Id is: $ActivationID"
$msipath = "C:\myfolder\myinstaller.msi"
$args = #("akey=$ActivationID", "/qn")
Write-Verbose "Install path is $msipath"
Write-Verbose "Activation key is $akey"
Start-Process $msipath -ArgumentList $args -Wait -NoNewWindow

Start-Process and the Stop Parsing (--%) parameter

I am having trouble getting the --% parameter to work as expected. My $TaskParams variable has the character '<' which is interpreted as a redirection by powershell, therefore needs to be escaped.
However the following does not work:
$CreateTask = Start-Process PowerShell.exe "$ScriptLocation --% $TaskParams" -Wait -PassThru
Without the --%, and when I manually remove any '<' characters, it works:
$CreateTask = Start-Process PowerShell.exe "$ScriptLocation $TaskParams" -Wait -PassThru
error received:
Start-Process : A positional parameter cannot be found that accepts argument
'--%'.
note: I am using PS 5.0
Am I using the --% parameter wrong? Any help or pointers is appreciated. Thanks
The stop-parsing symbol --% only works when calling executables directly or with the call operator &; it's not for use when calling PowerShell scripts / functions / cmdlets.
You do not need to spin up a new copy of powershell.exe or use Start-Process to run a script from within another script. Just put the script command and its parameters as a line from within the other script. For example, suppose you have script2.ps1:
param(
[String] $Name
)
Write-Host "Hello, $Name"
Now suppose you also have script1.ps1:
Write-Host "This is script1.ps1"
.\Script2.ps1 -Name "Bill Stewart"
Write-Host "script1.ps1 is finished"
If you now run script1.ps1:
PS C:\> .\Script1.ps1
This is script1.ps1
Hello, Bill Stewart
script1.ps1 is finished
If you really want to use Start-Process you could encode the argument, and run it as such. I use something similar to this when elevating past UAC:
$Code = ". '$ScriptLocation' $TaskParams"
$Encoded = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($code))
Start-Process PowerShell.exe -ArgumentList "-EncodedCommand",$Encoded -Wait -PassThru
I'm fairly certain that would accomplish what you're looking for.

Passing variable arguments using PowerShell's Start-Process cmdlet

Good evening everyone,
I'm using a command line that passes arguments to as variables in the following scripts to be run in another ps1 that I'm calling from within this script. Whenever I try to pass the arguments from the command line I get the following error though
Start-Process : A positional parameter cannot be found that accepts
argument
Would anyone be able to assist?
Thank you for your time and much appreciate any help.
param
(
[string]$targetserver = $args[0], #target server
[string]$module = $args[1], #module name
)
function Get-Script-Directory
{
return Split-Path $script:MyInvocation.MyCommand.Path
}
Start-Process powershell.exe (Join-Path (Get-Script-Directory) "...\StopServices.ps1") -ArgumentList $targetserver $module
Try this for the last line
$scriptPath = Join-Path (Get-Script-Directory) "...\StopServices.ps1"
Start-Process powershell.exe -ArgumentList "-file $scriptPath", $targetserver, $module
Update due to comment: To show you that it is working see the GIF below - so you may check it again or insert some debug output to see where things go wrong with your script

Call another powershell pass parameter use different creds

I want to call another secondary powershell script from within my primary powershell script. I want to pass it a parameter from the primary script, the secondary script needs the username parameter, I want to pass to it, from the primary, and then have the secondary script Im calling use different credentials. I think I might be able to use invoke-command, I just dont know all the syntax, anyone able to post some examples of what I want to accomplish, and then I'll fill in the blanks if need be?
Thanks in advance! :-)
Assume that your secondary script looks like this:
param (
[string] $Username = $args[0]
)
Write-Output -InputObject $Username;
You can use the Start-Process cmdlet to launch the script with alternate credentials.
$Credential = Get-Credential;
Start-Process -Wait -NoNewWindow -FilePath powershell.exe -ArgumentList '"c:\path\to my\file.ps1" -Username "UsernameGoesHere!"' -Credential $Credential;
Or you can use the Invoke-Command cmdlet:
Invoke-Command -FilePath 'c:\path\to my\script.ps1' -Credential $Credential -ArgumentList "UsernameGoesHere!";
I got it, thanks to Trevor Sullivan for pointing me in the right direction.
I ended up just putting my second ps1 file into a scriptblock, and running it as a job, and passing it the arguments from the main script, like this
$job = Start-Job -scriptblock {
param ($username)
some code to run against the variable that was passed in
} -Args $target -credential $Cred
$target being the variable I want to pass to my scriptblock
$username being the parameter that the scriptblock accepts
Thanks.