############################################################################## ## ## Send-File ## ## From Windows PowerShell Cookbook (O'Reilly) ## by Lee Holmes (http://www.leeholmes.com/guide) ## ############################################################################## <# .SYNOPSIS Sends a file to a remote session. .EXAMPLE PS >$session = New-PsSession leeholmes1c23 PS >Send-File c:\temp\test.exe c:\temp\test.exe $session #> param( ## The path on the local computer [Parameter(Mandatory = $true)] $Source, ## The target path on the remote computer [Parameter(Mandatory = $true)] $Destination, ## The session that represents the remote computer [Parameter(Mandatory = $true)] [System.Management.Automation.Runspaces.PSSession] $Session ) Set-StrictMode -Version Latest ## Get the source file, and then get its content $sourcePath = (Resolve-Path $source).Path $sourceBytes = [IO.File]::ReadAllBytes($sourcePath) $streamChunks = @() ## Now break it into chunks to stream Write-Progress -Activity "Sending $Source" -Status "Preparing file" $streamSize = 1MB for($position = 0; $position -lt $sourceBytes.Length; $position += $streamSize) { $remaining = $sourceBytes.Length - $position $remaining = [Math]::Min($remaining, $streamSize) $nextChunk = New-Object byte[] $remaining [Array]::Copy($sourcebytes, $position, $nextChunk, 0, $remaining) $streamChunks += ,$nextChunk } $remoteScript = { param($destination, $length) ## Convert the destination path to a full filesytem path (to support ## relative paths) $Destination = $executionContext.SessionState.` Path.GetUnresolvedProviderPathFromPSPath($Destination) ## Create a new array to hold the file content $destBytes = New-Object byte[] $length $position = 0 ## Go through the input, and fill in the new array of file content foreach($chunk in $input) { Write-Progress -Activity "Writing $Destination" ` -Status "Sending file" ` -PercentComplete ($position / $length * 100) [GC]::Collect() [Array]::Copy($chunk, 0, $destBytes, $position, $chunk.Length) $position += $chunk.Length } ## Write the content to the new file [IO.File]::WriteAllBytes($destination, $destBytes) ## Show the result Get-Item $destination [GC]::Collect() } ## Stream the chunks into the remote script $streamChunks | Invoke-Command -Session $session $remoteScript ` -ArgumentList $destination,$sourceBytes.Length