Execute powershell script in SSIS with parameters not successful - powershell

I have the following Powershell script:
#Set up server and AC parameters
param([string]$DBServer, [string]$ACString1, [string]$AcString2, [string]$ACString3, [string]$ACString4, [string]$ACString5, [string]$ACString6, [string]$ACString7, [string]$ACString8, [string]$ACString9, [string]$ACString10)
$ACString1 = $ACString1 -replace "'", ""
$ACString2 = $ACString2 -replace "'", ""
$ACString3 = $ACString3 -replace "'", ""
$ACString4 = $ACString4 -replace "'", ""
#Set up new session object for accessing production
$sess = new-pssession -computer $DBserver
#Execute AC
#invoke-command -session $sess -ScriptBlock {param($scriptACString)& 'C:\Program Files (x86)\LexisNexis\InterAction\IAAppCol\INTIATBC.EXE' Our Personnel/Personnel Bus Addr} -args $ACString invoke-command -session $sess -ScriptBlock {param($a, $b, $c, $d, $e, $f, $g, $h, $i, $j)& 'C:\Program Files (x86)\LexisNexis\InterAction\IAAppCol\INTIATBC.EXE' $a $b $c $d $e $f $g $h $i $j} -ArgumentList($ACString1, $AcString2, $AcString3, $AcString4, $AcString5, $AcString6, $AcString7, $AcString8, $AcString9, $AcString10)
This is set up this way because the executable it calls will not function if a single or double quote is passed along with any parameter. So I pass each token separately since passing it as one parameter would result in single quotes around every token.
When executing from powershell command prompt it is successful:
PS C:\users\mp071663_e> ./executeac.ps1 stvsqld08 our personnel
When I try to execute this in SSIS I can't get it to execute successfully. Using execute process task. Configured as follows:
Executable: C:\Windows\System32\WindowsPowerShell\v1.0\PowerShell.exe
Arguments: -ExecutionPolicy ByPass -command ". 'C:\Users\mp071663_e\ExecuteAC.ps1' stvsqld08 Our Personnel"
I've also tried the following:
Arguments: -ExecutionPolicy ByPass -command ". 'C:\Users\mp071663_e\ExecuteAC.ps1' 'stvsqld08' 'Our' 'Personnel'"
Arguments: -ExecutionPolicy ByPass -command ". 'C:\Users\mp071663_e\ExecuteAC.ps1' -$DBServer 'stvsqld08' -$ACString1 'Our' -$ACString2 'Personnel'"
Arguments: -ExecutionPolicy ByPass -command ". 'C:\Users\mp071663_e\ExecuteAC.ps1' -$DBServer stvsqld08 -$ACString1 Our -$ACString2 Personnel"
Any help is greatly appreciated.

Possibly a 32/64 bit issue? SSIS packages run from Visual Studio run as a 32 bit app, does your script work in 32 bit PowerShell?
Also have you set the WorkingDirectory?

Related

powershell start-process doesn't accept two commands in ArgumentList because they have a same parameter

I want to launch a admin powershell with two commands :
$command1 = "Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\{example}' -Name DHCPClassId -Value National"
$command2 = "Restart-NetAdapter -Name Ethernet"
Start-Process powershell -Verb 'RunAs' -ArgumentList "-NoExit","-Command &{$command1,$command2}"
And i have an error : he don't want to execute these two because they have a same parameter (-Name), so, what can i do ?
PowerShell's statement separator is ;, not , (the latter constructs arrays).
Also:
Even though passing arguments individually, as elements of an array to Start-Process is conceptually clean, it should be avoided due to a long-standing bug: pass a single string encoding all arguments to -ArgumentList - see this answer for more information.
When using PowerShell's CLI, -Command & { ... } is never necessary - just use -Command ...; that is, there is no reason to construct a script block ({ ... }) that you must then invoke with & - all commands given are directly executed by default.
To put it all together:
$command1 = "Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\{example}' -Name DHCPClassId -Value National"
$command2 = "Restart-NetAdapter -Name Ethernet"
Start-Process powershell -Verb RunAs "-NoExit -Command $command1; $command2"

Passing PowerShell variables to filepath

Completely new to Powershell but not new to programming. Anyway, Im trying to edit this script that was already created and it is almost working. I dont understand how to make Powershell pass a user assigned variable into the filepath for my invoke-command (\MICROS\Res\pos\scripts\$ScriptName) . Any help you can offer will be greatly appricated.
#Gather user input for name of script
$ScriptName=Read-Host "Enter the name of the script that you want to run [Examples: HH_Off.bat]"
#Loop through store array
foreach ($CurrentStore in $store) { #START LOOP
#How to call current store Name: $CurrentStore.Name
#How to call current store IP: $CurrentStore.IP
#How to call current store City: $CurrentStore.City
if ($RunListArray -contains $CurrentStore.ID){ #If the current store is in the input list
Write-Host " *** "$CurrentStore.City"("$CurrentStore.Name")"
$NetworkDrivePath = "\\" + $CurrentStore.IP + "\D$"
#Create Network Drives
New-PSDrive -Name $CurrentStore.Name -PSProvider FileSystem -Root $NetworkDrivePath -credential $mycred
#Check if site is responding
If (Test-Path -Path $NetworkDrivePath)
{
Write-Host " *** *** NETWORK DRIVE FOUND!!! PROCEEDING..."
Invoke-Command {powershell.exe -noprofile -ExecutionPolicy ByPass \MICROS\Res\pos\scripts\$ScriptName} -computername $CurrentStore.IP -credential $mycred
#REMOVE PS DRIVE
Remove-PSDrive $CurrentStore.Name
}
Else {
Write-Host " *** *** NETWORK DRIVE NOT FOUND, SENDING ERROR EMAIL"
$Subject = "*Testing*Powershell Error Send Files Script" + $CurrentStore.Name + " (" + $CurrentStore.City + ")"
$Body = "Network path " + $NetworkDrivePath + " is not accessible."
SendErrorEmail $Subject $Body
}
} #END LOOP
}
The variable is defined in the local (calling) session and not in the remote (Invoke-Command) session. It's referred to as scope. You can reach into the calling scope with the variable modifier $using: like this
Invoke-Command {powershell.exe -noprofile -ExecutionPolicy ByPass \MICROS\Res\pos\scripts\$using:ScriptName} -computername $CurrentStore.IP -credential $mycred
Or as a named or unnamed parameter with -ArgumentList
#named parameter
Invoke-Command {Param($script)powershell.exe -noprofile -ExecutionPolicy ByPass \MICROS\Res\pos\scripts\$script} -computername $CurrentStore.IP -credential $mycred -ArgumentList $ScriptName
#unnamed parameter
Invoke-Command {powershell.exe -noprofile -ExecutionPolicy ByPass \MICROS\Res\pos\scripts\$args[0]} -computername $CurrentStore.IP -credential $mycred -ArgumentList $ScriptName
Formatted and using splatting for readability
$sb = {
Param($script)
powershell.exe -noprofile -ExecutionPolicy ByPass \MICROS\Res\pos\scripts\$script
}
$params = #{
ScriptBlock = $sb
ComputerName = $CurrentStore.IP
Credential = $mycred
ArgumentList = $ScriptName
}
Invoke-Command #params
Also you probably can and should avoid the extra call to powershell.exe.

Calling script in elevated mode with more than one named argument

Test.ps1
Param (
[String]$CountryCode,
[String]$FilesPath,
[String]$KeepassDatabase,
[String]$KeepassKeyFile,
[String]$EventLog,
[String]$EventSource
)
Write-Host 'Ok' -ForegroundColor Yellow
Write-Host $PSBoundParameters
Start-Sleep -Seconds 5
The goal is to call the script with named parameters in elevated mode. When using named parameters without $Credential, it works fine. The window pops up and the word Ok is displayed:
$StartParams = #{
ArgumentList = "-File `"Test.ps1`" -verb `"runas`" -FilesPath `"S:\Files`" -CountryCode `"XXX`""
}
Start-Process powershell #StartParams
When I add the Credential argument it also pops-up but I can't see anything:
$StartParams = #{
Credential = Get-Credential
ArgumentList = "-File `"Test.ps1`" -verb `"runas`" -FilesPath `"S:\Files`" -CountryCode `"XXX`""
}
Start-Process powershell #StartParams
Am I missing something super obvious here? Even when using the same credentials as the logged on user, I can't see the text.
You need to specify an absolute path to the file. The new PowerShell-process (which will run as admin) doesn't run in the same working directory as your current session.
Try:
$StartParams = #{
FilePath = "powershell.exe"
Credential = Get-Credential
Verb = "RunAs"
ArgumentList = "-File `"c:\temp\Test.ps1`" -FilesPath `"S:\Files`" -CountryCode `"XXX`""
}
Start-Process #StartParams
If you only know the relative path, use Resolve-Path to convert it. Ex:
ArgumentList = "-NoExit -File `"$(Resolve-Path test.ps1 | Select-Object -ExpandProperty Path)`" -FilesPath `"S:\Files`" -CountryCode `"XXX`""
You should also look into string format or here-string so you can avoid escaping every double quote. It makes your life easier:
#Using here-string (no need to escape double quotes)
ArgumentList = #"
-NoExit -File "$(Resolve-Path test.ps1 | Select-Object -ExpandProperty Path)" -FilesPath "S:\Files" -CountryCode "XXX"
"#
#Using string format
ArgumentList = '-NoExit -File "{0}" -FilesPath "{1}" -CountryCode "{2}"' -f (Resolve-Path test.ps1 | Select-Object -ExpandProperty Path), "S:\Files", "XXX"

How to Invoke-Command and pass path to command as parameter

I'm tearing my hair out trying to invoke-command but pass the path to the exe as a parameter
eg:
I want to take this command
powershell Invoke-Command -ComputerName localhost -ScriptBlock { param($command ) C:\windows\system32\getmac.exe /$command } -ArgumentList ?
and translate it into a form like this
powershell Invoke-Command -ComputerName localhost -ScriptBlock { param($path, $command ) $path\getmac.exe /$command } -ArgumentList C:\windows\system32,?
I've tried all manner of quoting, ampersands and other contortions but can't get it to work. The above attempt results in
Unexpected token '\getmac.exe' in expression or statement.
At line:1 char:97
(I don't really want to invoke getmac on localhost, this is the runnable, SO distilled version)
Try this option. It shows me help for cscript.exe.
C:\>powershell.exe Invoke-Command -ComputerName localhost -ScriptBlock { param($path, $command ) cmd /c $path $command } -args '"C:\windows\system32\cscript.exe"','"/?"'
I tried other options using & and then path and arguments and it was giving me missing } exception. Then using cmd /c instead of & inside scriptblock fixed the issue.
Powershell won't parse a string as a command that way. For e.g. if you do this:
$path="C:\Windows\System32"
$path\getmac.exe
You would get the same error. The trick to work around this is to use the invoke operator &:
&$path\getmac.exe
or in your example, like this (also note that for a command that you pass to the powershell executable, you must wrap it in scriptblock braces):
powershell -command {Invoke-Command -ComputerName localhost -ScriptBlock { param($path, $command ) &$path\getmac.exe /$command } -ArgumentList C:\windows\system32,?}

Powershell: passing parameters to a job

I have a script that requires a number of parameters:
param ([string]$FOO="foo",[string]$CFG='\ps\bcpCopyCfg.ps1', [string]$CFROM="none", `
[string]$CTO="none", [switch]$HELP=$FALSE, [switch]$FULL=$FALSE, [string]$CCOL="none" `
,[string]$CDSQUERY="none", [string]$CMSSRV="none" `
,[string]$CSYBDB="none", [string]$CMSDB="none")
when called from the command prompt e.g.
powershell .\bcpCopy.ps1 -CFROM earn_n_deduct_actg -CTO fin_earn_n_deduct_actg -CCOL f_edeh_doc_id
everything works fine.
I need however to start several (dozens) instances of the script in parallel and I've written a wrapper script that calls the one doing the actual work as a job:
I prepare an array with the arguments (including the keywords like "-CFG") anhd pass it to start-job:
# Prepare script block to be released
$ARGS=("-CFG ", $CFG, "-CSYBDB ", $SYBDB, "-CMSDB ",$MSDB, "-CFROM ", $SYBTBL, "-CTO ",$MSTBL)
if ($FULL) {
$ARGS = $ARGS + " -FULL"
} else {
$ARGS = $ARGS + " -CCOL $($args[5]) "
}
"Argument array:"
$ARGS
start-job -scriptblock {powershell.exe -file '\ps\bcpCopy.ps1'} -ArgumentList $ARGS
Unfortunately, the called script does not receive the arguments: the caller prints the array and it looks fine:
Argument array:
-CFG
\ps\bcpCopyCfgOAH.ps1
-CSYBDB
vnimisro
-CMSDB
IMIS_UNOV
-CFROM
earn_n_deduct_ref
-CTO
fin_earn_n_deduct_ref
-FULL
but the output from the called scripts says that the only parameter received is the configuration file -- all the rest are at their default values.
PS C:\ps> receive-job 1391
12/17/2010 10:54:14 Starting the upload of table none; source db none;
12/17/2010 10:54:14 Target table is none; target db is none;
12/17/2010 10:54:14 Config file is \ps\bcpCopyCfg.ps1.
12/17/2010 10:54:14 Target server (MS SQL) is secap900-new
12/17/2010 10:54:14 Source database must be specified. Exiting...
Can you please point me what am I doing wrong?
I'm not sure what exactly you're trying to do, but this looks wrong:
start-job -scriptblock {
powershell.exe -file '\ps\bcpCopy.ps1'} -ArgumentList $ARGS
You are creating an entirely new powershell process needlessly. Try this instead:
start-job -scriptblock {
& 'c:\ps\bcpCopy.ps1' #args } -ArgumentList $ARGS
The "#args" syntax is called "splatting." This will expand the passed arguments and ensure each element is treated as a parameter. The ampersand (&) is the "call" operator.
Another way is to put the # before the array. I changed the $ARGS variable to $flags to differentiate $args in the scriptblock from $flags.
$flags = #("-CFG ", $CFG, "-CSYBDB ", $SYBDB, "-CMSDB ",$MSDB, "-CFROM ", $SYBTBL, "-CTO ",$MSTBL)
If($FULL) {
$flags = $flags + " -FULL"
}
Else {
$flags = $flags + " -CCOL $($args[5]) "
}
"Argument array:"
$flags
start-job -scriptblock {powershell.exe -file '\ps\bcpCopy.ps1' $args} -ArgumentList $flags