0

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")} 
4
  • Yes............ Commented Aug 20, 2020 at 13:41
  • 1
    please, Read The Friendly Manual by taking a look at Get-Help Invoke-Command for some ideas ... [grin] Commented Aug 20, 2020 at 13:45
  • Thanks for your response. sorry I don't know how to embed this in a invoke-command. Would you be kind enough to provide me a snippet of the invoke-command. Commented Aug 20, 2020 at 13:47
  • @signalhouse, for powershell Invoke-Command, Google returns "About 1,000,000 results". Just searching stackoverflow.com returns "9,137 results". Surely there is something in ther for you. Commented Aug 20, 2020 at 14:29

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you Steve. I tried your approach and it works. Is there a way I can parameterize the following statement. $pt.FileName = "E:\$folder\capture.bat";
You can use a parameter like -Arguments <FileName> in the New-Object command. Let me know how it goes. Mark the question as answered if you're ok...
Thank you Steve. I followed a slightly different approach. Used a separate invoke-command statement for each line of code that I want to execute remotely.
Thank you Steve. I tried your 2nd solution and it worked like a charm. Yes the value defined inside $FilePath variable is a typo on my script.
0
$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")} 

3 Comments

I'm glad this is working but it's unnecessary to repeatedly call Invoke-Command. Moreover, the way it is written the filename won't be an executable file it's just a flat string. Perhaps I didn't understand your parameterize question... The using scope modifier is available in a prefabricated script block so long as the scriptblock is used with certain cmdlets Invoke-cCommand chief among them. I'll update the answer with an additional sample.
Yes, I do feel that it's not a great solution (using multiple invoke-command statements). However I felt this is the most easiest way I could come up with being a rookie.
Check the answer I updated it, hopefully to give you a better understanding of the options for passing data into the script block. I hope that also gives you some degree of comfort running Invoke-Command only once. Please don't forget to mark the question answered. Thanks.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.