I want to call a VBScript located on a server with a PowerShell script, I want to pass parameters in the VBS by using invoke-command.
Code:
$username = [Environment]::UserName # Get the current user name
# Get with a Credential the logins to connect to an AS400 Server
$credential = $host.ui.PromptForCredential("Login", "Please enter your ID.", "", "")
$ASUser = $credential.Username.Substring(1)
$ASPwrd = $credential.GetNetworkCredential().password
# Call of the VBS on the server with these parameters
Invoke-Command -ComputerName MyServerName -ScriptBlock {
CSCRIPT "C:\MyScript.vbs"
} -ArgumentList $username, $ASUser, $ASpwrd
But I've got an issue caused by the parameters in the VBS, at these lines:
User = WScript.Arguments(0)
UID = WScript.Arguments(1)
PWD = WScript.Arguments(2)
The PowerShell script returns me this error:
C:\MyScript.vbs(64, 1) Microsoft VBScript runtime error: Subscript out of range
+ CategoryInfo : NotSpecified: (C:\Excel Script...pt out of range:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
The line 64 is User = WScript.Arguments(0).
It seems that my VBS does not recognize that I pass parameters, so I think the problem comes from the PS script, I also tried to pass the parameters like this:
Invoke-Command -ComputerName MyServerName -ScriptBlock {
CSCRIPT "C:\MyScript.vbs" $username $ASUser $ASpwrd
}
It does not work.
You're passing arguments into the scriptblock, but you never use them.
Change this:
Invoke-Command -ComputerName MyServerName -ScriptBlock {
CSCRIPT "C:\MyScript.vbs"
} -ArgumentList $username, $ASUser, $ASpwrd
into something like this:
Invoke-Command -ComputerName MyServerName -ScriptBlock {
CSCRIPT "C:\MyScript.vbs" $args[0] $args[1] $args[2]
} -ArgumentList $username, $ASUser, $ASpwrd
or this:
Invoke-Command -ComputerName MyServerName -ScriptBlock {
Param($user, $user2, $pass2)
CSCRIPT "C:\MyScript.vbs" $user $user2 $pass2
} -ArgumentList $username, $ASUser, $ASpwrd
Related
I am trying to follow this article to expand a variable in a scriptblock
My code tries this:
$exe = "setup.exe"
invoke-command -ComputerName $j -Credential $credentials -ScriptBlock {cmd /c 'C:\share\[scriptblock]::Create($exe)'}
How to fix the error:
The filename, directory name, or volume label syntax is incorrect.
+ CategoryInfo : NotSpecified: (The filename, d...x is incorrect.:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
+ PSComputerName : remote_computer
You definitely don't need to create a new script block for this scenario, see Bruce's comment at the bottom of the linked article for some good reasons why you shouldn't.
Bruce mentions passing parameters to a script block and that works well in this scenario:
$exe = 'setup.exe'
invoke-command -ComputerName $j -Credential $credentials -ScriptBlock { param($exe) & "C:\share\$exe" } -ArgumentList $exe
In PowerShell V3, there is an even easier way to pass parameters via Invoke-Command:
$exe = 'setup.exe'
invoke-command -ComputerName $j -Credential $credentials -ScriptBlock { & "C:\share\$using:exe" }
Note that PowerShell runs exe files just fine, there's usually no reason to run cmd first.
To follow the article, you want to make sure to leverage PowerShell's ability to expand variables in a string and then use [ScriptBlock]::Create() which takes a string to create a new ScriptBlock. What you are currently attempting is to generate a ScriptBlock within a ScriptBlock, which isn't going to work. It should look a little more like this:
$exe = 'setup.exe'
# The below line should expand the variable as needed
[String]$cmd = "cmd /c 'C:\share\$exe'"
# The below line creates the script block to pass in Invoke-Command
[ScriptBlock]$sb = [ScriptBlock]::Create($cmd)
Invoke-Command -ComputerName $j -Credential $credentials -ScriptBlock $sb
I'm trying to get the Invoke-Command cmdlet working with a CredSsp session by passing a locally defined function.
I have two local functions:
MyCopy which just invokes Copy-Item cmdlet on passed params with additional switches
MyCopyReturn which is the same as above, but in addition has return statement at the end
Now when I pass those functions to Invoke-Command without -Session parameter, they both succeed.
However, when specifying -Session for Invoke-Command, MyCopy fails with following exception (2. case):
Cannot bind argument to parameter 'Path' because it is null.
+ CategoryInfo : InvalidData: (:) [Copy-Item], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.CopyItemCommand
+ PSComputerName : localhost
Could someone please explain why result of passing MyCopyReturn is different from passing MyCopy?
function MyCopy ($from, $to) {
Copy-Item $from $to -Force -Recurse -Verbose
}
function MyCopyReturn ($from, $to) {
Copy-Item $from $to -Force -Recurse -Verbose
return
}
$credential = Get-Credential
$computerName = 'localhost'
$session = New-PSSession -ComputerName $computerName -Credential $credential -Authentication Credssp
# src is a file
$src = "c:\sandbox\a\test"
# dest is a directory
$dest = "c:\sandbox\b"
# 1.
# MyCopy works fine without giving session
Invoke-Command -ScriptBlock ${function:MyCopy} -ArgumentList $src,$dest
# 2.
# MyCopy DOESN'T WORK when session is given
Invoke-Command -Session $session -ScriptBlock ${function:MyCopy} -ArgumentList $src,$dest
# 4.
# MyCopyReturn works fine without the session
Invoke-Command -ScriptBlock ${function:MyCopyReturn} -ArgumentList $src,$dest
# 3.
# MyCopyReturn works fine with session too
Invoke-Command -Session $session -ScriptBlock ${function:MyCopyReturn} -ArgumentList $src,$dest
Remove-PSSession $session
I make some digging with ILSpy and can say, that the problem in the bug in ScriptBlock.GetPowerShell method. It does not bind parameters properly, if them come not from param block:
function f($Arg){write "`$Arg=`"$Arg`";`$Args=`"$Args`""}
function g{param($Arg) write "`$Arg=`"$Arg`";`$Args=`"$Args`""}
$Function:f.GetPowerShell('Test1','Test2').Invoke()
# $Arg="";$Args="Test1 Test2"
$Function:g.GetPowerShell('Test1','Test2').Invoke()
# $Arg="Test1";$Args="Test2"
As you can see, $Function:f.GetPowerShell('Test1','Test2') bind both arguments to $Args automatic variable and nothing get bound to $Arg. So when you invoke this command
Invoke-Command -Session $session -ScriptBlock ${function:MyCopy} -ArgumentList $src,$dest
$from and $to does not get bound properly and cause error.
Why error does not happens when you not use -Session parameter?
Looks like Invoke-Command have to convert ScriptBlock to PowerShell to invoke command in remote session and that does not required when ScriptBlock invoked locally.
Why MyCopyReturn does not cause same error?
Not all ScripBlocks can be converted to PowerShell by GetPowerShell method (in particular, it is required that ScriptBlock must have a single statement, having another statement return violate this). If that is the case (GetPowerShell throws ScriptBlockToPowerShellNotSupportedException), than Invoke-Command use some backup scenario to convert ScriptBlock to PowerShell and that scenario does not suffer from bug of GetPowerShell method.
I have a strange problem with one of my servers :
I am trying to open a PSsession with it.
If I copy my script directly in powershell everything works fine, but if i run it via a .ps1 file I get a access denied error.
The same sript works on multiple machines except this one.
Additonal information:
Executing Server : Server 2012
Target Server2003SP2
Another Server2003SP2 is working fine without a Problem
the Client Server was configured using :
Enable-PSRemoting -Force
Set-Item wsman:\localhost\client\trustedhosts MY2012Server -concatenate -force
Restart-Service WinRM
And the Error Message:
New-PSSession : [Server2003SP2] Connecting to remote server Server2003SP2 failed with the following error message : Access is denied. For more information,
Help topic.
At C:\Users\Administrator\Desktop\Script.ps1:23 char:13
+ $Session = New-PSSession -ComputerName $Servername -credential $Cred #-sessionO ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OpenError: (System.Manageme....RemoteRunspace:RemoteRunspace) [New-PSSession], PSRemotingTransportException
+ FullyQualifiedErrorId : AccessDenied,PSSessionOpenFailed
Edit : My full SCript as requested :
$Password = "Hereismypasswordwith#and€init"
$Username = "Servername\Administrator"
$Servername = "Servername"
$Language = {
$oscode = Get-WmiObject Win32_OperatingSystem -ErrorAction continue
$oscode = $oscode.oslanguage
$switch = switch ($oscode){
1031 {"Deutsch"};
1033 {"English"};
default {"English"};
}
write-host $switch
return $switch
}
$SecurePassWord = ConvertTo-SecureString -AsPlainText $Password -Force
$Cred = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList $Username, $SecurePassWord
$pssessionoption = new-pssessionoption -operationtimeout 7200000 -IdleTimeout 7200000
$Session = New-PSSession -ComputerName $Servername -credential $Cred -sessionOption $pssessionoption
Invoke-Command -Session $Session -Scriptblock $Language
Remove-PSSession -Session $Session
UPDATE :
it seems to be something within the Char encoding.
the password in the ps1 file produces a difrent output for the € in it :
in the ps1. ¬
in the ps window : ?
if i pass the Password as a Paramter it also works.
$password.gethash() also prouces difrent outputs. codepage is the same though (chcp)
the script was created in notepad++
Changing / Converting to ansi from UTC without BOM fixed the issue.. jesus crist who thinks about stuff like that / why the hell was it set to this value..
I am running the below powershell command:
$cmd = "xxx.exe"
Invoke-Command -ComputerName localhost {Invoke-Expression $cmd}
However I get the error:
Cannot bind argument to parameter 'Command' because it is null.
+ CategoryInfo : InvalidData: (:) [Invoke-Expression], ParameterB
indingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,M
icrosoft.PowerShell.Commands.InvokeExpressionCommand
Look at the documentation for Invoke-Command.
Use either the -ArgumentList parameter or if powershell 3 see example 9 ($Using:).
http://technet.microsoft.com/en-us/library/hh849719.aspx
ArgumentList Example -
$cmd = "xxx.exe"
Invoke-Command -ComputerName localhost {Invoke-Expression $args[0]} -ArgumentList $cmd
If you use param in the script block you can used named arguments rather than the $args built-in.
I am going to show you the way I do it, passing a file with -FilePath and passing the parameters with -ArgumentList
I create a function that is going to contain the code I want to execute.
#remote_functions.ps1
param($command, $param1, $param2, $param3, $param4, $param5)
$ScriptVersion = "1.0"
function Write5Strings($string1, $string2, $string3, $string4, $string5)
{
Write-Host "String1: $string1"
Write-Host "String2: $string2"
Write-Host "String3: $string3"
Write-Host "String4: $string4"
Write-Host "String5: $string5"
throw "ERROR"
}
try
{
&$command $param1 $param2 $param3 $param4 $param5
}
catch [System.Exception]
{
Write-Error $_.Exception.ToString()
exit 1
}
And I invoke it this way:
$server="server"
$remotingPort=81
$job = Invoke-Command -AsJob -Port $remotingPort -ComputerName $server -FilePath ".\remote_functions.ps1" -ArgumentList #("Write5Strings", "apple", "banana", "orange", "pear", "watermelon")
Check also this question: How do I pass named parameters with Invoke-Command?
I face an issue when I run the following command
$x = "c:\Scripts\Log3.ps1"
$remoteMachineName = "172.16.61.51"
Invoke-Command -ComputerName $remoteMachineName -ScriptBlock {& $x}
The expression after '&' in a pipeline element produced an invalid object. It must result in a command name, script
block or CommandInfo object.
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : BadExpression
+ PSComputerName : 172.16.61.51
Issue is not seen if I dont use $x variable
Invoke-Command -ComputerName $remoteMachineName -ScriptBlock {& 'c:\scripts\log3.ps1'}
Directory: C:\scripts
Mode LastWriteTime Length Name PSComputerName
---- ------------- ------ ---- --------------
-a--- 7/25/2013 9:45 PM 0 new_file2.txt 172.16.61.51
Variables in your PowerShell session are not transferred to sessions created with Invoke-Command
You need to use the -ArgumentList parameter to send the variables your command and then use the $args array to access them in the script block so your command will look like:
Invoke-Command -ComputerName $remoteMachineName -ScriptBlock {& $args[0]} -ArgumentList $x
If you work with variables inside a script block you need to add the modifier using:. Otherwise Powershell would search for the var definition inside the script block.
You can use it also with the splatting technique. E.g.:#using:params
Like this:
# C:\Temp\Nested.ps1
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)]
[String]$Msg
)
Write-Host ("Nested Message: {0}" -f $Msg)
# C:\Temp\Controller.ps1
$ScriptPath = "C:\Temp\Nested.ps1"
$params = #{
Msg = "Foobar"
}
$JobContent= {
& $using:ScriptPath #using:params
}
Invoke-Command -ScriptBlock $JobContent -ComputerName 'localhost'