Run a powershell script from one computer to the next - powershell

I already have code written to connect to another computer in my house and pull music files from the C drive. However, I am trying to find out how to keep this code, but modify it in a way that I can use it to run code on the second computer, then save it to a text file.
foreach ($server in Get-Content .\serverList.txt){
psexec \\$server -u username-p password cmd /c dir c:\*.mp3 /s > c:\Powershell\$server.txt
}

You could write a book on PowerShell Remoting (several people have) but it's reasonably straightforward.
On both computers run Enable-PSRemoting to configure all the settings. Then on the originating computer (the one making the remote call) run Set-Item WSMan:\localhost\Client\TrustedHosts -Value '*' (if you are security conscious replace the * with the IP of the remote PC).
Then you can run the all-powerful Invoke-Command to do all sorts of awesome stuff remotely. Unless you're on a domain or there's an identical user on the remote PC you'll need to provide credentials which means either prompting for them or saving them, but if I go into too much detail we'll both be here all day. Pretty easy to find the answers on Google.
$cred = Get-Credential
foreach ($server in Get-Content .\serverList.txt) {
Invoke-Command $server -Credential $cred -ScriptBlock { Get-ChildItem C:\*.mp3 -Recurse } | Out-File C:\Powershell\$server.txt
}

Related

Remote CrowdStrike Uninstallation

I am trying to uninstall outdated crowdstrike using CsUninstallTool.exe on bunch of remote servers.
As we know we cannot directly uninstall crowdstrike, it require a maintenance code unique to host. The below script is working correctly for a single remote host but when I try to run same script, crowdstrike did not get uninstalled.
Also same script is asking for credentials after every loop and looking for optimal way to manage user session without asking cred again & again.
$servers = Get-Content 'C:\Users\PP\Desktop\CrowdStrike_Automation\servers.txt'
$maintenance_token = Get-Content 'C:\Users\PP\Desktop\CrowdStrike_Automation\maintenance_key.txt'
foreach ($server in $servers) {
Invoke-Command -ComputerName $server -Credential (Get-Credential) -ScriptBlock {
& "C:\Temp\CrowdStrike_Automation\Setup\CsUninstallTool.exe" MAINTENANCE_TOKEN=$using:maintenance_token /quiet
}
}
Any suggestion?

Using Powershell to check proxy setting on remote machine

So i know I can't use Netsh because WinRM is disabled/access denied on my network.
I cant invoke etc.
So I'm trying to figure out a way to take a list of computer names and get the proxy from the machines.
So, my idea is to take the list I have on a \share, and foreach ($pc in $list) I would copy over a .cmd file from the same share. that .cmd file just runs a powershell script from the share, on that remote machine.
So copy a cmd to remote machine. Run cmd on remote machine, that cmd just runs the powershell script that gets the proxy from the registry, and then writes the machine name and the proxy to a file on the share.
But,
I'm getting a blank output tho. So, weird.
Here's the script that runs on the remote machine:
Set-ExecutionPolicy Unrestricted -Force
$proxy = (Get-ItemProperty
'Registry::HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings') | Select-Object AutoConfigURL
"$env:computername $proxy" |
Out-file -filepath "\share\Proxy\IEproxylistResolved.csv"
The problem is that I get empty file in IEproxylistResolved.csv its 3am and I'm prob just half dead in the head but could use a fresh perspective.
Have you tried this:
Import-Module PSRemoteRegistry
Get-RegValue -ComputerName $Computer1 -Key
"Software\Microsoft\Windows\CurrentVersion\Internet Settings" -Value AutoConfigURL
Source

Can I RDP through mstsc and run a script on that remote desktop?

I'm writing a script which needs to RDP to a few servers, do processes there and then come back.
mstsc /v:<computer> by itself looks great as it's security/credential prompt is the same as if you manually executed it.
However, after some research it appears that's meant to be a command line utility and nothing more because trying things like:
mstsc /v:104.209.198.181 | Invoke-Command -ScriptBlock {"New-Item C:\Users\<me>\Desktop\Success.txt -ItemType file"}
doesn't work.
So I tried Enter-PSSession <computer> -Credential $env:UserName which people use but it looks like a mess to deal with compared to mstsc because it looks primitive (an article I read yesterday tried to say this type of prompt is ALWAYS a phishing scam which obviously it's not but try telling management), it doesn't auto-populate domains, and I get a WinRM error which I'm sure will be a rabbit hole.
So is it possible to RDP with mstsc and then pipe commands to it so they're executed on that computer?
The answer is no. You cannot initiate some kind of pipe using MSTSC.exe.
You can, however, use PSRemoting to send the command like you're trying to do already:
Invoke-Command -ComputerName '<FQDN>' -ScriptBlock {
New-Item -Path "$HOME\Desktop\Success.txt" -ItemType File
}
If you don't know the FQDN, then look up the IP using DNS:
[System.Net.Dns]::GetHostEntry('104.209.198.181')
All this failing.. you can fall back on WMI, but you don't get any console feedback:
$WmiArgs = #{
'Class' = 'Win32_Process'
'Name' = 'Create'
'ArgumentList' = 'powershell -NoProfile -NonInteractive -WindowStyle Hidden -Command "New-Item -Path $HOME\Desktop\Success.txt -ItemType File"'
'ComputerName' = '104.209.198.181'
}
Invoke-WmiMethod #WmiArgs
While I tested the above is working, you can shorthand even this!
([wmiclass]'\\104.209.198.181\root\cimv2:win32_process').
Create('powershell -NoP -NonI -W Hidden -C "New-Item -Path $HOME\Desktop\Success.txt -ItemType File"')
With this method, however, you cannot pass credentials.

PowerShell failing to copy from UNC path

I'm working on a script to copy a folder from a UNC path to a local server. I'm remotely running my script through an interactive session and utilizing Invoke-Command -ScriptBlock like so:
Invoke-Command -ComputerName MyServer -ScriptBlock $Script
This is the script to do the copying:
$script {
try {
New-PSDrive -Name MyDrive -PSProvider FileSystem -Root \\uncpathserver\e$\SourceCode\ -Credential Contoso\me
Copy-Item -Path \\uncpathserver\e$\SourceCode\* -Destination E:\Inetpub\Target -Recurse -Force
}
catch {
Write-Host "Failed to copy!"
}
}
It is failing and throwing my catch block every time. I can't seem to figure out what I am missing to get this to work - it seems so simple and I hope I'm not missing something blatantly obvious.
EDIT:
I was able to get it to work by now just running the script from my local PC instead of from a server. I'm calling the file copy out of $script block now as well. This is what the new code looks like:
$MyServers= #("server-01", "server-02")
foreach ($server in $MyServers)
{
$TargetSession = New-PSSession -ComputerName $server -Credential
contoso\me
Copy-Item -ToSession $TargetSession -Path C:\Source\TheCode\ -
Destination "E:\InetPub\wherethecodegoes" -Recurse -Force
}
Everything else I'm doing inside my $script block (which has been omitted here for troubleshooting sake) is working A-OK. I do have to enter my credentials for each server, but due to the small nature of servers I'm working with, that isn't a deal breaker.
Sounds like a 'kerberos double hop' problem.
Short-Answer
Avoid the problem. From your system, setup two PSdrives. Then copy \\uncpathserver\e$\SourceCode\ to \\RemoteIISserver\E$\Inetpub\Target\
Long-Answer
From your system (System A), you are remotely executing a script (on System B) that will copy a remote folder (from System C).
It should work, but it doesn't. This is because when you (specifically, your account) from System A, remotely connects to System B, then asks System C for something, 'System C' doesn't trust you.
A quick google of the problem will show a myriad of ways around this issue, however;
Not all methods are secure (example: CredSSP)
Not all methods will work on your version of Windows (which is...?)
Not all methods will work with PowerShell
One secure method that does work with PowerShell leverages delegation.
This can be a bit daunting to setup, and I suggest you read-up on this thoroughly.
## Module 'ActiveDirectory' from RSAT-AD-PowerShell Windows feature required.
$ServerA = $Dnv:COMPUTERNAME
$ServerB = Get-ADComputer -Identity ServerB
$ServerC = Get-ADComputer -Identity ServerC
Delegate 'Server B' to access 'Server C';
# Set the resource-based Kerberos constrained delegation
Set-ADComputer -Identity $ServerC -PrincipalsAllowedToDelegateToAccount $ServerB
# Confirm AllowedToActOnBehalfOfOtherIdentity.Access is correct (indirectly).
Get-ADComputer -Identity $ServerC -Properties PrincipalsAllowedToDelegateToAccount
Wait about 15 minutes for 'Server B' to sync-up (or just reboot it).
You can force this with the following (Note: $Cred should contain your credentials);
Invoke-Command -ComputerName $ServerB.Name -Credential $cred -ScriptBlock {
klist purge -li 0x3e7
}
Run a test-hop;
Invoke-Command -ComputerName $ServerB.Name -Credential $cred -ScriptBlock {
Test-Path \\$($using:ServerC.Name)\C$
Get-Process lsass -ComputerName $($using:ServerC.Name)
Get-EventLog -LogName System -Newest 3 -ComputerName $($using:ServerC.Name)
}
The downside is you have to setup every remote remote-target (every 'Server C') this way. But the upside is that it's secure.

Copy/transfer file using PowerShell 2.0

I'm trying to create a PowerShell script to copy a file from my local computer to remote computer using its IP address.
I tested my client-server connection by using this command:
Invoke Command -ComputerName <IP Address> -ScriptBlock {ipconfig} -Credential $credential
(where $credential had been entered just before this command).
I tried using the Copy-Item and Robocopy commands but I'm not clear if it will even take my credentials and then let me copy a file from a local to a remote machine. To be specific, would these even support local to remote file transfer?
A lot of times I faced errors like:
Bad username and password, source path does not exist or destination path does not exist. But I still wanted to be sure if I was on right track and using the right commands to implement what I want to or if there is something else which I should consider using. How can I fix this problem?
It looks like you're trying to copy a file using PowerShell remoting. As posted in other answers, it would be simpler to use Copy-Item and/or Robocopy to copy from the source to a share on the destination computer.
If you want to copy the file using PowerShell remoting, you can slurp the file into a variable and use it in the remote script block. Something like:
$contents = [IO.File]::ReadAllBytes( $localPath )
Invoke-Command -ComputerName <IP Address> `
-Credential $credential `
-ScriptBlock { [IO.File]::WriteAllBytes( 'C:\remotepath', $using:contents ) }
Of course, if the file you're reading is really big, this could cause the remote connection to run out of memory (by default, PowerShell limits remote connections to around 128MB).
If you're stuck using PowerShell 2, you'll need to pass the bytes as a script block parameter:
$contents = [IO.File]::ReadAllBytes( $localPath )
Invoke-Command -ComputerName <IP Address> `
-Credential $credential `
-ScriptBlock {
param(
[byte[]]
$Contents
)
[IO.File]::WriteAllBytes( 'C:\remotepath', $Contents)
} `
-ArgumentList #( ,$contents )
And yes, you must wrap $contents in an array when passing it as the value to the -ArgumentList parameter and it must be prefixed with the comma operator ,, otherwise your remote script block will only receive the first byte.
One of the nice things about PowerShell is (unlike DOS) it support UNC paths. So you can literary just do:
Copy-Item -Path <local file path> -Destination \\<server IP>\<share>\<path>
Of course your account will need to have access to that location. If you need to enter alternate credentials you can pre-authenticate using net use \\<server IP>\<share> /user:[<domain>\]<user> <password>