-
Notifications
You must be signed in to change notification settings - Fork 4
/
Send-File.ps1
94 lines (73 loc) · 2.53 KB
/
Send-File.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
##############################################################################
##
## Send-File
##
## From Windows PowerShell Cookbook (O'Reilly)
## by Lee Holmes (http://www.leeholmes.com/guide)
##
## http://poshcode.org/2216
##
##############################################################################
<#
.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