How do I download files from a remote server over a PSSession? I'm aware that PS5 introduced Copy-Item -FromSession
, but both local and remote may be not running PS5. My files are also quite large so a simple Get-Content
may be problematic.
Asked
Active
Viewed 565 times
2

tyteen4a03
- 1,812
- 24
- 45
-
You can still copy files from one machine to another using the UNC path. – EBGreen Apr 10 '18 at 13:21
-
1[You understand wrongly](https://stackoverflow.com/a/39122508/4137916). The remote side can have a PowerShell as low as 2.0. (I've never tested with 1.0, for lack of machines that still have that, but I doubt that would work.) The server where you *initiate* the command must have PowerShell 5, but you can just swap things around and use `-ToSession` if required. – Jeroen Mostert Apr 10 '18 at 13:23
-
@JeroenMostert Looks like [this bug](https://github.com/PowerShell/PowerShell/issues/2469) means that the solution won't work for me. Something that doesn't require PS5 would be great. – tyteen4a03 Apr 10 '18 at 13:39
-
@EBGreen Pretty sure `Copy-Item` doesn't take credentials, which I need. – tyteen4a03 Apr 10 '18 at 13:42
-
1Weeeellll, if you want to get technical... apparently this only broke with PowerShell 5.1, so 5.0 should still be good. :-P Without `Copy-Item` or the administrative shares, your options get far more ugly. I mean, [look at this stuff](https://stackoverflow.com/a/11948096/4137916). In the past, I've "solved" this by simply installing my own service on the machine so I could download files over HTTP (complete with compression). That assumed I was free to install whatever I wanted on the remote server, but did get around SMB's poor performance. – Jeroen Mostert Apr 10 '18 at 13:44
-
@tyteen4a03: You can (temporarily) establish a PS drive mapped to your UNC path; `New-PSDrive` _does_ accept credentials. – mklement0 Apr 10 '18 at 14:03
-
@mklement0 Due to some weird configuration issues that I'm not going to get into here, there is a chance that PSRemote works but UNC access doesn't, so a pure PSRemote solution is preferred. – tyteen4a03 Apr 10 '18 at 14:10
-
Something like [this](https://gist.github.com/PetSerAl/ea4cb46270172e45d4110fb6670077c1)? – user4003407 Apr 10 '18 at 15:00
-
@PetSerAl Could you attach that in an answer? – tyteen4a03 Apr 10 '18 at 15:05
1 Answers
2
You can read file on remote side as sequence of byte arrays, stream them thru remoting, and then assemble them back to file locally:
function DownloadSingleFile {
param(
[System.Management.Automation.Runspaces.PSSession] $FromSession,
[string] $RemoteFile,
[string] $LocalFile,
[int] $ChunkSize = 1mb
)
Invoke-Command -Session $FromSession -ScriptBlock {
param(
[string] $FileName,
[int] $ChunkSize
)
$FileInfo = Get-Item -LiteralPath $FileName
$FileStream = $FileInfo.OpenRead()
try {
$FileReader = New-Object System.IO.BinaryReader $FileStream
try {
for() {
$Chunk = $FileReader.ReadBytes($ChunkSize)
if($Chunk.Length) {
,$Chunk
} else {
break;
}
}
} finally {
$FileReader.Close();
}
} finally {
$FileStream.Close();
}
} -ArgumentList $RemoteFile, $ChunkSize | ForEach-Object {
$FileName = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($LocalFile)
$FileStream = [System.IO.File]::Create($FileName)
} {
$FileStream.Write($_, 0, $_.Length)
} {
$FileStream.Close()
}
}

user4003407
- 21,204
- 4
- 50
- 60