【发布时间】: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-Nouncmdlet 将来自何处(当然,除非您控制环境,或者脚本包含明确的#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