在远程PowerShell会话c#运行空间期间复制文件

时间:2015-06-16 14:35:19

标签: c# powershell azure

我需要使用PowerShell将文件从Azure VM上的某个位置复制到本地计算机。例如,在本地计算机上的VM到C:\ tmp上的C:\ tmp

应用程序是使用System Automation的c#。目前我使用的方法。

    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();
    }

我目前使用的powershell只返回每个文件的get-content,在循环中将其返回到c#,每次都写入文件。然而,这是非常低效的。

1 个答案:

答案 0 :(得分:1)

这是正确的想法,但是在执行此操作时将文件块化更有效。 Powershell目前没有本地方法来执行此操作,因此您必须编写一些代码。有两个部分,远程PowerShell部分用于在服务器上存储文件,而C#部分用于重新组装块并执行powershell。

远程PowerShell部分:

$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 
    }
};

请注意,此脚本将由本地计算机上的运行空间调用:

Pipeline pipeline = runspace.CreatePipeline(command); // command is powershell above
Collection<PSObject> results = pipeline.Invoke();

重新组装块的C#部分:

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);
            }
        }
    }
}