【问题标题】:Debugging / unloading PowerShell Cmdlet调试/卸载 PowerShell Cmdlet
【发布时间】:2016-06-25 08:53:51
【问题描述】:

我正在使用 Visual Studio 2015 在 C# 中编写一个 PowerShell Cmdlet。调试它工作正常,但我无法重建 DLL,直到我关闭 PowerShell 窗口。 DLL 似乎正在使用中,因此无法删除(不是在命令行上也不是使用资源管理器)。我试过删除模块。这成功删除了我的 Cmdlet,但我仍然无法删除/覆盖它。

关闭 PowerShell,重建 DLL,然后重新打开一个新的 PowerShell,cd 到 DLL 路径(通常是深度嵌套),再次重新导入,启动命令进行调试,等等,非常不方便。调试会话...

有没有更好的办法卸载DLL?

【问题讨论】:

  • AFAIK,无法卸载。我也遇到过这种情况。
  • 是否可以选择新的 powershell 配置文件?
  • 这个问题不是@beavel 提到的问题的重复,因为在这种情况下,问题是关于使用 Visual Studio 和调试模块,而不是尝试卸载它并像另一个一样复制文件问题呼唤。在调试的上下文中,有一个答案,我已经在下面发布了。
  • @KoryGill 我明白你的意思。但是从技术上讲,正如我引用的问题所表明的那样,一旦将 DLL 加载到 AppDomain 中,就无法卸载它。这个问题说的是卸载,但实际上是关于重新阅读后的工作。您建议的工作流程绝对是一种改进。

标签: c# visual-studio powershell


【解决方案1】:

每当我看到这样的事情时:

关闭powershell,重新构建dll,然后重新打开一个新的powershell,cd到dll路径(通常嵌套很深),重新导入,启动命令首次亮相,等等。单个调试会话...

我立刻想到,“我应该创建一个脚本来为我完成这些任务”。

有解决办法。您可以启动第二个 PowerShell(如建议的另一个答案)。另一种解决方案是使用脚本为您做一些工作,最重要的是,您可以将其添加到您的 VS 项目中。

在您的配置文件中创建一个脚本以启动 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

编辑 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 实例。

【讨论】:

  • 这应该被标记为答案。 Kory 的解决方案在带有 Powershell 7 的 VS 2019 中也表现出色。只需将外部程序更改为pwsh.exe
【解决方案2】:

据我所知,恐怕您对这种行为无能为力。一个技巧是在加载 DLL 之前立即在现有会话中启动一个新的 PowerShell 会话。然后你可以退出第二个,你有一个全新的,没有加载 DLL。请记住在再次加载之前启动一个新的“辅助”会话,以防您需要再次卸载它。

【讨论】:

  • 我认为你是对的(不幸的是)。对于调试,还需要在 Visual Studio 中附加正确的进程。因此,启动调试会话总是需要一些“手动工作”。
  • Kory Gill 下面的回答非常棒。它应该被标记为这个问题的答案。它在带有 PowerShell 7 的 VS2019 中也很有效。
【解决方案3】:

我使用了helper powershell script,它为我完成了大部分工作。

    $module = 'AccessLogParser'
    Push-Location $PSScriptroot

    dotnet build -o $PSScriptRoot\output\$module\bin
    Import-Module "$PSScriptRoot\Output\$module\bin\$module.dll"
    $VerbosePreference = $DebugPreference="continue"
    Write-Debug "$pid - $($PSVersionTable.PSVersion)"

在启动配置中有两个选项,帮助程序输出终端进程(vscode 的底部)正在运行的当前进程 ID,当我启动调试器时,我可以在下拉列表中选择该 PID。当您想为旧的 v5 powershell 以及 v7 (pwsh.exe) 版本开发一些东西时很有帮助。

 {
            "name": ".NET Framework Attach",
            "type": "clr",
            "request": "attach",
            "processId": "${command:pickProcess}"
        },
        {
            "name": ".NET Core Attach",
            "type": "coreclr",
            "request": "attach",
            "processId": "${command:pickProcess}"
        }

【讨论】:

    【解决方案4】:

    https://docs.microsoft.com/en-us/powershell/scripting/dev-cross-plat/vscode/using-vscode-for-debugging-compiled-cmdlets - 该文档讨论了 DLL 锁定问题 /edit>

    添加到@kory-gill 的答案,这是我的launch.json:

    {
        "name": ".NET Core Launch (console)",
        "type": "coreclr",
        "request": "launch",
        "preLaunchTask": "build",
        "cwd": "${workspaceFolder}",
        "program": "pwsh",
        "args": [
            "-NoExit",
            "-NoProfile",
            "-Command",
            "ipmo ${workspaceFolder}/DependencyTree/bin/Debug/netstandard2.0/DependencyTree.dll",
        ],
        "console": "integratedTerminal",
        "stopAtEntry": false
    }
    

    我的项目名为DependencyTree。替换为您自己的项目名称。

    -NoProfile 对我来说很重要,因为我的配置文件很大并且会破坏调试器。

    更一般地说,我设置了 PSReadline,你也应该,在终端会话中保留历史记录。所以我可以Ctrl-R 并召唤我很久以前输入的任何命令。配置后,以下内容在与已编译或 Powershell 类交互工作时非常有用,并且在处理模块的非导出成员时也很有用:

    1. 使用键盘快捷键创建和删除终端。在 VS Code 中,终端应视为一次性的。
    2. $host.ExitNestedPrompt(); $Module = ipmo .\DependencyTree.psd1 -Force -PassThru; & $Module {$host.EnterNestedPrompt()}

    & $Module { ... } 技巧在模块范围内运行该脚本块。对向导非常有用;-)

    【讨论】:

      猜你喜欢
      • 2011-03-20
      • 2013-06-08
      • 2018-06-21
      • 2014-02-28
      • 2020-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-17
      相关资源
      最近更新 更多