writing a powershell script to relay commands over two servers - powershell

I have been working on getting a script running that runs from a main domain controller. I want to be able to run the script from this domain controller and have it invoke some commands on a varied amount of remote servers which in turn copies files from a NAS on the same network to a local directory on each server. I use credentials from a securecard that I pass in to elevate privileges but I cannot seem to get it to copy the files down unless I execute the commands on the server itself. If I can get powershell to remotely execute these commands and perform the action then I would be all set.
Here is what I have come up with so far, please let me know what might help get this going for me. I would appreciate any help provided.
# Sets the variable for the source file location (c:\temp\ThisFile.exe)
#$Source = "\\nas\Applications\devapp\autononomous\v2\.exe"
$Source = "c:\temp\redirect"
# Sets the variable for the destination file location
$Destination = "temp"
# Sets the variable for application
$Application = "REDIRECT"
# Sets the variable for the remote destination file location
$Remote_Destination = "c:\$Destination\$Application"
# Sets the variable for the remote command to be executed
$Remote_Command = "regedit /s $Remote_Destination"
# Pass in the credentials you will be using to be able to copy from
one server to another, otherwise it will attempt to use local credentials.
$Credentials = get-credential
# Read in servers from text file and execute script
$Servers = Get-Content c:\temp\PowerShell\Servers.txt | ForEach-Object {
Write-Host "Installing" $Application "on server" $_
Copy-Item -Path $Source -Destination \\$_\c$\$Destination -recurse -force -Credential $Credentials
Invoke-Command -ComputerName $_ -ScriptBlock {
Param($Remote_DestinationR, $Remote_CommandR)
cmd.exe /c if not exist "c:\app\v2" mkdir "C:\app\v2"
cmd.exe /c xcopy /E /I /Y "C:\temp\redirect\home" "C:\app\v2\home"
} -Argumentlist $Remote_Destination, $Remote_Command
}

Related

Create folder with WMI with alternate credentials

I have a PowerShell script to create a folder on a remote computer with WMI. But I need to run this with alternate credentials. Normally I would just add -credential $cred to the command but I don't know where to put it in this case.
$computer = "COMPUTERNAME" # add the computername where the folder needs to bee created
$pathname = "PATHNAME" # add the path and foldername to be added
# Start local process with help of WMI
$p = [WMIClass]"\\$computer\root\cimv2:Win32_Process"
$p.Create("cmd.exe /c md $pathname") # run CMD to execute the action

Unable to run the parametrized batch file on remote machine using PowerShell

Execute the remote server parametrized batch file from PowerShell.
Doesn't throw an error nor executed command on remote machine.
$path = "D:\run\test-5.2.bat";
Invoke-Command -ComputerName testserver -Scriptblock { "$path" }
Script inside the bat file is msiexec with parameters, which shall execute through Command Prompt only.
Based on this msdn link, you can run a ps1 script file on remote computers. So if it is possible to "port" the content of the bat file in a ps1 it should work. Here is the msdn example:
Example 11: Run a script on all the computers listed in a text file
PS C:\> Invoke-Command -ComputerName (Get-Content Servers.txt) -FilePath C:\Scripts\Sample.ps1 -ArgumentList Process, Service
This example uses the Invoke-Command cmdlet to run the Sample.ps1 script on all of the computers listed in the Servers.txt file. The command uses the FilePath parameter to specify the script file. This command lets you run the script on the remote computers, even if the script file is not accessible to the remote computers.
When you submit the command, the content of the Sample.ps1 file is copied into a script block and the script block is run on each of the remote computers. This procedure is equivalent to using the ScriptBlock parameter to submit the contents of the script.
Hope that helps
$path is a string. PowerShell simply echoes bare strings instead of executing them, unlike CMD or bash. Use the call operator (&):
& "$path"
or Start-Process:
Start-Process cmd.exe -ArgumentList '/c', $path -NoNewWindow -Wait
to have PowerShell execute a string as a command. Since you say you're running msiexec.exe from the batch script using the latter may be required.
On top of that you have a scope issue. The variable $path inside the scriptblock is not the same as the one in the global scope. You can mitigate that via the using: scope qualifier:
Invoke-Command -Computer testserver -Scriptblock { & "$using:path" }
or by passing $path as an argument to the scriptblock:
Invoke-Command -Computer testserver -Scriptblock { & "$($args[0])" } -ArgumentList $path

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

PowerShell Passing Local Parameters to a Remote Script via Invoke-Command

Using PowerShell 4.0. I'm trying to run a script remotely that resides on the remote server. I need to pass a variable from my local script to the remote script. I've gone over dozens of posts and tried at least 10 variations but none seem to work. My initial command was:
Invoke-Command -ComputerName $ServerList -FilePath $piDeployScript -ArgumentList $SDFEnvironment
Where $piDeployScript is the full UNC path to the script on the remote server and $SDFEnvironment is a simple string parameter passed into my script. It looks like the parameter is not getting passed to the script. Is there a simple way to do this? How far off am I?
Update: I don't write the remote scripts, they're written by other groups in the company. The only thing I know is what field(s) need to be passed and they're all positional. I don't know the actual parameter names in the remote scripts. I could get them but I'm trying to write something that will work regardless of the parameters on the remote script. I get passed a list of parameter values (in this case 1 parameter) and send that list of strings to the remote script.
Update: Per #dugas this is the test script I'm running on my own server to test the functionality
Param
(
# SDF Environment
[Parameter(Position=0)]
[string]$SDFEnvironment
)
if ($PSBoundParameters.ContainsKey('SDFEnvironment'))
{
"Script Ran Env $SDFEnvironment"|Out-File -FilePath .\$SDFEnvironment"_LogFile.txt" -Encoding ascii -Force
}
else
{
"Environment Parameter missing"|Out-File -FilePath .\"ERR_LogFile.txt" -Encoding ascii -Force
}
Update: Below is the entire section of my local script that runs the Invoke-Command:
# Run the specifed script on all computers
Write-Output ("Running command ""{0}"" on server(s) ""{1}"" for Environment ""{2}"" " -f $piDeployScript,$SDFServerList,$SDFEnvironment)
try
{
if (Test-Connection -ComputerName $SDFServerList -Quiet)
{
Invoke-Command -ComputerName $SDFServerList -FilePath $piDeployScript -ArgumentList $SDFEnvironment
}
else
{
Write-Error "Remoting not enabled on one or more of ""$SDFServerList"" "
exit 1
}
}
catch
{
Write-Error ("Error running script {0} on server(s) {1}. Check log for more detail." -f $piServerScript,$SDFServerList)
exit 1
}
and here's the output from that code:
Running command "D:\AHP\pi_exceed_presentation\pi_exceed_presentation_deploy.ps1" on server(s) "ad1hfdahp802" for Environment "INT"
D:\a5\RWS_pi_exceed_presentation\Content_Deploy\trunk\deploy\Deploy-Content.ps1
: Error running script pi_exceed_presentation_deploy.ps1 on server(s)ad1hfdahp802. Check log for more detail.
My bad on the $piDeployScript variable. It's not the UNC to the script, it's the local file system address on the remote server. Is that the problem? Is it looking for the script on my local D: drive? Did I just answer my question?
Just to test my questions above I ran this code in PowerShell from my desktop:
$s="ad1hfdahp802"
$SDFEnvironment="INT"
$fp="\\ad1hfdahp802\D$\AHP\pi_exceed_presentation\pi_exceed_presentation_deploy.ps1"
try
{
Invoke-Command -ComputerName $s -FilePath $fp -ArgumentList $SDFEnvironment
}
catch
{
write-output "error running $fp on $s for $SDFEnvironment"
}
The code returned with no error, but the remote script didn't run. I logged into the remote server via RDC and ran the remote script locally in PowerShell with and without a parameter and it worked as expected. Now I'm really stumped.
Local script:
$server='ad1hfdahp802'
$remotepath='\\ad1hfdahp802\d$\AHP\pi_exceed_presentation\pi_exceed_presentation_deploy.ps1'
$scriptPath='d:\AHP\pi_exceed_presentation\'
$SDFEnvironment='INT'
Invoke-Command -ComputerName $server -FilePath $remotepath -ArgumentList($SDFEnvironment,$scriptPath)
Remote Script:
Param
(
# SDF Environment
[Parameter(Position=0)]
[string]$SDFEnvironment,
[Parameter(Position=1)]
[string]$scriptPath
)
Write-Output "Running Script - $SDFEnvironment"
Write-Output "Path: $scriptPath"
$outpath=("{0}\{1}_LogFile.txt" -f $scriptPath,$SDFEnvironment)
"Script Ran Env $SDFEnvironment"|Out-File -FilePath $outpath -Encoding ascii -Force
Write-Output "Script Complete"
This combination works. Originally the remote script used $PSCommandPath (also tried $PSScriptRoot) to determine the output path but that doesn't work on scripts run remotely. The actual path has to be passed in if you want deterministic placement of output files.

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>