2012-05-17 11 views
19

Ich habe nur ein paar Stunden auf der Suche nach einer Lösung zum Senden von Dateien über eine aktive PSSession verbrannt. Und das Ergebnis ist nada, niente. Ich versuche, einen Befehl auf einem Remotecomputer über eine aktive Sitzung aufzurufen, die etwas aus einem Netzwerkspeicher kopieren soll. Also, im Grunde ist es dieses:Senden von Dateien über PSSession

icm -Session $s { 
Copy-Item $networkLocation $PCLocation } 

Wegen der „zweiten Sprung“ Problem, das kann ich nicht tun, direkt, und weil ich Win Server 2003 betreibe ich kippe CredSSP aktivieren. Ich könnte zuerst die Dateien auf meinen Computer kopieren und sie dann an die entfernte Maschine senden/schieben, aber wie? Ich versuchte PModem, aber wie ich sah, kann es nur Daten ziehen und nicht drücken.

Jede Hilfe ist appreaciated.

+1

Warum verwenden Sie keine Netzwerkfreigabe, um Ihre Dateien zu kopieren? – JPBlanc

+1

Nice one, aber höhere Autoritäten genehmigen das nicht :) –

+1

Wenn Sie den Remote-Computer aktivieren können, um für Delegierung in AD "vertrauenswürdig zu sein" dann können Sie den zweiten Hop ohne CredSSP durchführen. –

Antwort

17

Wenn es sich um eine kleine Datei handelt, könnten Sie den Inhalt der Datei und den Dateinamen als Parameter senden.

$f="the filename" 
$c=Get-Content $f 
invoke-command -session $s -script {param($filename,$contents) ` 
    set-content -path $filename -value $contents} -argumentlist $f,$c 

Wenn die Datei zu lang ist, zu passen, was auch immer die Grenzen für die Sitzung sind, können Sie die Datei in als Brocken, lesen und eine ähnliche Technik verwenden sie zusammen in der Zielposition anhängen

+1

'$ f == $ filename' und' $ c == $ contents' ?? –

+2

$ filename und $ contents sind die Namen der Parameter im Skriptblock. $ f und $ c sind Variablen, die an den Skriptblock übergeben werden. –

2

Ich hatte vor einiger Zeit das gleiche Problem und habe einen Proof-of-Concept für das Senden von Dateien über eine PS Remoting-Sitzung erstellt. Sie finden das Skript finden Sie hier:

https://gist.github.com/791112

#requires -version 2.0 

[CmdletBinding()] 
param (
    [Parameter(Mandatory=$true)] 
    [string] 
    $ComputerName, 

    [Parameter(Mandatory=$true)] 
    [string] 
    $Path, 

    [Parameter(Mandatory=$true)] 
    [string] 
    $Destination, 

    [int] 
    $TransferChunkSize = 0x10000 
) 

function Initialize-TempScript ($Path) { 
    "<# DATA" | Set-Content -Path $Path 
} 

function Complete-Chunk() { 
@" 
DATA #> 
`$TransferPath = `$Env:TEMP | Join-Path -ChildPath '$TransferId' 
`$InData = `$false 
`$WriteStream = [IO.File]::OpenWrite(`$TransferPath) 
try { 
    `$WriteStream.Seek(0, 'End') | Out-Null 
    `$MyInvocation.MyCommand.Definition -split "``n" | ForEach-Object { 
     if (`$InData) { 
      `$InData = -not `$_.StartsWith('DATA #>') 
      if (`$InData) { 
       `$WriteBuffer = [Convert]::FromBase64String(`$_) 
       `$WriteStream.Write(`$WriteBuffer, 0, `$WriteBuffer.Length) 
      } 
     } else { 
      `$InData = `$_.StartsWith('<# DATA') 
     } 
    } 
} finally { 
    `$WriteStream.Close() 
} 
"@ 
} 

function Complete-FinalChunk ($Destination) { 
@" 
`$TransferPath | Move-Item -Destination '$Destination' -Force 
"@ 
} 

$ErrorActionPreference = 'Stop' 
Set-StrictMode -Version Latest 

$EncodingChunkSize = 57 * 100 
if ($EncodingChunkSize % 57 -ne 0) { 
    throw "EncodingChunkSize must be a multiple of 57" 
} 

$TransferId = [Guid]::NewGuid().ToString() 


$Path = ($Path | Resolve-Path).ProviderPath 
$ReadBuffer = New-Object -TypeName byte[] -ArgumentList $EncodingChunkSize 

$TempPath = ([IO.Path]::GetTempFileName() | % { $_ | Move-Item -Destination "$_.ps1" -PassThru}).FullName 
$Session = New-PSSession -ComputerName $ComputerName 
$ReadStream = [IO.File]::OpenRead($Path) 

$ChunkCount = 0 
Initialize-TempScript -Path $TempPath 

try { 
    do { 
     $ReadCount = $ReadStream.Read($ReadBuffer, 0, $EncodingChunkSize) 
     if ($ReadCount -gt 0) { 
      [Convert]::ToBase64String($ReadBuffer, 0, $ReadCount, 'InsertLineBreaks') | 
       Add-Content -Path $TempPath 
     } 
     $ChunkCount += $ReadCount 
     if ($ChunkCount -ge $TransferChunkSize -or $ReadCount -eq 0) { 
      # send 
      Write-Verbose "Sending chunk $TransferIndex" 
      Complete-Chunk | Add-Content -Path $TempPath 
      if ($ReadCount -eq 0) { 
       Complete-FinalChunk -Destination $Destination | Add-Content -Path $TempPath 
       Write-Verbose "Sending final chunk" 
      } 
      Invoke-Command -Session $Session -FilePath $TempPath 

      # reset 
      $ChunkCount = 0 
      Initialize-TempScript -Path $TempPath 
     } 
    } while ($ReadCount -gt 0) 
} finally { 
    if ($ReadStream) { $ReadStream.Close() } 
    $Session | Remove-PSSession 
    $TempPath | Remove-Item 
} 

Einige kleinere Änderungen erlauben würden, eine Sitzung als Parameter anstatt sie zu akzeptieren, eine neue zu starten. Ich habe festgestellt, dass die Speicherbelegung des Remoting-Dienstes auf dem Zielcomputer beim Übertragen großer Dateien sehr groß werden kann. Ich vermute, PS Remoting wurde nicht wirklich so entworfen, um auf diese Weise verwendet zu werden.

31

Dies ist nun möglich, in Powershell/WMF 5,0

Copy-Item-FromSession und -toSession Parameter. Sie können eines davon verwenden und eine Sitzungsvariable übergeben.

z.

$cs = New-PSSession -ComputerName 169.254.44.14 -Credential (Get-Credential) -Name SQL 
Copy-Item Northwind.* -Destination "C:\Program Files\Microsoft SQL Server\MSSQL10_50.SQL2008R2\MSSQL\DATA\" -ToSession $cs 

Weitere Beispiele bei https://richardspowershellblog.wordpress.com/2015/05/28/copy-files-over-ps-remoting-sessions/

0
$data = Get-Content 'C:\file.exe' -Raw 
Invoke-Command -ComputerName 'server' -ScriptBlock { $using:data | Set-Content -Path 'D:\filecopy.exe' } 

wissen eigentlich nicht, was die maximale Dateigrößenbeschränkung ist.

+0

Was ist 'get-data'? – Mark

+0

Das würde ich Powershell von der Spitze meines Kopfes tippen. Hätte "Get-Content" offensichtlich sein sollen – mtnielsen

1

NET USE können Sie einen lokalen Laufwerksbuchstaben für das Remote-System hinzuzufügen, die dann anschließend den Laufwerksbuchstaben in Ihrem PSSession verwenden Sie ermöglicht es, oder auch ohne PSSession. Dies ist hilfreich, wenn Sie Powershell v5 nicht haben.0, und auch wenn Sie das tun,

Sie den Namen Remote-Computer oder seine IP-Adresse als Teil des Remote-UNC-Pfad verwenden können und Sie den Benutzernamen und das Passwort, auf der gleichen Zeile angeben:

NET USE Z: \\192.168.1.50\ShareName /USER:192.168.1.50\UserName UserPassword 

Ein weiteres Beispiel:

NET USE Z: \\RemoteSystem\ShareName /USER:RemoteSystem\UserName UserPassword 

ODER

NET USE Z: \\RemoteSystem\ShareName /USER:Domain\UserName UserPassword 

Wenn Sie liefern nicht den Benutzer cr edentials auf der gleichen Linie, werden Sie für sie aufgefordert werden:

>NET USE Z: \\192.168.1.50\ShareName 
Enter the user name for '192.168.1.50': 192.168.1.50\UserName 
Enter the password for 192.168.1.50: ***** 
The command completed successfully. 

Sie den Laufwerksbuchstaben entfernen, wenn Sie mit den folgenden fertig sind:

NET USE Z: /delete 

Sie die vollständige Syntax mit NET bekommen BENUTZEN /?

>net use /? 
The syntax of this command is: 

NET USE 
[devicename | *] [\\computername\sharename[\volume] [password | *]] 
     [/USER:[domainname\]username] 
     [/USER:[dotted domain name\]username] 
     [/USER:[[email protected] domain name] 
     [/SMARTCARD] 
     [/SAVECRED] 
     [[/DELETE] | [/PERSISTENT:{YES | NO}]] 

NET USE {devicename | *} [password | *] /HOME 

NET USE [/PERSISTENT:{YES | NO}] 

NET ist ein Standard externer Exe-Befehl im Systemordner und arbeitet in Powershell einfach gut.

+0

Ist es nicht viel einfacher, nur Ihre Powershell auf v5 + zu aktualisieren? – Liam

Verwandte Themen