Local Variable to validate remote operation - powershell

I am trying to validate that a remote machine can connect to another machine on a specific port
Pseudo Code
$RemoteSession = New-PSSession -ComputerName MyRemoteVM
Invoke-Command -Session $RemoteSession -ScriptBlock {$RsTestResults = New-Object System.Net.Sockets.TcpClient -Argument 2ndRemoteVM , 2ndRemoteVMPort}
However, I can't seem to get the results of that test
I have tried adding another Invoke-Command like below, but it is not helping
$LocalResults = Invoke-Command -ScriptBlock {$RsTestResults}
any thoughts?

When you do:
Invoke-Command -Session $RemoteSession -ScriptBlock {
$RsTestResults = New-Object System.Net.Sockets.TcpClient -ArgumentList 2ndRemoteVM, 2ndRemoteVMPort
}
The variable $RsTestResults is being created on the remote host and its scope will be said host. If you want the results of System.Net.Sockets.TcpClient to be stored on your local host, you would need to store the results of Invoke-Command like below:
$RsTestResults = Invoke-Command -Session $RemoteSession -ScriptBlock {
New-Object System.Net.Sockets.TcpClient -ArgumentList 2ndRemoteVM, 2ndRemoteVMPort
}
Edit
To explain the error message you're getting:
PS > New-Object System.Net.Sockets.TcpClient -ArgumentList $null, $null
New-Object : Exception calling ".ctor" with "2" argument(s): "The requested address is not valid in its context xxx.xxx.xxx.xxx:0"
Which means, the variables for IPAddress and Port are never being passed to Invoke-Command.
You have 2 options to pass those variables to the cmdlet, one is with $using:variableName and the other is with -ArgumentList.
Assuming you have 2 local variables, for example:
$ipAddress = $csv.IPAddress
$port = $csv.Port
With $using:variableName
$RsTestResults = Invoke-Command -Session $RemoteSession -ScriptBlock {
New-Object System.Net.Sockets.TcpClient -ArgumentList $using:ipAddress, $using:port
}
With -ArgumentList
$RsTestResults = Invoke-Command -Session $RemoteSession -ScriptBlock {
param($ipAddress, $port)
New-Object System.Net.Sockets.TcpClient -ArgumentList $ipAddress, $port
} -ArgumentList $ipAddress, $port

Related

execute a script block on a remote server

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")}

Powershell Invoke-Command with arbitrary ScriptBlock

I have the following command which executes successfully on a remote Windows server.
Invoke-Command -ComputerName $ComputerName -UseSSL -SessionOption $sessionOptions -Credential $cred -ScriptBlock
{Start-Service "Test Service"}
I am attempting to pass in the script block as a variable so that I can execute any arbitrary command on the particular server, but I can't seem to pass the ScriptBlock argument successfully. The code executes without any errors, but does not start the remote service.
$ScriptBlock = Start-Service "Test Service"
Invoke-Command -ComputerName $ComputerName -UseSSL -SessionOption $sessionOptions -Credential $cred -ScriptBlock
{$args[0]} -ArgumentList $ScriptBlock
Enclose the code in {} to define a scriptblock literal when assigning it to your $ScriptBlock variable, then pass that as the argument to the -ScriptBlock parameter:
$ScriptBlock = { Start-Service "Test Service" }
Invoke-Command -ScriptBlock $ScriptBlock -ComputerName $ComputerName -UseSSL -SessionOption $sessionOptions -Credential $cred

how to pass command line parameters to invoked session in powershell 2.0

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

adding printer in remote machine is not working: invalid printer name

I have gone through many blogs for finding solution for this issue, but never find a solution.
$CompName = "test.domain.com"
$Printer = "\\122.21.10.11\PRINTER-NAME-1"
Invoke-Command -ComputerName $CompName -Scriptblock {
Param($p)
(New-Object -Com Wscript.Network).AddWindowsPrinterConnection($p)
} -ArgumentList $Printer
I have even tried PSRemoting and tried to execute the ps1 file from remote machine. the same script is working in local and not working remote.
Enter-PSSession -ComputerName "testserver.testdomain.com" -Authentication Credssp -Credential Get-Credential
Error:
Exception calling "AddWindowsPrinterConnection" with "1" argument(s): "The printer name is invalid. (Exception from HRESULT: 0x80070709)"
Updates:
Working without CredSSP:
Invoke-Command -ComputerName remotemac.mydomain.com -ScriptBlock {
Get-ChildItem C:\Users\myusername\Desktop
}
Working with CredSSP:
Invoke-Command -ComputerName remotemac.mydomain.com -ScriptBlock {
Get-ChildItem \\sharedmac\sharef
} -Authentication Credssp -Credential mydomain\myusername
Script is working, but not showing network printers:
Invoke-Command -ComputerName remotemac.mydomain.com -ScriptBlock {
(New-Object -ComObject WScript.Network).EnumPrinterConnections()
} -Authentication Credssp -Credential mydomain\myusername
Script gives error: Invalid Printer name
$Printer = "\\172.26.30.13\SDB1-FLOOR1-B2" # I have tried this input in single, double, with and without escape character
Invoke-Command -ComputerName remotemac.mydomain.com -ScriptBlock {
Param($p)
(New-Object -Com WScript.Network).AddWindowsPrinterConnection("$p")
} -ArgumentList $Printer -Authentication Credssp -Credential mydomain\myusername
I'm totally stuck.
I heard we can use Group Policy, is there anyway we can automate this using group policy?

nested scriptblocks in a powershell remote session

I am trying to run a script block on a remote machine, but i don't to be prompted for credentials, i want to pass them in the script.
Some commands may but the commands i want to run are access denied unless i provide the credential.
for example this command can work:
Invoke-Command -Session $session -ErrorAction Stop -ErrorVariable $Error -Scriptblock {ls }
but this wont work unless -credential is passed (Invoke-Command on target)
Invoke-Command -Session $session -ErrorAction Stop -ErrorVariable $Error -Scriptblock {Invoke-Command -computername $Env:COMPUTERNAME -Credential $Cred -ScriptBlock {ls} }
the same way what i want to achieve causes access denied problem (starting a process)
Invoke-Command -Session $session -ErrorAction Stop -ErrorVariable $Error -Scriptblock {[System.Diagnostics.Process]::Start("C:\Myprocess.exe", $localArgs, "UserName", $credential.Password, "MyDomain")}
Invoke-Command -Session $session -ErrorAction Stop -ErrorVariable $setError -Scriptblock {$Domain = "domain";$PassSec = ConvertTo-SecureString $( "password") -AsPlainText -Force ; $Cred = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $($domain + "\" + "userName"),$passSec; Invoke-Command -computername $Env:COMPUTERNAME -Credential $Cred -ScriptBlock {C:\Myprocess.exe } }