Copying files over network - powershell

OK so below is my little script that I have come up with that should copy files from my local drive to a remote server using a local server admin user.
$User = "SERVER-NAME\MyUser"
$Password = "Password"
$net = new-object -ComObject WScript.Network
$net.MapNetworkDrive("X:", "\\SERVER-NAME\c$\MyTestFolder\", $false, $User, $Password)
Copy-Item -Path "D:\Path\To\Copy\From" -Destination "X:\" -Recurse -Force -PassThru -Verbose
For some reason I am getting the following error, even though the server is reachable from my machine:
Exception calling "MapNetworkDrive" with "5" argument(s): "The network path was not found."

So it seems that the script is able to copy files only if the folder was actually shared over the network (Folder Properties -> Sharing -> Advanced Sharing). No actual remote access to a file system (which is kinda disappointing).
Here's the simplified version of the script I ended up with:
$User = "SERVER-NAME\AdminUser"
$Password = "Password"
$net = new-object -ComObject WScript.Network
$net.MapNetworkDrive("x:", "\\SERVER-NAME\TestFolder", $false, $User, $Password)
Copy-Item -Path "D:\Path\To\Copy\From" -Destination "x:\" -Recurse -Force -PassThru
$net.RemoveNetworkDrive("x:", 0)

try to create drive with new-psdrive, like this:
$userCRED = "SERVER-NAME\MyUser"
$pass="Password"
$passCRED = ConvertTo-SecureString -String $pass -AsPlainText -Force
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $userCRED, $passCRED
$DestinationExport="\\SERVER-NAME\c$\MyTestFolder"
New-PSDrive -Name X -PSProvider filesystem -Root $DestinationExport -Credential $cred
Copy-Item -Path "D:\Path\To\Copy\From" -Destination "X:\" -Recurse -Force -PassThru -Verbose
Remove-PSDrive -Name X

Related

Creating PowerShell File Using New-Item & Add-Content Cmdlets

This is the first time posting on SO (and really on any public platform), so I apologize if this question was already answered or if the question isn't structured appropriately.
I am brand new to creating PowerShell Scripts and I'm hoping someone can assist me on my new scripting adventure!
The script I am trying to create is to gather user input on OS user credentials, the OS user password, and the remote server's IP Address\FQDN\Hostname. From there I want to create a ps1 file that a scheduled task will point to, which will copy a particular folder from one server to a remote server on a daily basis (replacing the remote servers folder). I am getting caught up on properly adding the needed lines using the New-Item and Add-Content cmdlets
Here is my script I created so far:
#Clear the Screen
Clear-Host
#Create Variable for OS User Account
$User = read-host "What is the OS User that has permissions to the remote web server?"
#Clear the Screen
Clear-Host
#Password for OS User Account
$Password = Read-Host "What is the password of the OS account that has permissions to the remote web server?"
#Clear the Screen
Clear-Host
#Convert Password String
$PWord = ConvertTo-SecureString -String $Password -AsPlainText -Force
#Combine User Name and Password into One Entity
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, $PWord
#IP Address of Destination ICA Web Server
$DestServer = Read-Host "What is the IP address\FQDN\Hostname of the Destination Web Server"
#Create a PowerShell File that will be used for Task Scheduler
New-Item "C:\Test\ScheduledTask\CopyPasteDownLoadFolder.ps1" -ItemType File -Force -Value "$PWord = ConvertTo-SecureString -String $Password -AsPlainText -Force"
Add-Content "C:\Test\ScheduledTask\CopyPasteDownLoadFolder.ps1" ""
Add-Content "C:\Test\ScheduledTask\CopyPasteDownLoadFolder.ps1" "$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, $PWord"
Add-Content "C:\Test\ScheduledTask\CopyPasteDownLoadFolder.ps1" ""
Add-Content "C:\Test\ScheduledTask\CopyPasteDownLoadFolder.ps1" "$Session = New-PSSession -ComputerName $DestServer -Credential $Credential"
Add-Content "C:\Test\ScheduledTask\CopyPasteDownLoadFolder.ps1" "Copy-Item `"C:\Web\Web\Download`" -Destination `"C:\Web\Web\`" -ToSession $Session -Recurse -Force"
This is the results that I get in the ps1 that gets created (Used 'TestUser' for the OS user, 'PW' for the password, and '10.10.10.10' for the remote server):
System.Security.SecureString = ConvertTo-SecureString -String PW -AsPlainText -Force
System.Management.Automation.PSCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList TestUser, System.Security.SecureString
= New-PSSession -ComputerName 10.10.10.10 -Credential System.Management.Automation.PSCredential
Copy-Item "C:\Web\Web\Download" -Destination "C:\Web\Web\" -ToSession -Recurse -Force
On the first line, for some reason it displays 'System.Security.SecureString' rather than the $PWord variable.
The second line displays 'System.Management.Automation.PSCredential' & System.Security.SecureString rather than the $Credential & $PWord variables.
The third line does not display the $Session variable. It also displays 'System.Management.Automation.PSCredential' rather than the $Credential variable.
The fourth line does not display the $Session variable
So it looks like Powershell doesn't like me adding variables using the New-Item & Add-Content cmdlets.
Any input/suggestions is greatly appreciated!! Thank you!
UPDATE: Thank you, mklement0, for providing the missing piece to my puzzle!
Here is an updated working script based off the information provided by mklement0
#Clear the Screen
Clear-Host
#Create Variable for OS User Account
$User = read-host "What is the OS user account that has permissions to the remote web server?"
#Clear the Screen
Clear-Host
#Password for OS User Account
$Password = Read-Host "What is the password of the OS user account that has permissions to the remote web server?"
#Clear the Screen
Clear-Host
#Convert Password String
$PWord = ConvertTo-SecureString -String $Password -AsPlainText -Force
#Combine User Name and Password into One Entity
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, $PWord
#IP Address of Destination ICA Web Server
$DestServer = Read-Host "What is the IP address, FQDN, or Hostname of the remote web server"
#Create a PowerShell File that will be used for Task Scheduler
New-Item "C:\Test\ScheduledTask\CopyPasteDownLoadFolder.ps1" -ItemType File -Force -Value "`$OSUser = `"$User`""
Add-Content "C:\Test\ScheduledTask\CopyPasteDownLoadFolder.ps1" ""
Add-Content "C:\Test\ScheduledTask\CopyPasteDownLoadFolder.ps1" "`$PWord = ConvertTo-SecureString -String `"$Password`" -AsPlainText -Force"
Add-Content "C:\Test\ScheduledTask\CopyPasteDownLoadFolder.ps1" "`$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList `$OSUser, `$PWord"
Add-Content "C:\Test\ScheduledTask\CopyPasteDownLoadFolder.ps1" ""
Add-Content "C:\Test\ScheduledTask\CopyPasteDownLoadFolder.ps1" "`$Session = New-PSSession -ComputerName `"$DestServer`" -Credential `$Credential"
Add-Content "C:\Test\ScheduledTask\CopyPasteDownLoadFolder.ps1" "Copy-Item `"C:\Web\Web\Download`" -Destination `"C:\Web\Web\`" -ToSession `$Session -Recurse -Force"
$ characters that you want to retain as-is inside an expandable (double-quoted) string ("...") must be escaped as `$, otherwise they and what follows are subject to string interpolation; e.g.:
$foo = 'bar'
# Note the ` (backtick) before the first $, which escapes it.
# The second $foo, which is unescaped is expanded (interpolated).
"Variable `$foo contains $foo"
The above yields verbatim:
Variable $foo contains bar

Connect to server that requires authentication using PowerShell 5.1?

I am new to PowerShell. I can't connect to a server that requires a username and password.
I wrote a script that moves files from 5 different servers to 5 different sources.
Out of these 5 source servers, one of them requires a username and password to connect to it.
This script is supposed to run every hour. I want the authentication to go through so when it comes to transferring files the script runs as is without errors.
The code below gives the following error:
Connecting to remote server xx.xx.xx.x failed with the following error message : The WinRM client cannot
process the request. Default authentication may be used with an IP address under the following conditions: the transport
is HTTPS or the destination is in the TrustedHosts list, and explicit credentials are provided. Use winrm.cmd to configure
TrustedHosts. Note that computers in the TrustedHosts list might not be authenticated.
The complete code block is:
$logPath = "C:\Users\Log.txt"
$trancriptPath = "C:\Users\LogTranscript.txt"
$getDate = Get-Date -Format "dddd MM/dd/yyyy HH:mm "
$counter = 0
Start-Transcript -Path $trancriptPath -Append
Add-Content -Path $logPath -Value ("LOG CREATED $getDate") -PassThru
#Credentials For Server5
$password = ConvertTo-SecureString “password” -AsPlainText -Force
$userName = "username"
[pscredential]$cred = New-Object System.Management.Automation.PSCredential -ArgumentList #($userName, $password)
Enter-PSSession -ComputerName "xx.xx.xx.x" -Credential $cred
#Sources
$srcMt01 = "\\Server2\programs\RECEIVE\*"
$srcMt01NameChg ="\\Server2\programs\RECEIVE"
$srcMC2o = "\\Server3\Predator\Revised Programs\MC2o\*"
$srcMC2oNameChg ="\\Server3\Predator\Revised Programs\MC2o"
$srcHm03 = "\\Server4\Predator\Revised Programs\H3\*"
$srcHm03NameChg ="\\Server4\Predator\Revised Programs\H3"
$srcMca = "\\Server5\Public\NcLib\FromNC\*"
$srcMcaNameChg ="\\Server5\Public\NcLib\FromNC"
$srcMt02 = "\\Server6\programs\RECEIVE\*"
$srcMt02NameChg ="\\Server6\programs\RECEIVE"
#Destination
$destMt01 = "\\Sever1\MfgLib\RevisedPrograms\MT01"
$destMC2o = "\\Server1\MfgLib\RevisedPrograms\MC2old"
$destHm03 = "\\Sever1\MfgLib\RevisedPrograms\H3"
$destMca = "\\Sever1\MfgLib\RevisedPrograms\MC-A"
$destMt02 = "\\Sever1\MfgLib\RevisedPrograms\MT02"
Function MoveFiles{
Param(
[string]$src,
[string]$dest,
[string]$srcNameChange
)
Get-ChildItem -Force -Recurse $src -ErrorAction Stop -ErrorVariable SearchError | ForEach-Object{
$counter++
$fileName = $_.Name
# Check for duplicate files
$file = Test-Path -Path $dest\$fileName
Write-Output $file
if($file)
{
"$srcNameChange\$fileName" | Rename-Item -NewName ("Copy_"+$fileName);
Add-Content -Path $logPath -Value ("$fileName exists in destination folder. Name change was successful") -PassThru
}
}
Move-Item -Path $src -Destination $dest -Force
Add-Content -Path $logPath -Value ("$counter file(s) moved to $dest") -PassThru
}
MoveFiles -src $srcMt01 -dest $destMt01 -srcNameChange $srcMt01NameChg
MoveFiles -src $srcMC2o -dest $destMC2o -srcNameChange $srcMC2oNameChg
MoveFiles -src $srcHm03 -dest $destHm03 -srcNameChange $srcHm03NameChg
MoveFiles -src $srcMca -dest $destMca -srcNameChange $srcMcaNameChg
MoveFiles -src $srcMt02 -dest $destMt02 -srcNameChange $srcMt02NameChg
Stop-Transcript
Any help is appreciated.
You might find it easier to remote into the server using Invoke-Command and then running your file copy using a script block on the remote server. You will probably need to use CredSSP authentication so the copy process can connect to the destination server.
The server running the script will need to be configured as a WinRM client and the remote servers will need WinRM configured to accept connections. This is most likely where your current WinRM error is coming from. That's a pretty involved discussion so do some research and post specific questions as you uncover them.
Ex.
$Destination = "\\Sever1\MfgLib\RevisedPrograms\MT01"
$SourceServer = "Server2"
$password = ConvertTo-SecureString “password” -AsPlainText -Force
$userName = "username"
[pscredential]$cred = New-Object System.Management.Automation.PSCredential -ArgumentList #($userName, $password)
$ScriptBlock = {
param ( [string]$dest )
Code to move the files from source to $dest
}
Invoke-Command -ComputerName $SourceServer -ScriptBlock $ScriptBlock -Authentication CredSSP -Credentials $Cred -ArgumentList $Destination

MI_RESULT_FAILED on Copy-Item in PowerShell Script

I am running PowerShell on CentOS 7.x. I converted working individual commands when running within PowerShell via pwsh to a PowerShell script and then it no longer works. Can someone please shed me some light on what I did wrong?
Here's the working individual commands when running within PowerShell via pwsh.
PS /home/user1/Downloads> $userPw = ConvertTo-SecureString -String "user1password" -AsPlainText -Force
PS /home/user1/Downloads> cd
PS /home/user1> $userCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "user1win", $userPw
PS /home/user1> $s = New-PSSession -computerName 192.168.20.143 -credential $userCredential -Authentication Negotiate
PS /home/user1> Copy-Item -Path /home/user1/Downloads/gssntlmssp-0.7.0-1.el7.x86_64.rpm -Destination "C:\users\user1win\Desktop" -ToSession $s
PS /home/user1> exit
Here's the script when I converted to a PowerShell script so I can pass arguments into it. remote-copy.ps
$remoteHost = $args[0]
$username = $args[1]
$pwp = $args[2]
$source = $args[3]
$destination = $args[4]
Write-Host "Remote Host: '$remoteHost'"
Write-Host "Username: '$username'"
Write-Host "Password: '$pwp'"
Write-Host "Source: '$source'"
Write-Host "Destination: '$destination'"
$pw = ConvertTo-SecureString -String $pwp -AsPlainText -Force
$cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, $pw
$s = New-PSSession -computerName $remoteHost -credential $cred -Authentication Negotiate
Copy-Item -Path $source -Destination $destination -ToSession $s
When I run the script, I got the following error.
[user1#rhel7-tm PowerShell]$ pwsh -File ./remote_copy.ps 192.168.20.143 user1win user1password /home/user1/Downloads/vte-0.28.2-10.el7.x86_64.rpm "C:\\users\user1win\Desktop"
Remote Host: '192.168.20.143'
Username: 'user1'
Password: 'user1password'
Source: '/home/user1/Downloads/vte-0.28.2-10.el7.x86_64.rpm'
Destination: 'C:\users\user1win\Desktop'
Copy-Item:
Line |
19 |
Copy-Item -Path "$source" -Destination "$destination" -ToSession $s |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
Starting a command on the remote server failed with the following error message : MI_RESULT_FAILED For more information, see the about_Remote_Troubleshooting Help topic.
Copy-Item: Line |
19 |
Copy-Item -Path "$source" -Destination "$destination" -ToSession $s |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
Failed to copy file /home/user1/Downloads/vte-0.28.2-10.el7.x86_64.rpm to remote target destination.
I would be greatly appreciate if someone can point me to where I did wrong. Thanks!
It's a false alarm. The script does work. The issue is by default the MaxEnvelopeSizekb in winrm/config is only 500kb. I need to set to a bigger value if I want to send a bigger file. To set MaxEnvelopSizekb to 500mb, you need to open PowerShell on Windows as Administrator and run the following command.
PS C:\WINDOWS\system32> Set-WSManInstance -ResourceUri winrm/config -ValueSet #{MaxEnvelopeSizekb = "500000"}

Copy-Item over remote network path using WinRS throws UnauthorisedAccessException

$_sourcepath = '\\servername\DriveLetter$\folder\file.zip'
$_destinationPath = 'D:\Temp\file.zip'
Copy-Item -Path $_sourcepath -Destination $_destinationPath;
My PowerShell script is run using WinRS in MSBuilds. It throws UnauthorisedAccessException but works fine when running on the local server.
Now I'm using
$Username = Domain\username";
$Password = ConvertTo-SecureString "password" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential($Username, $Password)
$session = new-pssession -computername 'serverName' -credential $cred
Invoke-Command -Session $session -ScriptBlock {copy-Item -Path $($args[0]) -destination $($args[1])} -argumentlist $_sourcepath,$_destinationPath ;
and im still getting Unauthorized AccessException.

Powershell OnlyInJobError

Weird problem I saw today and I don't understand.
Is there a difference beetween running a script manually in the ISE or Pshell, and as a job?
If I run it manually the code doesn't throw an error - runs smoothly:
Get-ChildItem "\\SERVER\S$\ROOT\DIR" -Recurse | Where {$_.creationtime -lt (Get-Date).AddDays(-35)} | Remove-Item -Force -Include *.conf
But if I run it via Job and let the it export the $error to a txtfile this happens:
Are the rights of my running machine different to the rights of the scheduled job?
Get-ChildItem : Zugriff verweigert
In Zeile:81 Zeichen:1
+ Get-ChildItem "\\SERVER\S$\ROOT\DIR" -Recurse | Where
{$_.creati ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-ChildItem], UnauthorizedA
ccessException
+ FullyQualifiedErrorId : System.UnauthorizedAccessException,Microsoft.Pow
erShell.Commands.GetChildItemCommand
Zugriff verweigert = Access denied
Oh, totally forgot to tell about my windows rights.
Normally the Server I am connecting to is blocked for everybody - except for login with credentials ofc. But somehow my manual powershell script is able to delete and create files?
In "job-mode" it loses it's abilities.
Edit:
Same for the Test-Path commandlet. Manually it shows me true or false. Via job it throws an error.
EDIT - SAME PROBLEM COMPLETELY DIFFERENT Commandlets:
$username = "Administrator"
$password = cat C:\securestring.txt | convertto-securestring
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $password
New-PSDrive -Name Z -PSProvider FileSystem -Root \\Server\ROOT -Credential $cred -Persist
test-path 'Z:'
Remove-PSDrive -Name Z -PSProvider FileSystem
This works!
This does not:
$jobname = "Test5"
$JobTrigger = New-JobTrigger -Daily -At "00:18 PM"
$MyOptions = New-ScheduledJobOption -ContinueIfGoingOnBattery -HideInTaskScheduler -RunElevated
Register-ScheduledJob -name "$jobname" -scriptblock {
$username = "Administrator"
$password = cat C:\securestring.txt | convertto-securestring
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $password
New-PSDrive -Name Z -PSProvider FileSystem -Root \\Server\ROOT -Credential $cred -Persist
test-path 'Z:'
Remove-PSDrive -Name Z -PSProvider FileSystem
} -trigger $JobTrigger –ScheduledJobOption $MyOptions
You probably have the job running under the SYSTEM account. Use the -Credential parameter to provide your account credentials (whatever account you're logged in with when you successfully run the command interactively).
BTW, Register-ScheduledJob uses the Task Scheduler. You can check the properties of the job in Task Scheduler to see what account it's configured to run as.
Well, it is not exactly an answere to my original question, but I was able to work around my problem by using the invoke-command and test-path from there and giving argument via the -arg.
Invoke-Command -ComputerName $FTPADRESS -ArgumentList $DIRECTORY -ScriptBlock {param ($DIR)
$check = Test-Path -Path "\\SERVER\ROOT\$DIR"
if ($check -ne $true) {New-Item -ItemType directory -Path "\\SERVER\ROOT\$DIR"}
}
Same works with the get-childitem.