Reputation: 119
I need to copy a file from a location on an Azure VM to my local computer using powershell. e.g C:\tmp on the VM to C:\tmp on my local machine
The application is c# using System Automation. Currently I use the method.
using (Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo))
{
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline(//Some SQL that pulls files from database to C:\tmp);
var results = pipeline.Invoke();
}
The powershell I use at the moment just return get-content for each file, returns it to c# in a loop, writing to file each time. However this is very inefficient.
Upvotes: 2
Views: 810
Reputation: 2258
This is the right idea, however it is more efficient to chunk the file when you do this. Powershell does not currently have a native way to do this, so you have to write some code. There are two parts, the remote powershell part to chunk the file on the server, and the C# part to re-assemble the chunks and execute the powershell.
The remote powershell part:
$streamChunks = New-Object System.Collections.Generic.List[byte[]]
$buffer = New-Object byte[] 1024
[IO.FileStream] $fileStream = $null
try
{
$targetPath = # FILE TO GET
$fileStream = [IO.File]::OpenRead($targetPath)
[int] $bytesRead = 0
while (($bytesRead = $fileStream.Read($buffer, 0, 1024)) -gt 0)
{
$chunk = New-Object byte[] $bytesRead
[Array]::Copy($buffer, $chunk, $bytesRead)
$streamChunks.Add($chunk)
}
Write-Output $streamChunks
}
finally
{
if ($fileStream -ne $null)
{
$fileStream.Dispose()
$fileStream = $null
}
};
Note that this script will be invoked by a runspace on your local machine:
Pipeline pipeline = runspace.CreatePipeline(command); // command is powershell above
Collection<PSObject> results = pipeline.Invoke();
The C# part to re-assemble the chunks:
using (FileStream fileStream = new FileStream(localPath, FileMode.OpenOrCreate, FileAccess.Write))
{
foreach (PSObject result in results)
{
if (result != null)
{
byte[] chunk = (byte[])result.BaseObject;
if (chunk != null)
{
fileStream.Write(chunk, 0, chunk.Length);
}
}
}
}
Upvotes: 1