Skip to content

Instantly share code, notes, and snippets.

@pvandervelde
Created November 10, 2014 08:26
Show Gist options
  • Save pvandervelde/b2f5b4156e5efe67f495 to your computer and use it in GitHub Desktop.
Save pvandervelde/b2f5b4156e5efe67f495 to your computer and use it in GitHub Desktop.
Copies a set of files to a remote directory on a given Azure VM.
<#
.SYNOPSIS
Copies a set of files to a remote directory on a given Azure VM.
.DESCRIPTION
The Add-AzureFilesToVM function copies a set of files to a remote directory on a given Azure VM.
.PARAMETER session
The PSSession that provides the connection between the local machine and the remote machine.
.PARAMETER remoteDirectory
The full path to the remote directory into which the files should be copied. Defaults to 'c:\installers'
.PARAMETER filesToCopy
The collection of local files that should be copied.
.EXAMPLE
Add-AzureFilesToVM -session $session -remoteDirectory 'c:\temp' -filesToCopy (Get-ChildItem c:\temp -recurse)
#>
function Add-AzureFilesToVM
{
param(
[System.Management.Automation.Runspaces.PSSession] $session,
[string] $remoteDirectory = "c:\installers",
[string[]] $filesToCopy
)
# Stop everything if there are errors
$ErrorActionPreference = 'Stop'
$commonParameterSwitches =
@{
Verbose = $PSBoundParameters.ContainsKey('Verbose');
Debug = $PSBoundParameters.ContainsKey('Debug');
ErrorAction = "Stop"
}
# Create the installer directory on the virtual machine
Invoke-Command `
-Session $session `
-ArgumentList @( $remoteDirectory ) `
-ScriptBlock {
param(
[string] $dir
)
if (-not (Test-Path $dir))
{
New-Item -Path $dir -ItemType Directory
}
} `
@commonParameterSwitches
# Push binaries to the new VM
Write-Verbose "Copying files to virtual machine: $filesToCopy"
foreach($fileToCopy in $filesToCopy)
{
$remotePath = Join-Path $remoteDirectory (Split-Path -Leaf $fileToCopy)
Write-Verbose "Copying $fileToCopy to $remotePath"
Copy-ItemToRemoteMachine -localPath $fileToCopy -remotePath $remotePath -Session $session @commonParameterSwitches
}
}
<#
.SYNOPSIS
Copies a file to the given remote path on the machine that the session is connected to.
.DESCRIPTION
The Copy-ItemToRemoteMachine function copies a local file to the given remote path on the machine that the session is connected to.
.PARAMETER localPath
The full path of the file that should be copied.
.PARAMETER remotePath
The full file path to which the local file should be copied
.PARAMETER session
The PSSession that provides the connection between the local machine and the remote machine.
.EXAMPLE
Copy-ItemToRemoteMachine -localPath 'c:\temp\myfile.txt' -remotePath 'c:\remote\myfile.txt' -session $session
#>
<#
Original found here: http://measureofchaos.wordpress.com/2012/09/26/copying-files-via-powershell-remoting-channel/
#>
function Copy-ItemToRemoteMachine
{
[CmdletBinding()]
param(
[string] $localPath,
[string] $remotePath,
[System.Management.Automation.Runspaces.PSSession] $session
)
# Use .NET file handling for speed
$content = [Io.File]::ReadAllBytes( $localPath )
$contentsizeMB = $content.Count / 1MB + 1MB
Write-Output "Copying $fileName from $localPath to $remotePath on $session.Name ..."
# Open local file
try
{
[IO.FileStream]$filestream = [IO.File]::OpenRead( $localPath )
Write-Output "Opened local file for reading"
}
catch
{
Write-Error "Could not open local file $localPath because:" $_.Exception.ToString()
Return $false
}
# Open remote file
try
{
Invoke-Command -Session $Session -ScriptBlock {
Param($remFile)
[IO.FileStream]$filestream = [IO.File]::OpenWrite( $remFile )
} -ArgumentList $remotePath
Write-Output "Opened remote file for writing"
}
catch
{
Write-Error "Could not open remote file $remotePath because:" $_.Exception.ToString()
Return $false
}
# Copy file in chunks
$chunksize = 1MB
[byte[]]$contentchunk = New-Object byte[] $chunksize
$bytesread = 0
while (($bytesread = $filestream.Read( $contentchunk, 0, $chunksize )) -ne 0)
{
try
{
$percent = $filestream.Position / $filestream.Length
Write-Output ("Copying {0}, {1:P2} complete, sending {2} bytes" -f $fileName, $percent, $bytesread)
Invoke-Command -Session $Session -ScriptBlock {
Param($data, $bytes)
$filestream.Write( $data, 0, $bytes )
} -ArgumentList $contentchunk,$bytesread
}
catch
{
Write-Error "Could not copy $fileName to $($Connection.Name) because:" $_.Exception.ToString()
return $false
}
finally
{
}
}
# Close remote file
try
{
Invoke-Command -Session $Session -ScriptBlock {
$filestream.Close()
}
Write-Output "Closed remote file, copy complete"
}
catch
{
Write-Error "Could not close remote file $remotePath because:" $_.Exception.ToString()
Return $false
}
# Close local file
try
{
$filestream.Close()
Write-Output "Closed local file, copy complete"
}
catch
{
Write-Error "Could not close local file $localPath because:" $_.Exception.ToString()
Return $false
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment