Using "Invoke-Command" to run a local file on a remote machine - powershell

I am trying to use powershell to run a bat script that is located on Computer A and execute it on Computer B
Computer A is the computer calling the Invoke Command function
I am trying to do this via
Invoke-Command -ComputerName ComputerB -ScriptBlock{& "\\ComputerA\filepath\batch.bat"} -Credential $Cred
When I run this I recieve the error
The term '\\ComputerA\filepath\batch.bat' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
I have also tried to run it by calling cmd on Computer B and pass this bat script as an argument and I dont recieve any errors but I can tell the script did not run
The command I use for this is
Invoke-Command -ComputerName ComputerB -ScriptBlock{& "C:\Windows\System32\cmd.exe"} -ArgumentList "\\ComputerA\filepath\batch.bat" -Credential $Cred
When I go onto Computer B and call the script manually through cmd it works
I confirmed the Invoke-Command works because I was able to run programs that were local to Computer B
I am trying to not have to put any files on computer B such as psexec or the bat script itself which is why I am trying it this way
Thank you

When you remote to a machine (in this case ComputerB) and try to access something on ComputerA you are basically trying to access a network resource which by default isn't allowed. Use the -EnableNetworkAccess parameter in Invoke-Command to explicitly allow the same

This sounds like the "double hop"-/"second hop"-problem. You're credentials aren't available in the remote session (to access the network share).
Solutions:
Use CredSSP authentication
Requires some configuration
Invoke-Command -Authentication Credssp
Run it locally..
Copy the file to the remote computer
Use Invoke-Command -Scriptblock { & "c:\temp\batch.bat" }
Remove fiel on the remote computer if necessary
Use psexec.exe

Related

Enter-PSSession equivalent of $profile script

On my local PC and locally on the servers I admin, I regularly use the $profile script to set/output basic information. For instance running Set-Location to set the current path to the folder containing the scripts, and perhaps some Write-Host entries to show a basic cheat sheet for the most commonly used scripts and their expected parameters.
Does anyone know of a way to do something similar to that when using Enter-PSSession to connect interactively with a remote server?
As far as I can see there are no $profile files available with remote sessions, so I can't just add the commands in there (and the $profile used interactively on the local server doesn't get called when you remote into that same server).
Locally I've added functions to my local profile to make connecting to specific servers quicker, for example :
function foo{
$host.ui.RawUI.WindowTitle = "Foo"
Enter-PSSession -computername foo.local.mydomain.com -authentication credssp -credential mydomain\adminuser
}
and that works fine for connecting me (eg I type foo, then enter my password, and I'm in), but I still get dumped into C:\Users\adminuser\Documents.
I've tried adding things like the Set-Location command to the function after the connection, but that gets run in the local context (where the folder doesn't exist) and THEN it connects to the server. I even tried piping the commands to Enter-PSSession, but perhaps unsuprisingly that didn't work either.
Obviously things like Invoke-Command would allow me to specify commands to run once connected, but that wouldn't (as far as I can work out) leave me with an interactive session which is the primary aim.
You can't really automate unattended execution of anything that happens after Enter-PSSession connects your host to the remote session - but you can execute all the code you want in the remote session before calling Enter-PSSession:
function DumpMeInto {
param([string]$Path)
# Create remote session (you'll be prompted for credentials at this point)
$session = New-PSSession -ComputerName foo.local.mydomain.com -Authentication credssp -Credential mydomain\adminuser
# Run Set-Location in remote runspace
Invoke-Command -Session $session -ScriptBlock { Set-Location $args[0] } -ArgumentList $Path
# ... and then enter the session
Enter-PSSession -Session $session
}
Now you can do DumpMeInto C:\temp and it should drop you into a remote session on foo.local.mydomain.com with it's working directory set to c:\temp

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.

Running a PowerShell script on a remote Windows server using WinRM

I have written a script that allows to connect to a windows server machine using WinRM in order to run a script that exists on the Windows Server machine PS_Block_Access_Internet_GPO.ps1 but the script is not executed despite that the session was well created.
Besides the script needs administrator privileges to be executed, so how can I provide the needed privileges for script using PowerShell.
Enable-PSRemoting
Enter-PSSession -ComputerName Server.Admin.6NLG-AD
.\PS_Block_Internet_Access_GPO.ps1
To run a local script against a remote computer I would use use Invoke-Command, this doesn't need the script to be present on the remote computer.
Invoke-Command -ComputerName 'Server.Admin.6NLG-AD' -FilePath C:\Folder\myScript.ps1
As your script looks to create a GPO, you may likely need to use an alternative user account with appropriate permissions on your domain...
You can use the Credential param to specify an account like this:
Invoke-Command -ComputerName 'Server.Admin.6NLG-AD' -FilePath C:\Folder\myScript.ps1 -Credential Domain\Username

Unable to run a PS script from UNC path on a remote server

I'm trying to run the following PS command from server A on server B (10.11.12.13) which is supposed to run a PS script locally but from a UNC path. So I have:
Invoke-Command -ComputerName 10.11.12.13 -Credential $cred -ScriptBlock {powershell.exe -ExecutionPolicy Bypass "\\netshare\PSScript.ps1"}
After I enter my credentials it fails with the error:
*\\netshare\PSScript.ps1 : The term '\\netshare\Powershell\PSScript.ps1' is not recognized as
+CategoryInfo: NotSpecified: (\\netshare\Pow... recognized as :String) [],
RemoteException
+FullyQualifiedErrorId: NativeCommandError
+PSComputerName: 10.11.12.13*
In my command if I replace the unc path with a local path such as C:\files\PSScript.ps1 it runs fine.
The remote server is running PS v4. I've already run the command:
Set ExecutionPolicy Unrestricted on server B. I also tried adding -File after Bypass but that also fails with a different error.
How do I get that script to run from server B? Solutions like copying a script to server B first will not work. I also need this to run from the command line (not from a script).
Three things:
There is no reason to invoke powershell.exe from within PowerShell. Invoke the script by the call-operator &
Pay attention to the double-hop issue. If you connect to a remote computer by network logon you can't authenticate from within this remote connection to another remote computer (here network share).
Use Invoke-Command -FilePath C:\PSScript.ps1 -ComputerName 10.11.12.13 instead. Thereby you don't have to copy the file to every remote computer in advance.
Finally got it working with this:
Invoke-Command -FilePath \\netshare\PSScript.ps1 -ComputerName 10.11.12.13 -Credential $cred
Would still have liked to figure out how to run it inside a ScriptBlock however.

Powershell Remoting: Load local script inside script

I launch a local script on a remote computer with:
Invoke-Command -ComputerName RemoteServer -FilePath C:\myFolder\Script1.ps1
This script dot-sources another script (Script2), which also is located on my local computer in "C:\myFolder". This fails because Script1 trys to load the Script2 from the remote computer.
Is there a way to load Script2 from my local computer inside Script1 inside the remoting session?
[Workaround]
Create a session to the remote server
Use the session to load the script2
use the same session to run the script1.
eg:- $Session = New-PSSession -ComputerName $Server
Invoke-command -Session $Session -FilePath <script2> this should load functions
Invoke-command -Session $Session -FilePath <script1>
here the functions in script2 will be available for script1 to consume, so no need to refer and dot source script2 .
I don't think this can work the way you outlined it since code running on the remote machine cannot find a file that is relative to the local machine.
The only way to achieve this is to share your script and include it as with a UNC path, or an administrative share, like \\localmachine\c$\users\test\script\a.ps1.
But there's a chance you'll run into authentication issues (double hop).
The (easiest) solution: copy all your scripts to the remote machine first and make sure that the paths used in the scripts will work.