Start-Job via Invoke-Command: Job is only available in remote session - powershell

I'm trying to start TShark on different servers via following command:
Invoke-Command -Session $remoteSession -ScriptBlock {start-job -ScriptBlock {& 'C:\Program Files\Wireshark\tshark.exe' -b filesize:10000 -b files:5 -w "$tsharkResultDirectory\tshark.pcap"} -Name "TShark"}
The command works and everything is fine. But when I connect to the remote server via e.g. remote desktop, and perform the command Get-Job nothing is returned.
So that means that the beforehand started job only runs in the remote session. Does anybody know if there is a way to start a job in "global" scope. I don't want that TShark stops tracing if I accidentally close my PowerShell window.
Thx

You're correct that the job only exists for the duration of the PowerShell host session, which is why you can't retrieve it when you RDP.
A better approach might be to use the -AsJob switch of Invoke-Command. You can then retrieve the results by running Get-Job on your local machine rather than RDP'ing to the remote host:
Invoke-Command -Session $remoteSession -ScriptBlock { & 'C:\Program Files\Wireshark\tshark.exe' -b filesize:10000 -b files:5 -w "$tsharkResultDirectory\tshark.pcap" } -AsJob -Name "TShark"
Note again that you'll lose the job if you end your local PowerShell session.
I believe the only other way to run a remote job and have it persist is via the *-ScheduledJob commands as they record their results on disk:
PS C:\> get-command *ScheduledJob | Select Name
Name
----
Disable-ScheduledJob
Enable-ScheduledJob
Get-ScheduledJob
Register-ScheduledJob
Set-ScheduledJob
Unregister-ScheduledJob

Related

Powershell : I am trying to run a script on a remote server. The script is for gathering info of that remote and other servers in the same domain

Editing to be clear with the issue
I am running the below code from a local computer which should run the script Test.ps1 placed on $server at C:\Temp to collect data from $server and other servers.
When i perform this, the script runs but i only get data for the $server and not the others. While if i run the C:\Temp\Test.ps1 script sitting on the $server, i get the desired output for all servers.
I am using this code
$s = New-PSSession -ComputerName $server -Credential $credential
Invoke-Command -Session $s -Command {C:\Temp\Test.ps1}
I am getting the output for the remote server on which the code is placed (localhost for the script), buti am not getting any output for the other servers.
While if I run the script locally on the remote server i get output from all the servers
The script does not have to be on the remote host. PowerShell allows you to run local PS1 scripts on remote computers.
Running Remote Commands
https://learn.microsoft.com/en-us/powershell/scripting/learn/remoting/running-remote-commands?view=powershell-7.1
Run a Script
To run a script on one or many remote computers, use the FilePath
parameter of the Invoke-Command cmdlet. The script must be on or
accessible to your local computer. The results are returned to your
local computer.
For example, the following command runs the DiskCollect.ps1 script on
the remote computers, Server01 and Server02.
Invoke-Command -ComputerName Server01, Server02 -FilePath 'c:\Scripts\DiskCollect.ps1'
As for this...
'My requirement is to run that script from the remote host per
security protocols'
... just use a script block as shown via the same MS Docs link
Run a Remote Command
To run a command on one or more computers, use the Invoke-Command
cmdlet. For example, to run a Get-UICulture command on the Server01
and Server02 remote computers, type:
Invoke-Command -ComputerName Server01, Server02 -ScriptBlock {& .c:\Scripts\DiskCollect.ps1}
Of course, I just removed Get-UICulture cmdlet in the docs command, with a script to use.
It depends on how your remote script uses credentials to access other servers. This should classify as a double hop issue.
If you cannot use CredSPP, you can use Resource-Based Kerberos Constrained Delegation
or use credentials inside the Invoke-Command scriptblock i.e. you can define a credential object on the local computer to be used in the -credentials parameter, and refer to it with $using:cred in your scriptblock.
The article does a good job of summarizing all your options.

Powershell start-process can't find file

I am trying to upgrade a server with a particular application from a client by PowerShell remote:
Invoke-Command -ComputerName $server -Credential $mycreds {Start-Process -FilePath "C:\temp\xxx.exe" -ArgumentList "-default", "-acceptEULA" -wait }
Whatever I try, I get messages like "Can't find the file specified..." what do I do wrong?
FilePath is on the local (client) computer.
Your C:\temp\xxx.exe executable must be present on the server (the remote machine) for your command to work, because that is where your script block ({ ... }) executes.
Note: By contrast, if you use Invoke-Command with the -FilePath parameter in order to run a locally present script file (.ps1) remotely, PowerShell automatically copies it to the remote machine; from the docs: "When you use this parameter, PowerShell converts the contents of the specified script file to a script block, transmits the script block to the remote computer, and runs it on the remote computer."
To copy the executable there from your local (client-side) machine, you need a 4-step approach (PSv5+, due to use of Copy-Item -ToSession[1]):
Create a remoting session to $server explicitly, using New-PSSession
Copy the local (client-side) executable to that session (the remote computer) with Copy-Item and its -ToSession parameter
Run your Invoke-Command command with the -Session parameter (rather than -ComputerName) in order to run in the explicitly created session (this isn't strictly necessary, but there's no need to create another (ad hoc) session).
Run Remove-PSSession to close the remote session.
Important: In a PowerShell remoting session, you cannot run external programs that require interactive user input:
While you can launch GUI applications, they invariably run invisibly.
Similarly, interactive console applications aren't supported (although output from console applications is received by the client).
However, interactive prompts from PowerShell commands are supported.
To put it all together:
# Specify the target server(s)
$server = 'w764' # '.'
# Establish a remoting session with the target server(s).
$session = New-PSSession -ComputerName $server
# Copy the local executable to the remote machine.
# Note: Make sure that the target directory exists on the remote machine.
Copy-Item C:\temp\xxx.exe -ToSession $session -Destination C:\temp
# Now invoke the excutable on the remote machine.
Invoke-Command -Session $session {
# Invoke *synchronously*, with -Wait.
# Note: If the program is a *console* application,
# you can just invoke it *directly* - no need for Start-Process.
Start-Process -Wait -FilePath C:\temp\xxx.exe -ArgumentList "-default", "-acceptEULA"
}
# Close the remote session.
# Note: This will terminate any programs that still
# run in the remote session, if any.
Remove-PSSession $session
[1] If you're running Powershell v4 or below, consider downloading psexec.

Start an executable on a remote station

I have a executable that resides on a remote station that I am trying to run from a central server, but running into issues. I am able to stop the Process on the remote station from the server using
Invoke-Command -ComputerName $name {Stop-Process -Name "ProcessName"
But when I try and run the executable, using
Invoke-Command -ComputerName $Args Start-Process "C:\Process\Process.exe"
it returns an error
This command cannot be run due to the error: The system cannot find the file
I have tried many variations of Invoke-Command, Start-Process, along with specifying the UNC path using the $name variable, but it will not run the executable stored on the remote computer.
You should run it like this:
Invoke-Command -ComputerName $name -ScriptBlock {
Set-Location c:\path\to\exe
FileName.exe /switch 1 /switch 2
}
You don’t need to use Start-Process. Just call the file and it should start execution.

Using PowerShell to execute a remote script that calls a batch file

I am having an issue with running a batch file that is located on a remote server.
I have a batch file located on a remote server that i want to run that kicks off an automated Selenium test. For simplicity, let's say the name of my batch file is mybatch.bat
I have the following code in a Powershell script located on the server:
$BatchFile = "mybatch.bat"
Start-Process -FilePath $BatchFile -Wait -Verb RunAs
If I run this PowerShell script locally on the server in ISE then it runs fine and it kicks off the selenium test which takes a couple minutes to run.
Now I want to try to execute this test from another machine by using PowerShell remoting. Let's assume that remoting is already configured on the servers.
I have a PowerShell script located on another server which has the following code segment. Assume that all of the session variables have the correct information set:
$CMD = "D:\mybatch.bat"
$TargetSession = New-PSSession -ComputerName $FullComputerName -Credential $myCreds -ConfigurationName RemoteExecution
$command = "powershell.exe -File $CMD -Wait"
Invoke-Command -Session $TargetSession -ScriptBlock { $command }
When this script runs, it does connect to the remote machine and create a remote session. It does look like it kicks off the batch file because PowerShell does not give me an error. But it does not wait for the full 3 or 4 minutes for the Selenium test to finish. It seems like it just times out. Also if I am logged onto the other machine, I don't see any Selenium web test running. No Selenium log files or results files are created on remote server as should be expected.
I was wondering what I could be doing wrong with my code.
Also, it seems that the server always returns the echo outputs of the batch file to my local machine. I see these random blinking white screen on ISE which looks like output from the batch file
$command = "powershell.exe -File $CMD -Wait"
Invoke-Command -Session $TargetSession -ScriptBlock { $command }
There are 2 issues with the above code:
$command inside the scriptblock and $command outside the scriptblock are different variables due to different scopes. The variable inside the scriptblock is thus undefined and the scriptblock will simply echo an emtpy value.
Even if $command weren't undefined, the scriptblock would still just echo its value, since it's defined as a string. PowerShell does not execute strings unless you're using something like Invoke-Expression (which you shouldn't).
This should do what you want:
$CMD = "D:\mybatch.bat"
$TargetSession = New-PSSession -ComputerName $FullComputerName -Credential $myCreds -ConfigurationName RemoteExecution
Invoke-Command -Session $TargetSession -ScriptBlock { & $using:CMD }
If you would like execute a bat file from another machine by using PowerShell Remote Session, simply enter dot and then follow by a whitespace, then enter the exact path of bat file located on that remote machine.
Example
Invoke-Command -ComputerName RemoteComputerName -Credential $credential -ScriptBlock {. "D:\Temp\Install_Something.bat"}

Running a remote cmd command in PowerShell

I uploaded some files to a remote host with PowerShell, by FTP. On this host runs Windows 7 Embedded.
It turns out there is EWF (Enhanced Write Filter). So after a restart the uploaded files were gone. For saving the changes it needs commit them in cmd (at the remote host) by: ewfmgr d:-commit How can I include this command in my PowerShell code?
The code:
Enable-PSRemoting -Force
Set-Item wsman:\localhost\client\trustedhosts -Value * -Force
Restart-Service WinRm
Test-WSMan $line
Invoke-Command -ComputerName $line -scriptblock {cmd.exe /c "ewfmgr d: -commit"} -credential $FTPCredential
When I run Enable-PSRemoting -Force manually on the remote computer, it works, but it is uncomfortable and take lots of time. Is there another way to do this once for many hosts simultaneously?
Example-Code:
$session = New-PSSession -ComputerName yourRemoteComputer
Invoke-Command -Session $session -Scriptblock {ewfmgr d: -commit}
Remove-PSSession -Session $session
You have to enable Powershell Remoting on your host to invoke a command like this (https://technet.microsoft.com/en-us/library/ff700227.aspx)
If you need to transmit Credentials to your remote host, you can add the -Credential-Parameter to New-PSSession. This article describes how to add valid Credentials to your script (https://technet.microsoft.com/en-us/library/ff700227.aspx)
Greetings, Ronny