2010-05-13 12 views
14

Esiste un modo per utilizzare i moduli importati in una sessione locale in una sessione remota? Ho guardato alla pssession di importazione, ma non so come ottenere la sessione locale. Ecco un esempio di ciò che voglio fare.Remot PowerShell: utilizzo di cmdlet di moduli importati in una pssessione remota

import-module .\MyModule\MyModule.ps1 
$session = new-pssession -computerName RemoteComputer 
invoke-command -session $session -scriptblock { Use-CmdletFromMyModule } 

Inoltre, non desidero import-module nella sessione remota, poiché i file ps1 non si trovano su quel server.

risposta

0

Non credo che tu possa. È possibile passare dall'altra parte: importare i comandi caricati sulla macchina remota nella sessione remota in esecuzione sul computer locale. È possibile specificare uno script per invocare-comando e copierà quello script sul computer remoto ed eseguirlo. Ma se hai bisogno di snap-in o moduli aggiuntivi, dovrai assicurarti che siano installati su ogni macchina remota e poi caricarli nella sessione remota tramite i comandi o il tuo script.

10

Ho finito per hackerarlo per funzionare. Quello che ho fatto è stato creare una sessione locale, importare moduli in quella sessione e usare import-pssession per importare i moduli dalla sessione locale creata nella sessione remota. Questo è lento. Se qualcuno ha un modo migliore di farlo, o se qualcuno sa come ottenere un'istanza della sessione di base mi piacerebbe sentirti!

Remoting.psm1

function Export-ModuleToSession { 
Param(
    [ValidateNotNull()] 
    $session, 
    [ValidateNotNull()] 
    $modules 
) 

$computername = $env:computername 

$modulesToImport = get-module -name $modules 

invoke-command -session $session -argumentlist @($computername, $modulesToImport) -scriptblock { 
    Param(
    $computername, 
    $modules 
) 

    write-host ("Creating Temp Session On: " + $computername) 

    $localSession = New-psSession -computername $computername 

    $modules | foreach-object { 
    if($_.ModuleType -ne "Binary") { 
    $path = $_.path 
    } 
    else { 
    $path = join-path (split-path $_.Path) ("{0}.psd1" -f $_.name) 
    } 

    invoke-command -session $localSession -argumentList $path -scriptblock { 
    Param(
    $path 
    ) 

    $initializeDefaultBTSDrive = $false 
    set-executionpolicy unrestricted 

    write-host ("Importing Module To Temp Session: " + $path) 
    import-module $path 
    } 
    } 

    $initializeDefaultBTSDrive = $false 

    $modules | foreach-object { 
    write-host ("Exporting Module: " + $_.name) 
    import-psSession -session $localSession -Module $_.name | out-null 
    } 
} 
} 

MyModule.psm1

function MyCmdlet {} 

RemotingTest.ps1

import-module .\remoting.psm1 
import-module .\MyModule.psm1 

try 
{ 
$remoteSession = New-PsSession -computerName "RemoteComputer" 
Export-ModuleToSession -session $remoteSession -modules "MyModule" 

Invoke-Command -session $remoteSession -scriptblock { MyCmdlet } -verbose -ea Stop 
} 
finally 
{ 
Remove-PsSession $remoteSession -ea Continue 
Remove-Module "Remoting" -ea Continue 
Remove-Module "MyModule" -ea Continue 
} 
+0

Sono in posizione corretta. :-) Un buon approccio nel prendere la capacità di importare commmands dal computer remoto e girarlo in testa per importarlo dal computer locale. A proposito, stai importando in base al percorso (anziché al nome del modulo) perché hai riscontrato un problema? –

+0

È possibile importare un modulo solo per nome se il file del modulo si trova in una delle posizioni predefinite del modulo. Se non lo è, devi dargli il percorso del file. Mi sono imbattuto in un problema con i moduli assembly che sono stati importati da un manifest manifest di psd1. La proprietà PSModuleInfo.Path per un modulo binario punta alla DLL invece che a psd1. Se si importa direttamente dalla dll, quindi import-pssession fallirà. Quindi tutto il voodoo per ottenere il file psd1 per un modulo assembly. –

+0

Usi ancora questo metodo o hai trovato un modo migliore per farlo? – icnivad

0

vorrei suggerire qualcosa di simile:

$rs = New-PSSession -ComputerName "RemoteComputer" 
Invoke-Command -Session $rs -scriptblock {import-module ActiveDirectory} 
Import-PSSession -Session $rs -Module ActiveDirectory 

Da allora, è possibile utilizzare i cmdlet ActiveDirectory nella sessione.

Spero che questo aiuti.

3

In alternativa a ciò che Jonathan menziona, se si dispone di moduli di origine che si desidera spingere sul filo, è possibile farlo senza troppi problemi. Se hai i binari, puoi essere in grado di fare qualcosa di simile. Ma direi che tutte le scommesse sono lì. In pratica si spinge i file come parametri in un hash, si scrive in temp, quindi si importa.

function Export-SourceModulesToSession 
{ 
    Param(
    [Management.Automation.Runspaces.PSSession] 
    [ValidateNotNull()] 
    $Session, 

    [IO.FileInfo[]] 
    [ValidateNotNull()] 
    [ValidateScript(
    { 
     (Test-Path $_) -and (!$_.PSIsContainer) -and ($_.Extension -eq '.psm1') 
    })] 
    $ModulePaths 
) 

    $remoteModuleImportScript = { 
    Param($Modules) 

    Write-Host "Writing $($Modules.Count) modules to temporary disk location" 

    $Modules | 
     % { 
     $path = ([IO.Path]::GetTempFileName() + '.psm1') 
     $_.Contents | Out-File -FilePath $path -Force 
     "Importing module [$($_.Name)] from [$path]" 
     Import-Module $path 
     } 
    } 

    $modules = $ModulePaths | % { @{Name = $_.Name; Contents = Get-Content $_ } } 
    $params = @{ 
    Session = $Session; 
    ScriptBlock = $remoteModuleImportScript; 
    Argumentlist = @(,$modules); 
    } 

    Invoke-Command @params 
} 

chiamata come

$session = New-PSSession -ComputerName Foo 
Export-SourceModulesToSession $session -ModulePaths '.\module.psm1','.\module2.psm1' 

anche teoricamente possibile, l'esportazione di una sessione di localhost corrente al modulo e spingendo che sul filo - non testata pseudo-codice. Questo potrebbe non funzionare ...

$localSession = New-PSSession #defaults to localhost 

# if you don't have modules automatically loading in the profile, etc, then manually load them 
Invoke-Command -Computer $localSession -ScriptBlock { Import-Module 'foo'; Import-Module '.\module.ps1' } 
Export-PSSession $localSession -OutputModule TempLocalModule 
#now that you have TempLocalModule written out, it's possible you can send that thing across the wire in the same way 
+0

Suggerimento: se il modulo si trova nel percorso PSModule o è già caricato, può essere utile modificare la valutazione di ModulePaths su (Modulo Get-Module $) .Path – 2xMax

+0

Fantastico, funziona molto bene! – ssougnez

2

nel caso in cui questo aiuta:

se è possibile passare alla PowerShell 3.0, quindi Get-Module e Import-Module moduli di supporto cmdlet su computer remoti:

http://technet.microsoft.com/en-us/library/hh857339.aspx#BKMK_REM

Dovrebbe essere possibile eseguire PowerShell sul computer remoto, che esegue Import-Module, senza avere alcuna script ps1 sul computer remoto.

+0

Probabilmente abbiamo bisogno di PS 3.0 su entrambe le estremità, no? – icnivad

-2

utilizzo CredSSP autenticazione

invoke-command -computername $localSession -Credential $Credential -Authentication Credssp 
0

Quindi ero alla ricerca di qualcosa di simile ... Nel mio caso ho solo bisogno di esportare una singola funzione ad una sessione remota ... questo è ciò che mi è venuta. Forse potresti passarci sopra per provarlo. Non funziona con i comandi interni, ma funziona sulle funzioni nei moduli personalizzati (nel test che ho fatto).

function Export-FunctionToSession 
{ 
    [CmdletBinding()] 
    [Alias()] 
    [OutputType([int])] 
    Param 
    (
     [Parameter(Mandatory=$true, 
        ValueFromPipelineByPropertyName=$true, 
        Position=0)] 
     $Session, 
     [Parameter(Mandatory=$true, 
        ValueFromPipelineByPropertyName=$true, 
        Position=0)] 
     $FunctionName 
    ) 
    $script = "Function $functionName(){" + (Get-Command $functionName).definition + '}' 
    $scriptBlock = {Invoke-Expression $using:script} 
    Invoke-Command -Session $session -ScriptBlock $scriptBlock 
} 
Problemi correlati