Copy-Item with remote session - how to reference remote variables? - powershell

I'm using Copy-Item with the -ToSession parameter to copy some local files to a remote machine. Is there a straightforward way to make the cmdlet use variables from the remote session, instead of the local one? (I imagine I can always just output the variable in the remote session and read it locally, but that's a bit unwieldy...)
Specifically, I just want to copy the files into $env:USERPROFILE directory.
$session = New-PSSession ...
Copy-Item ".\some-file.txt" -ToSession $session -Destination $env:USERPROFILE

Related

How to copy files from one directory to another in the same PS session

I want to copy files from a remote session (a VM) and paste them in a different directory in the same session.
The Copy-Item command only allows me to copy from local machine to a remote session and vice versa.
I tried using -FromSession and -ToSession commands but they are mutually exclusive.
As you want to copy files from folderA to folderB on a Windows remote machine you can do:
#Define the actions to execute on the remote computer
$scriptBlock = {
move-item -Path [path] -Destination [path]
}
#Run the command on the remote computer
invoke-command -ComputerName [dnsHostName] -ScriptBlock $scriptBlock

Powershell - "Copy-item" command in scriptblock of Invoke-Command

I need to copy file from one remote server to other using powershell script.
What I have tried :-
While i use following powershell commands it's work fine.(means file copied from one server to other)
But while i use following script it gives error "cannot find path..." as follows
Actually, file is exist at that path.
I have tried to refer following stack-overflow already question-answer
Error with PowerShell command for copying file to remote server with credential
'Session' Parameter is null or empty in PowerShell script
powershell remote
Invoke-Command with remote session: Cannot validate argument on parameter
Unable to copy a binary to a remote Azure VM
PowerShell Command to Copy File on Remote Machine
I have also tried to get help using
Get-Help Invoke-Command
Question :-
How can i use "Copy-Item" command inside "Invoke-Command(Scriptblock)" in script(2) to copy file?
Is there any better way to achieve this(means best practice)?
Invoke-Command has the parameter -ArgumentList wich can be used to supply the values of local variables in the remote session. The Problem is: it's just the VALUE of the variable. No file!
What you can do:
Use Get-Content -Raw on small files to save the contant in a variable. On the target system create a New-Item with the -Value of that file. However thats not very efficent.
Example:
$txt = Get-Content -Raw -Path "C:\test\oldFile.txt"
$Session = New-PSSession 127.0.0.1
Invoke-Command -Session $Session -ScriptBlock { Param($Txt) New-Item -Path c:\test\newFile.txt -Value $txt } -ArgumentList $txt
#Get-PSSession | Remove-PSSession
Result:
Verzeichnis: C:\test # Sry german OS
Mode LastWriteTime Length Name PSComputerName
---- ------------- ------ ---- --------------
-a---- 03.09.2020 12:23 658033 newFile.txt 127.0.0.1
What you should do:
I think your use of Copy-Item -ToSession $Session is the right way to do it. It's litteraly made just for your purpose. The downside is, that the target directory needs to exist. But you need a PSSession for both cmdlets anyway. So you can use Invoke-Command with the same PSSession. First Create a PSSession. Use Invoke-Command to create you directory. Then use Copy-Item to move your file to the right place. Finally you can use Invoke-Command to do some finishing steps. And don't forget to Remove-PSSession when you are done:
$DestinationPath = "C:\test"
Invoke-Command -Session $Session -ScriptBlock { Param($Destination) New-Item -Path $Destination -ItemType Directory } -ArgumentList $DestinationPath
Copy-Item -Path "C:\test\oldFile.txt" -ToSession $Session -Destination "c:\test\newFile.txt"
Invoke-Command -Session $Session -ScriptBlock { write-host "Do some stuff" }
$Session | Remove-PSSession

Copy Folder Remote to Remote (No sharing path)

We are writing powershell script that will make backup on remote server. I am looking for some code reference that can copy my folder from remote to remote machine .
Trying with below sample code but "ToSession" is working with powershell 4.0.
We are writing powershell script (windows) that will run in separate server and create backup in remote machine(s).
Copy-Item –Path $sourcePath -Filter *.* -Recurse -Destination $targetPath -ToSession $session

Powershell Remote Copy fails, locally it works

We have logfile on a server A in a different location (no UNC Path access) and we wish to copy the file to server B. This successfully works with Copy-Item -FromSession (run on Server B) as long as the file is closed. So we can successfully copy the previous day's logs but not today's.
$cred = Get-OurUserCredentials
$sess = New-PSSession -ComputerName $ServerA -Credential $cred -Authentication Negotiate
$LogFile = "D:\log\tomcat\access.20180227.log"
Copy-Item -FromSession $sess $LogFile "D:\logs\tomcat\" -Force
However, we can locally copy the active log of today if we run Copy-Item locally on server A. It's only Copy-Item -FromSession on server B which fails with:
Copy-Item : The process cannot access the file 'D:\log\tomcat\access.20180227.log' because it is being used by another process.
At line:11 char:2
As a workaround we could create a local task on server A to create a local copy but why is this necessary?
Why does Copy-Item behave differently when run remotely and can we "fix" it's behaviour so it copies the log remotely as it would locally.
A version of the answer proposed in the OP but avoiding the need for a scheduled task.
$cred = Get-OurUserCredentials
$sess = New-PSSession -ComputerName $ServerA -Credential $cred -Authentication Negotiate
#ScriptBlock to copy file locally
$SB =
{
#Create variables on the remote machine avoid havin gto pass to scriptblock
$LogFile = "D:\log\tomcat\access.20180227.log"
$TempDes = "temporarylocationhere"
Copy-Item -Path $LogFile -Destination $Des
}
#optional scriptblock to clean up
$SB2 =
{
Remove-Item -Path $TempDes -force
}
#Run the copy file scriptblock
Invoke-Command -Session $sess -ScriptBlock $SB
#Copy file
Copy-Item -FromSession $sess $TempDes "D:\logs\tomcat\" -Force #"
#Run clean up scriptblock
Invoke-Command -Session $sess -ScriptBlock $SB2
Have you considered using a PSDrive to map the remote location and then copy the file to or from that drive?
The New-PSDrive cmdlet creates temporary and persistent drives that
are mapped to or associated with a location in a data store, such as a
network drive, a directory on the local computer, or a registry key,
and persistent Windows mapped network drives that are associated with
a file system location on a remote computer.
Example using your code:
# Change the ServerNameToCopyTo below
New-PSDrive -Name "Remote" -PSProvider "FileSystem" -Root "\\ServerNameToCopyTo\log\tomcat\"
$LogFile = "D:\log\tomcat\access.20180227.log"
Copy-Item $LogFile "Remote:\" -Force

Copy files from UNC path to C:\ and Program files (x86) folder within a remotly generated New-PSSession

I am writing a script, that creates a new VM, connects to it via New-PSSession and runs serveral Commands to alter a few settings and copy folders from a UNC path to the local C: and C:\Program files (x86).
Everything works fine expect the copy part - I get an error saying
permission denied.
I run the script itself as domain admin and the credentials I pass also has domain admin rights.
For example:
$source = '\\server\share'
$cred = Get-Credential
$pss = New-PSSession -ComputerName "$computername" -Credential $cred
Invoke-Command -Session $pss -ScriptBlock {
Copy-Item "$source\FOLDER" -Destination 'C:\FOLDER' -Recurse -Force -
Credential
$cred
Even if I pass the cedentials it fails. A quick search results in "use robocopy", but in my opinion it must be possible to copy files from a UNC path to a local directory with PowerShell even if that directory is basically protected by Microsoft.
I think you need to pass the variable to the remote session:
invoke-Command -Session $pss -Args $source -ScriptBlock{Copy-Item "$args[0]\FOLDER" ...}
otherwise $source is considered a variable in the remote session and since it doesn't exist there ps will try to copy from \Folder
You can try to use -ToSession parametr without entering to PSSession.
$ses = New-PSSession -ComputerName WorkStation
Copy-Item -ToSession $ses -Destination C:\users\TempUser\Documents\ -Path '\\10.0.0.1\share\' -Recurse
My solution for Copy-Item is:
-Destination $($(dir "env:programfiles(x86)").value + "\Avest\AvPCM_nces\")