Передача файлов Powershell на удаленную машину через потоковые сбои - PullRequest
1 голос
/ 02 мая 2019

Я пытаюсь перенести файл с локального компьютера на удаленный компьютер через Powershell.Я использую Powershell версии 3.0 и не могу обновить Powershell.

Мне необходим удаленный сеанс с указанными учетными данными.

Ниже приведен код, который я использую:

# $credential variable created and set elsewhere

$command = {
param( [System.IO.FileStream]$inputStream, [string]$filePath, [string]$fileName )

    $writeStream = [System.IO.File]::Create( "$filePath\$fileName" );
    $inputStream.Seek(0, [System.IO.SeekOrigin]::Begin);
    $inputStream.CopyTo( $writeStream );
    $writeStream.Close();
    $writeStream.Dispose();
}

$readStream = [System.IO.File]::OpenRead( "C:\temp\tempfile.txt" );
$path = "C:\temp";
$file = "test.txt";

$session = New-PSSession -ComputerName RemoteMachineName -UseSSL -Credential $credential;

# this works when copying the file/stream locally
Invoke-Command -ArgumentList $readStream, $path, $file -ScriptBlock $command
# this does not work when copying the file/stream remotely
Invoke-Command -Session $session -ArgumentList $readStream, $path, $file -ScriptBlock $command

$readStream.Close();
$readStream.Dispose();

Приведенный выше код работает при попытке скопировать этот файл локально.Но при попытке скопировать этот файл на удаленный компьютер через сеанс я получаю следующую ошибку:

Невозможно обработать преобразование аргумента для параметра 'inputStream'.Не удалось преобразовать значение «System.IO.FileStream» типа «Deserialized.System.IO.FileStream» в тип «System.IO.FileStream».+ CategoryInfo: InvalidData: (:) [], ParameterBindin ... mationException + FullyQualifiedErrorId: ParameterArgumentTransformationError + PSComputerName: RemoteMachineName

Я не могу нигде найти в Интернете любую ссылку на класс "Десериализованная система. S.IO.FileStream».Я предполагаю, что поток становится сериализованным, поскольку он передается на удаленную машину, и именно это является причиной проблемы.

Кто-нибудь знает, как это сделать правильно, или есть лучший способ для передачи этого файла?Конечный файл (ы) большие, поэтому я не могу просто прочитать их в байтовый массив без нехватки памяти.Кроме того, я должен использовать указанные учетные данные, и передача должна быть зашифрована.

1 Ответ

1 голос
/ 03 мая 2019

Объекты в удаленном сеансе разрушаются, отправляются по проводам, а затем восстанавливаются. Некоторые типы могут быть перестроены в живые объекты, в то время как другие являются десериализованными версиями, как вы и предполагали. Здесь есть запись в блоге , которая объясняет это .

Обратите внимание, что PSRemoting всегда шифруется с AES-256 после первоначальной аутентификации независимо от используемого протокола HTTP или HTTPS.

Исходя из этого ответа для загрузки файла через PsSession Я перевернул процесс для отправки кусков размером 1 МБ по проводам и записи их в поток на удаленной машине. Поскольку он использует тот сеанс, который вы уже установили, он должен соответствовать вашим требованиям. Возможно, это можно оптимизировать, но я выполнил некоторые базовые тесты для файла объемом 1 ГБ, и он работал как положено.

function UploadSingleFile {
    param(
        [System.Management.Automation.Runspaces.PSSession] $RemoteSession,
        [string] $RemoteFile,
        [string] $LocalFile,
        [int] $ChunkSize = 1mb
    )
    $FileInfo = Get-Item -LiteralPath $LocalFile
    $FileStream = $FileInfo.OpenRead()
    try {
        $FileReader = New-Object System.IO.BinaryReader $FileStream
        try {
            for() {
                $Chunk = $FileReader.ReadBytes($ChunkSize)
                if($Chunk.Length) {
                        Invoke-Command -Session $RemoteSession -ScriptBlock {
                        param(
                            [string] $RemoteFile,
                            [byte[]] $Chunk
                        )
                        $FileStream = [System.IO.FileStream]::new($RemoteFile, [System.IO.FileMode]::Append, [System.IO.FileAccess]::Write)
                        $FileStream.Write($Chunk, 0, $Chunk.Length)
                        $FileStream.Close()      
                    } -ArgumentList $RemoteFile, $Chunk
                } else {
                    break;
                }
            }
        } finally {
            $FileReader.Close();
        }
    } finally {
        $FileStream.Close();
    }
}

Призвание:

$session = New-PSSession -ComputerName ComputerOne -UseSSL -Credential $credential
UploadSingleFile -Session $session -RemoteFile 'c:\temp\Destination.bin' -LocalFile 'C:\temp\source.bin'

Затем я использовал Get-FileHash для подтверждения того, что файл успешно скопирован.

PS C:\> Get-FileHash C:\temp\source.bin

Algorithm       Hash                                                                   Path                                                                                                                                                                                               
---------       ----                                                                   ----                                                                                                                                                                                               
SHA256          C513BFBCF4501A06BCC5F6F7A589532F7D802AA2C032D88143B0A31C1CFBD5F4       C:\temp\source.bin                                                                                                                                                                                   



PS C:\> Get-FileHash '\\ComputerOne\c$\temp\Destination.bin'

Algorithm       Hash                                                                   Path                                                                                                                                                                                               
---------       ----                                                                   ----                                                                                                                                                                                               
SHA256          C513BFBCF4501A06BCC5F6F7A589532F7D802AA2C032D88143B0A31C1CFBD5F4       \\ComputerOne\c$\temp\Destination.bin
...