【问题标题】:Get all references to a given PowerShell module获取对给定 PowerShell 模块的所有引用
【发布时间】:2017-06-03 03:04:21
【问题描述】:

有没有办法找到引用给定模块 (.psm1) 的脚本文件列表?换句话说,获取在脚本代码中使用模块中定义的至少 1 个 cmdlet 的所有文件。

显然由于 PowerShell 3.0 及更高版本,我的大多数脚本文件在代码中的某处都没有明确的 Import-Module MODULE_NAME,因此我无法使用该文本进行搜索。

我知道我可以使用Get-ChildItem -Path '...' -Recurse | Select-String 'TextToSearchFor' 在文件中搜索特定字符串,但这与搜索对模块的任何 cmdlet 的任何引用不同。我可以搜索模块中的每个 cmdlet,但我想知道是否有更好的方法。

澄清:我只是在一个受控环境内部查看,我将所有脚本都放在一个文件位置。

【问题讨论】:

  • PowerShell 不是静态语言。从字面上看,仅查看脚本就无法知道在任何给定环境中Verb-Noun cmdlet 将来自何处(当然,除非您控制环境,或者脚本包含明确的#requires)。鉴于此,字符串匹配确实不是那么糟糕的一种方法。任何更复杂的东西都不太可能给出更准确的结果(如果脚本想要变得迟钝,这个问题通常是无法解决的)。
  • 不会有 100% 万无一失的方法来完成此任务。您可以使用 AST 来解析文件,但您必须记住,脚本可以稍后导入以前未导入的模块,它可以在运行时生成或下载新脚本然后导入它,它可以使用 @ 执行代码987654325@ 等。最全面的方法是执行每个脚本,然后在前后压缩加载的模块,但即使这样也容易出错;如果一个函数引用了一个 cmdlet 但您从不调用该函数怎么办。也许你可以用 Pester 和嘲笑做点什么?
  • 我想我应该澄清一下,我只是在一个受控环境内部查看,在这个环境中我将所有脚本都放在一个文件位置。字符串搜索可能仍然是最好的方法,但我不知道如何以一种有效的方式准确地做到这一点。我想对我环境中的 100 多个模块执行此操作,以查看哪些模块可能不再使用,所以我不想逐个检查并手动输入每个 cmdlet。
  • 至于被引用但未被调用的 cmdlet,我不在乎它是否真的被调用,只是被引用。我可以判断它是否在那个时候被使用。
  • 哦,既然您想要所有模块(跳过该位),您可能确实需要一个哈希表:$cmdlets = @{}; Get-Command -CommandType Cmdlet,Function | Foreach { $cmdlets[$_.Name] = $_.Module.Name }; dir *.ps1 | Select-String "\w+-\w+" | Foreach { $cmdlets[$_.Matches[0].Value] } | Sort-Object -Unique 给出了所有使用的模块的(近似)列表(有些模块不清楚宣传他们的 cmdlet)。它在我的机器上相当快。生成所有 not 使用的模块的列表几乎没有涉及,但到那时我可能会发布一个实际答案。 :-P

标签: powershell


【解决方案1】:

根据场景,调用堆栈可能会很有趣。在这种情况下,您需要修改要查找的函数,以在运行时收集有关调用堆栈的信息并将其记录在某处。随着时间的推移,您可能有足够的日志来做出一些好的假设。

function yourfunction {
    $stack = Get-PSCallStack
    if ($stack.Count -gt 1) {
        $stack[1] # log this to a file or whatever you need
    }
}

这在你的场景中可能根本不起作用,但我想我把它作为一个选项扔在那里。

【讨论】:

    猜你喜欢
    • 2016-03-15
    • 2013-10-15
    • 1970-01-01
    • 1970-01-01
    • 2023-02-03
    • 1970-01-01
    • 2012-03-04
    • 2013-09-15
    • 1970-01-01
    相关资源
    最近更新 更多