I'm trying to run Invoke-Command within a PowerShell script to run scripts on remote servers. It retrieves the computer names and scripts to run from an XML file. Code sample is below. The script executes but nothing on the remote server is being run. I've tried 2 different ways to run Invoke-Command.
[string] $computer = "lumen"
[string] $scriptBlock = "cd C:\Scripts\Update-Apps; ./Update-Apps"
$session = New-PSSession -ComputerName $computer
Invoke-Command -Session $session -ScriptBlock { $scriptBlock }
#Invoke-Command -ComputerName $computer -ScriptBlock { $scriptBlock }
What am I doing wrong with Invoke-Command?
Thanks!
You are passing in a scriptblock with a string. When it will call it, it will basically have the same effect as writing $scriptBlock in your terminal. You have to actually execute the string in the scriptblock. You could use Invoke-Expression.
[string] $computer = "lumen"
[scriptblock] $scriptBlock = { "cd C:\Scripts\Update-Apps; ./Update-Apps" | Invoke-Expression }
$session = New-PSSession -ComputerName $computer
Invoke-Command -Session $session -ScriptBlock $scriptblock
Or you could write directly your command as PowerShell code in the scriptblock.
[string] $computer = "lumen"
[scriptblock] $scriptBlock = { cd C:\Scripts\Update-Apps; ./Update-Apps }
$session = New-PSSession -ComputerName $computer
Invoke-Command -Session $session -ScriptBlock $scriptblock
It doesn't have to be a string.
Related
I have written a script which works fine on the local server. However I would like to run the script block on a remote server. Here's the script block that's that runs fine locally. Can I use Invoke-Command to embed the below script block and run it on a remote server?
$Folder = Read-Host "Enter the folder name"
$FilePath = "E:\$Folder\capture.bat"
$Session = New-PSSession -ComputerName "qtestwest01"
Invoke-Command -Session $Session -ScriptBlock {$pt = New-Object System.Diagnostics.ProcessStartInfo;}
Invoke-Command -Session $Session -ScriptBlock {$pt.FileName = $using:FilePath;}
Invoke-Command -Session $Session -ScriptBlock {$pt.UseShellExecute = $false;}
Invoke-Command -Session $Session -ScriptBlock {$pt.RedurectStandardInput = $true;}
Invoke-Command -Session $Session -ScriptBlock {$e = [System.Diagnostics.Process]::Start($pt);}
Invoke-Command -Session $Session -ScriptBlock {$e.StandardInput.WriteLie("`n")}
Yes, it's pretty straight forward:
$Session = New-PSSession -ComputerName "qtestwest01"
$SB =
{
$pt = New-Object System.Diagnostics.ProcessStartInfo;
$pt.FileName = "E:\testscripts\capture.bat";
$pt.UseShellExecute = $false;
$pt.RedirectStandardInput = $true;
$e = [System.Diagnostics.Process]::Start($pt);
$e.StandardInput.WriteLine("`n")
}
Invoke-Command -Session $Session -ScriptBlock $SB
An aside: You may want to look at Start-Process -PassThru. Though I'm not sure you can set UseShellExecute using that pattern. There are some details about that here , but I didn't give it a thorough reading.
Update
Responding to your implementation and the parameter question, repeatedly calling Invoke-Command is unnecessary. You're calling into the same session so it's functionally the same thing, but everything you need is available so you can run a single command. The $Using: modifier can be used in a prefabricated ScriptBlock so long as the script block is used with certain cmdlets, including and maybe primarily Invoke-Command.
A new example:
$FilePath = "C:\windows\System32\notepad.exe"
$Session = New-PSSession -ComputerName "Server1"
$SB =
{
$pt = New-Object System.Diagnostics.ProcessStartInfo;
$pt.FileName = $Using:FilePath;
$pt.UseShellExecute = $false;
$pt.RedirectStandardInput = $true;
$e = [System.Diagnostics.Process]::Start($pt);
$e.StandardInput.WriteLine("`n")
}
Invoke-Command -Session $Session -ScriptBlock $SB
A second method of passing parameters into a script block is to use the Invoke-Command -ArgumentList parameter:
Example:
$FilePath = "C:\windows\System32\notepad.exe"
$Session = New-PSSession -ComputerName "Server1"
$SB =
{
$pt = New-Object System.Diagnostics.ProcessStartInfo;
$pt.FileName = $args[0] ;
$pt.UseShellExecute = $false;
$pt.RedirectStandardInput = $true;
$e = [System.Diagnostics.Process]::Start($pt);
$e.StandardInput.WriteLine("`n")
}
Invoke-Command -Session $Session -ScriptBlock $SB -ArgumentList $FilePath
And, Either approach, $Using or $args[0] will work even if cite the script block inline with the command:
Example:
$FilePath = "C:\windows\System32\notepad.exe"
$Session = New-PSSession -ComputerName "Server1"
Invoke-Command -Session $Session -ArgumentList $FilePath -ScriptBlock {
$pt = New-Object System.Diagnostics.ProcessStartInfo;
$pt.FileName = $args[0] ;
$pt.UseShellExecute = $false;
$pt.RedirectStandardInput = $true;
$e = [System.Diagnostics.Process]::Start($pt);
$e.StandardInput.WriteLine("`n")
}
Notes:
-ComputerName argument name and $FilePath value were changed in these examples just so I could test in my environment.
The use of $FilePath instead of $Folder. So far as I can tell $pt.FileName property needs a the full path. This was either mis-typed or in error in your last sample. $FilePath because of the -FilePath parameter on Start-Process.
$folder = 'testscripts'
$Session = New-PSSession -ComputerName "qtestwest01"
Invoke-Command -Session $Session -ScriptBlock {$pt = New-Object System.Diagnostics.ProcessStartInfo;}
Invoke-Command -Session $Session -ScriptBlock {$pt.FileName = $using:folder;}
Invoke-Command -Session $Session -ScriptBlock {$pt.UseShellExecute = $false;}
Invoke-Command -Session $Session -ScriptBlock {$pt.RedurectStandardInput = $true;}
Invoke-Command -Session $Session -ScriptBlock {$e = [System.Diagnostics.Process]::Start($pt);}
Invoke-Command -Session $Session -ScriptBlock {$e.StandardInput.WriteLie("`n")}
How can i pass command line parameters to a session which is invoked using 'invoke-command' in powershell 2.0
my script:
param(
[string]$hostname = 'my_server_name'
)
function createSession($hostname){
return New-PSSession -ComputerName $hostname -Credential $env:UserDomain\$env:UserName
}
$session = createSession $hostname
invoke-command -Session $session -ScriptBlock {
write-host $hostname
write-host $using:hostname
write-host $script:hostname
write-host '**test text**'
}
Exit-PSSession
Output: (I'm getting empty string if i print the parameter value directly.)
**test text**
use param block
$hostname = $env:computername
Invoke-Command -ScriptBlock { param($hostname)
Write-OutPut $hostname
} -ArgumentList $hostname
param(
[string]$hostname = 'my_server_name'
)
function createSession($hostname){
return New-PSSession -ComputerName $hostname -Credential $env:UserDomain\$env:UserName
}
$session = createSession $hostname
invoke-command -Session $session -ScriptBlock {
$hostname=$using:hostname
or
$hostname=$script:hostname
write-host $hostname
write-host '**test text**'
}
Exit-PSSession
Hope any one of the above helps,If Not Please look at the concept of scoping variables in powershell,May be they will help
Powershell variable scoping
PowerShell 5.1
Invoke-Command -ScriptBlock {start-job {gsv}} -ComputerName Will
Invoke-Command -ScriptBlock {get-job} -ComputerName Will
Nothing was displayed. I couldn't retrieve any job.
Jobs are tied to the current session. The way you run Invoke-Command creates a new session with every invocation, so the second session naturally doesn't know anything about jobs of the first one.
Change your code to something like this, so both invocations run in the same session:
$session = New-PSSession -ComputerName Will
Invoke-Command -Session $session -ScriptBlock { Start-Job {gsv} }
Invoke-Command -Session $session -ScriptBlock { Get-Job }
Remove-PSSession $session
I'm having trouble executing a program on a remote server. This is my command
$appCommand = "`"c:\SIDApps\{0}\{1}.exe`"" -f $destinationDirectory, $processToKill
Invoke-Command -ComputerName $remoteComputer -Credential $credentials -ScriptBlock { $args[0] } -ArgumentList $appCommand
That prints out "c:\SIDApps\FFMBC_Drone\GCUKTransCodeServiceFFMBCApp.exe" (Including the quotes) in the output window, but does not actually execute the program
If you only output $args[0] in the ScriptBlock it will only display the path not run the command.
Have you tried this ?
$appCommand = "c:\SIDApps\{0}\{1}.exe" -f $destinationDirectory, $processToKill
Invoke-Command -ComputerName $remoteComputer -Credential $credentials -ScriptBlock { Start-Process $args[0] } -ArgumentList $appCommand
I am trying to run a powershell script on remote pc . if i put the path in variable it does not run, but if i put the path as string it works. Not sure why.
This works
Invoke-Command -computername $serverName -scriptblock {& ("C:\_Project\test.ps1") }
This does not work
$server = "test"
$script = "C:\_Project\test.ps1"
Invoke-Command -computername $server -scriptblock {& ( $script) }
I would like to get the 2nd one working
Variables need to be passed to script blocks as arugments or they won't be available in the scriptblock. Here is how to do it.
$server = "test"
$script = "C:\_Project\test.ps1"
Invoke-Command -computername $server -ArugmentList $Script -scriptblock {
Param ($Script)
& ( $script)
}
Try this:
$server = "test"
$script = [ScriptBlock]::Create("& C:\_Project\test.ps1")
Invoke-Command -computername $server -scriptblock $script