Powershell卸载模块......完全

Eri*_*ver 36 .net powershell

我正在调试一个Powershell项目.我正在使用Import-Module从我的C#dll加载PS模块,一切正常.Remove-Module虽然DLL仍然被锁定且无法删除,但调用并未完全卸载模块.

有没有办法让PSH完全卸载模块并释放DLL,这样我就可以复制它并在Import-Module不重新启动PSH控制台的情况下重新加载它?

更新
因此,如果您将模块加载到单独的AppDomain中,它仍然像普通模块一样工作吗?谁能提供一个例子?

jpm*_*c26 27

有一个解决方法.打开另一个PowerShell实例:

PS > powershell
PS > [load DLL]
PS > [do work]
PS > exit
Run Code Online (Sandbox Code Playgroud)

在退出之后,您将被带回PowerShell的实例,您可以从中进行此调用(假设您在powershell内部进行调用并使用PowerShell实例).您可以传入任何常规参数powershell,因此您可以使用-Co​​mmand或-File.例如,

PS > powershell -Command '[load DLL]; [do work]' # Executes a command and exits
PS > powershell -Command '.\myscript.ps1 param1 param2' # Executes the script and exits
PS > powershell -File .\myscript.ps1 param1 param2 # Executes a script and exits.
Run Code Online (Sandbox Code Playgroud)

当PowerShell退出时,它将释放DLL上的锁定,允许您继续工作.

所有这些都是通过PowerShell命令行界面完成的.我没有测试如果你抛入powershell脚本中间或者如果这在ISE中工作会发生什么.(我怀疑它在ISE中有效.)即使if在脚本中不起作用,这在开发过程中仍然有用.

编辑:

做了一些检查.所以这似乎在脚本和ISE中都可以正常工作,但在ISE中有一个警告.在ISE中,当您在单独的PowerShell进程中时,无法读取用户的任何输入.如果您尝试,脚本或命令停止等待,但没有输入框像正常一样显示,当然,您不能直接键入ISE中的输出窗口.因此,如果您需要在中间提示输入[do work],请启动PowerShell的新实例之前进行提示,并将其作为参数传递给工作.如果您使用常规PowerShell命令行,这些都不是问题.

  • 我能想到的两个好处:首先,您将脚本块传递给作业,这允许您将脚本保存在一个源文件中.其次,您可以将(可序列化的)对象作为参数传递给作业,而不仅仅是文本参数.这是与你类似的解决方法,这就是为什么我没有把它作为一个单独的答案发布. (3认同)

小智 18

不会.由于PowerShell在其下使用.NET,因此具有相同的要求.在不卸载AppDomain本身的情况下,无法从.NET AppDomain卸载dll.由于PowerShell UI位于同一AppDomain中,因此无法实现.


Jes*_*ett 9

我在这里看到一些可行的答案,但这是我的,以防这对某人来说仍然是一个问题(这很懒,这很好).

Enter-PSSession -localcomputername
[load dlls]
[execute script(s)]
Exit-PSSession
Run Code Online (Sandbox Code Playgroud)

简而言之,为本地计算机创建PSSession会创建一个不同的PowerShell会话,包括被认为是"已加载"的会话,当您退出时,它会为您清理.


Kor*_*ill 8

在 Cmdlet 开发的上下文中,并且在卸载 DLL 时遇到问题,我使用了两种方法。

首先,我在 Visual Studio 中进行开发,并设置了一个外部程序 (PowerShell) 来加​​载我的 Cmdlet。这样,我的模块在我开始调试时加载,并在我停止调试时卸载。

其次,在我知道我想要加载一个模块、做一些工作并确保之后卸载模块的情况下,我使用 PowerShell 的第二个实例。这已在其他答案中讨论过,下面我的答案显示了我如何通过在我的个人资料中使用具有别名的函数来启用此工作流程。我更改了提示,以便我可以看到我在“递归 PowerShell 窗口”中的视觉提醒。

在您的配置文件中创建脚本以启动 PowerShell

function Start-DebugPowerShell
{
    PowerShell -NoProfile -NoExit -Command {
        function prompt {
            $newPrompt = "$pwd.Path [DEBUG]"
            Write-Host -NoNewline -ForegroundColor Yellow $newPrompt
            return '> '
        }
    }
}
Set-Alias -Name sdp -Value Start-DebugPowerShell
Run Code Online (Sandbox Code Playgroud)

编辑 Cmdlet 项目的调试设置

启动外部程序

C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe

命令行参数

-NoProfile -NoExit -Command "Import-Module .\MyCoolCmdlet.dll"

调试你的模块

现在,从 Visual Studio 中,使用 启动调试器F5,您将拥有一个加载了 Cmdlet 的新 PowerShell 窗口,您可以随意调试它。

在任何 PowerShell 窗口中使用“sdp”别名

由于 Start-DebugPowerShell 函数在我们的配置文件中,并且我们给它起了一个别名sdp,您可以随时使用它来启动 PowerShell 的第二个实例。


STW*_*STW 5

我相信这适用于PowerShell:在.NET世界中卸载程序集的唯一方法是将其加载到另一个程序集中AppDomain; 一旦装配件加载到一个装配件,AppDomain它的使用寿命就会保持不变AppDomain.


这是一个来自一个线程的例子,它提出了几乎相同的问题并展示了一些创建和加载模块到新AppDomain的方法:

http://www.eggheadcafe.com/conversation.aspx?messageid=30789124&threadid=30766269