16

有没有办法在远程会话中使用在本地会话中导入的模块?我查看了 import-pssession,但我不知道如何获取本地会话。这是我想做的一个示例。

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

另外,我不想在远程会话中导入模块,因为 ps1 文件不在该服务器上。

4

7 回答 7

10

我最终破解了这个工作。我所做的是创建一个本地会话,将模块导入该会话并使用 import-pssession 将模块从创建的本地会话导入远程会话。这很慢。如果有人有更好的方法来做到这一点,或者如果有人知道如何获取基本会话的实例,我很乐意听取您的意见!

远程处理.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 
  }
 }
}

我的模块.psm1

function MyCmdlet {}

远程测试.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
}
于 2010-05-14T16:33:08.583 回答
3

作为 Jonathan 提到的替代方案,如果您有源模块想要通过网络推送,那么您可以轻松地做到这一点。如果你有二进制文件,你也许可以做类似的事情。但我想说所有的赌注都在那里。本质上,您将文件作为哈希中的参数推送,写入临时文件,然后导入。

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
}

打电话喜欢

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

理论上也是可能的,将当前的本地主机会话导出到模块并将其推送到网络上——未经测试的伪代码。这可能行不通...

$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
于 2012-04-26T17:30:01.690 回答
2

如果这有帮助:

如果您可以切换到PowerShell 3.0,则 Get-Module 和 Import-Module cmdlet 支持远程计算机上的模块:

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

应该可以在执行 Import-Module 的远程计算机上运行 PowerShell,而无需在远程计算机上安装任何 ps1 脚本。

于 2012-11-22T12:27:16.907 回答
2

所以我一直在寻找类似的东西......在我的情况下,我只需要将一个函数导出到远程会话......这就是我想出的。也许你可以遍历它来尝试一下。它不适用于内部命令,但它确实适用于自定义模块中的功能(在我所做的测试中)。

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
}
于 2017-08-04T17:29:24.997 回答
0

我不相信你可以。您可以采用另一种方式 - 将远程计算机上加载的命令导入本地计算机上运行的远程会话。您可以指定一个脚本来调用命令,它将将该脚本复制到远程计算机并运行它。但是,如果您需要管理单元或其他模块,则需要确保将它们安装在每台远程计算机上,然后通过命令或脚本将它们加载到远程会话中。

于 2010-05-14T16:06:35.920 回答
0

我会建议类似:

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

从那时起,您可以在会话中使用 ActiveDirectory cmdlet。

希望这可以帮助。

于 2011-08-11T13:22:37.027 回答
-2

使用 credssp 认证

invoke-command -computername $localSession -Credential $Credential -Authentication Credssp
于 2016-09-06T07:42:23.697 回答