2010-05-13 11 views
14

¿Hay alguna manera de usar módulos que se importaron en una sesión local en una sesión remota? Miré import-pssession, pero no sé cómo obtener la sesión local. Aquí hay una muestra de lo que quiero hacer.Remoting de Powershell: uso de cmdlets de módulo importados en una sesión remota

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

Además, yo no quiero importar-módulo en la sesión remota, como los archivos de PS1 no están en ese servidor.

Respuesta

0

No creo que puedas. Puede ir por el otro lado: importar comandos cargados en la máquina remota en su sesión remota ejecutándose en la máquina local. Puede especificar un script para invocar-comando y copiará ese script en el equipo remoto y lo ejecutará. Pero si necesita snapins o módulos adicionales, deberá asegurarse de que estén instalados en cada equipo remoto y luego cargarlos en la sesión remota mediante comandos o su secuencia de comandos.

10

Terminé pirateando esto para trabajar. Lo que hice fue crear una sesión local, importar módulos en esa sesión y usar import-pssession para importar módulos de la sesión local creada a la sesión remota. Esto es lento Si alguien tiene una mejor manera de hacerlo, o si alguien sabe cómo obtener una instancia de la sesión base, me encantaría saber de usted.

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

Me corrigieron. :-) Buen enfoque de tomar la capacidad de importar comandos de la computadora remota y convertirlo en su cabeza para importar desde la computadora local. Por cierto, ¿está importando basado en Path (en lugar de nombre del módulo) porque se encontró con un problema? –

+0

Solo puede importar un módulo por nombre si el archivo del módulo se encuentra en una de las ubicaciones predeterminadas del módulo. Si no es así, debe darle la ruta del archivo. Me encontré con un problema con los módulos de ensamblaje que se importan desde un manifiesto de módulo psd1. La propiedad PSModuleInfo.Path para un módulo binario apunta al dll en lugar de a la psd1. Si importa directamente desde el dll, entonces import-pssession fallará. De ahí todo el vudú para obtener el archivo psd1 para un módulo de ensamblaje. –

+0

¿Todavía usa este método o encontró una forma mejor de hacerlo? – icnivad

0

Yo sugeriría algo así como:

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

Desde entonces, puede usar cmdlets ActiveDirectory en su sesión.

Espero que esto ayude.

3

Como una alternativa a lo que Jonathan menciona, si tiene módulos de fuente que desea pasar por el cable, puede hacerlo sin demasiados problemas. Si tiene binarios, puede ser capaz de hacer algo similar. Pero yo diría que todas las apuestas están ahí. Esencialmente empuja los archivos como params en un hash, escribe en temp, luego 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 
} 

llamada Al igual que

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

también teóricamente posible, la exportación de una sesión de host local actual al módulo y empujando que sobre el alambre - no probado pseudo-código. Esto podría no funcionar ...

$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

Consejo: si el módulo está ubicado en la ruta de PSModule o ya está cargado, puede ser útil cambiar la evaluación de ModulePaths a (Get-Module $ Module) .Path – 2xMax

+0

¡Impresionante, funciona muy bien! – ssougnez

2

en caso de que esto ayuda:

si se puede cambiar a PowerShell 3.0, entonces los módulos de soporte cmdlets Import-Module Get-Module y en equipos remotos:

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

Debería ser posible ejecutar PowerShell en el equipo remoto, que realiza módulo de importación, sin tener ningún scripts ps1 en la computadora remota.

+0

Probablemente necesitamos PS 3.0 en ambos extremos, ¿no? – icnivad

-2

uso CredSSP autenticación

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

Así que yo estaba buscando algo similar ... En mi caso sólo necesitaba para exportar una única función a una sesión remota ... esto es lo que ocurrió. Tal vez podrías recorrerlo para probarlo. No funciona con comandos internos, pero funciona en funciones en módulos personalizados (en las pruebas que he hecho).

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 
} 
Cuestiones relacionadas