web-dev-qa-db-fra.com

Envoyer des fichiers via PSSession

Je viens de passer quelques heures à chercher une solution pour envoyer des fichiers via une session PSSession active. Et le résultat est nada, niente. J'essaie d'appeler une commande sur un ordinateur distant via une session active, qui devrait copier quelque chose d'un stockage réseau. Donc, fondamentalement, c'est ça:

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

À cause du problème du "second saut", je ne peux pas le faire directement, et comme je suis sous Win Server 2003, je ne peux pas activer CredSSP. Je pourrais d’abord copier les fichiers sur mon ordinateur, puis les envoyer/les envoyer à la machine distante, mais comment? J'ai essayé PModem , mais comme je l'ai vu, il ne peut extraire que des données et non Push.

Toute aide est appréciée.

20
kalbsschnitzel

S'il s'agissait d'un petit fichier, vous pouvez envoyer le contenu du fichier et le nom du fichier en tant que paramètres.

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

Si le fichier est trop long pour tenir dans les limites de la session, vous pouvez le lire en morceaux et utiliser une technique similaire pour les ajouter ensemble à l'emplacement cible

20
Mike Shepard

Ceci est maintenant possible dans PowerShell/WMF 5.0

Copy-Item a les paramètres -FromSession et -toSession. Vous pouvez utiliser l'un de ceux-ci et transmettre une variable de session.

par exemple.

$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

Voir d'autres exemples à https://richardspowershellblog.wordpress.com/2015/05/28/copy-files-over-ps-remoting-sessions/

36
David Gardiner

Il y a quelque temps, j'ai rencontré le même problème et mis au point une preuve de concept pour l'envoi de fichiers via une session PS Remoting. Vous trouverez le script ici:

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
}

Certaines modifications mineures lui permettraient d’accepter une session en tant que paramètre au lieu d’en démarrer une nouvelle. J'ai constaté que la consommation de mémoire sur le service Remoting sur l'ordinateur de destination pouvait devenir assez importante lors du transfert de fichiers volumineux. Je soupçonne que PS Remoting n'a pas vraiment été conçu pour être utilisé de cette façon.

2
Jason Stangroome

Net Usevous permet d'ajouter une lettre de lecteur local pour le système distant, ce qui vous permet ensuite d'utiliser la lettre de lecteur dans votre PSSession, ou même sans PSSession. Ceci est utile si vous n’avez pas Powershell v5.0, et même si vous en avez, 

Vous pouvez utiliser le nom de l'ordinateur distant ou son adresse IP dans le chemin UNC distant et vous pouvez spécifier les informations d'identification du nom d'utilisateur et du mot de passe sur la même ligne:

    Net Use Z: \\192.168.1.50\ShareName /USER:192.168.1.50\UserName UserPassword  

Un autre exemple: 

    Net Use Z: \\RemoteSystem\ShareName /USER:RemoteSystem\UserName UserPassword  

OU 

    Net Use Z: \\RemoteSystem\ShareName /USER:Domain\UserName UserPassword  

Si vous ne fournissez pas les informations d'identification de l'utilisateur sur la même ligne, vous serez invité à les entrer:

>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.

Vous pouvez supprimer la lettre de lecteur lorsque vous avez terminé avec les éléments suivants:

    Net Use Z: /delete

Vous pouvez obtenir la syntaxe complète avec Net Use /? 

>Net Use /?
The syntax of this command is:

Net Use
[devicename | *] [\\computername\sharename[\volume] [password | *]]
        [/USER:[domainname\]username]
        [/USER:[dotted domain name\]username]
        [/USER:[username@dotted domain name]
        [/SMARTCARD]
        [/SAVECRED]
        [[/DELETE] | [/PERSISTENT:{YES | NO}]]

Net Use {devicename | *} [password | *] /HOME

Net Use [/PERSISTENT:{YES | NO}]  

NET est une commande .exe externe standard dans le dossier système et fonctionne parfaitement dans Powershell.

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

Je ne sais pas réellement quelle est la limite de taille de fichier maximale. 

0
mtnielsen