在 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 也应该至少对参数组合有效。
我有几个想法,但不确定是否可行。
- 创建一个 powershell 模块,例如PSRemotify 将探测远程服务器上的模块并生成代码。
- 如果我选择将文件写入文件系统,那么这应该是可行的,前提是我可以对 cmdlet 进行反射。
- 如果我不想保存文件,那么我需要在内存中做所有事情。我可以在内存中写入 cmdlet 的主体吗?我可以生成字符串并导入其嵌入的 cmdlet 吗?
- 创建执行 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.Management
从 SERVER
隐式导入 Get-Service
returns 来自 SERVER
.
的服务
你可以通过执行
真正看到代理cmdlets的实现
$module=Get-Module Microsoft.PowerShell.Management
$module.Definition
至少很有趣。
这是我想要实现的,但我找不到任何相关信息。
我想为远程服务器上可用的模块创建一个远程模块代理。
我知道如何使用远程处理,但我想要创建更清晰的脚本文件的东西。
举个例子。如果我想在远程计算机上从模块 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 也应该至少对参数组合有效。
我有几个想法,但不确定是否可行。
- 创建一个 powershell 模块,例如PSRemotify 将探测远程服务器上的模块并生成代码。
- 如果我选择将文件写入文件系统,那么这应该是可行的,前提是我可以对 cmdlet 进行反射。
- 如果我不想保存文件,那么我需要在内存中做所有事情。我可以在内存中写入 cmdlet 的主体吗?我可以生成字符串并导入其嵌入的 cmdlet 吗?
- 创建执行 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.Management
从 SERVER
隐式导入 Get-Service
returns 来自 SERVER
.
你可以通过执行
真正看到代理cmdlets的实现$module=Get-Module Microsoft.PowerShell.Management
$module.Definition
至少很有趣。