在 PowerShell 中动态创建 cmdlets/module

Dynamically create a cmdlets/module in PowerShell

这是我想要实现的,但我找不到任何相关信息。

我想为远程服务器上可用的模块创建一个远程模块代理。

我知道如何使用远程处理,但我想要创建更清晰的脚本文件的东西。

举个例子。如果我想在远程计算机上从模块 MyModule 执行 MyCmdlet,我会这样做

$block={
    # Invoke the cmdlet from a module named MyCmdlet
    MyCmdlet -Parameter1 -Parameter2
}

Invoke-Command -ComputerName "" -ScriptBlock $block

但我想着陆到这样的地方

Import-Module MyModuleRemote
MyCmdlet -ComputerName "" -Parameter1 -Parameter2

请注意 MyModule 没有安装在我的客户端机器上。

我可以为每个 cmdlet 使用 Invoke-Command 包装器重新编写模块,但这不是目的。我想做的是通过为每个 cmdlet 和参数创建一个代理相等代理来远程化 MyModule。即使是 Get-Help 也应该至少对参数组合有效。

我有几个想法,但不确定是否可行。

  1. 创建一个 powershell 模块,例如PSRemotify 将探测远程服务器上的模块并生成代码。
    1. 如果我选择将文件写入文件系统,那么这应该是可行的,前提是我可以对 cmdlet 进行反射。
    2. 如果我不想保存文件,那么我需要在内存中做所有事情。我可以在内存中写入 cmdlet 的主体吗?我可以生成字符串并导入其嵌入的 cmdlet 吗?
  2. 创建执行 1.2 的脚本。

我的偏好是选项 1.2。非常干净,没有在文件系统上留下任何痕迹。

有什么想法吗?有人试过类似的东西吗?

经过我的调查和@Persistent13 的回答得出的结论:

PowerShell 提供开箱即用的此功能。它被称为 IMPLICIT REMOTING。在@Persistent13 的回答之前,我选错了部分,因为我认为分享我的经验很有趣,我已经写了博客。 import and use module from a remote server

听起来您正在寻找的是隐式远程处理,而且设置起来相当简单。

请注意,我已经从 here 那里获取了相关说明。

要创建隐式会话,您需要:

PS C:\> $foo = New-PSSession -ComputerName DC1
PS C:\> Import-Module -PSSession $foo -Name ActiveDirectory
PS C:\> Get-ADUser

以上将在计算机 DC1 上打开一个 PowerShell 会话,在远程计算机上导入 ActiveDirectory 模块,命令 运行 针对远程计算机,但看起来是在本地执行。

也可以为隐式导入的模块添加前缀,以防本地模块与远程模块发生冲突。

PS C:\> $foo = New-PSSession -ComputerName DC1
PS C:\> Import-Module -PSSession $foo -Name ActiveDirectory -Prefix DC1
PS C:\> Get-DC1ADUser

这样做的好处是不需要远程处理您的模块,只要它存在于远程计算机上并且允许 PowerShell 远程处理。

然而,此方法的一个警告是返回的对象类型将会改变。

Deserialized.Microsoft.ActiveDirectory.Management.ADUser 使用隐式远程处理时。

Microsoft.ActiveDirectory.Management.ADUser 当 运行 在本地时。

我当时提这个问题的时候并不知道隐式远程处理的概念

实际上,您使用 Import-Module 导入模块,但您还使用 -Session 参数指定到远程服务器的会话。

例如从服务器 $target="SERVER" 导入 Microsoft.PowerShell.Management 执行这个

$session=New-PSSession -ComputerName $target
Import-Module Microsoft.PowerShell.Management -Session $session

由此在当前会话中生成一个代理模块,它提供与指定的相同的 cmdlet。代理 cmdlet 自动将参数推送到远程会话 $session 并捕获其输出。使用 Microsoft.PowerShell.ManagementSERVER 隐式导入 Get-Service returns 来自 SERVER.

的服务

你可以通过执行

真正看到代理cmdlets的实现
$module=Get-Module Microsoft.PowerShell.Management
$module.Definition

至少很有趣。