如何跟踪某些模块的所有函数调用?

how to track all function calls of some modules?

我想要一些我的模块的使用统计数据。

如果我可以 运行 在从一组模块调用函数时编写代码,那将会很方便。可行吗? powershell 会生成我们可以挂接的内部事件吗?我还找不到任何指导

我不太清楚您是对记录事件更感兴趣还是对执行代码(挂钩)更感兴趣。

日志记录

Powershell 写入日志的事件日志中有 2 个地方:

  • Applications and Services > Windows PowerShell
  • Applications and Services > Microsoft > Windows > PowerShell

在每个模块级别,您可以启用 LogPipelineExecutionDetails 属性。要在加载时执行:

$mod = Import-Module ActiveDirectory
$mod.LogPipelineExecutionDetails = $true

或者对于已经加载的模块:

$mod = Get-Module ActiveDirectory
$mod.LogPipelineExecutionDetails = $true

之后您检查我列出的第一个事件日志位置 (Windows PowerShell),您将看到显示使用绑定参数调用各种 cmdlet 的日志。

您也可以通过组策略作为计算机或用户设置启用此功能:

  • Administrative Templates > Windows Components > Windows PowerShell > Turn On Module Logging

您可以指定要为其启用日志记录的模块。

在 PowerShell v5 中,将提供更详细的日志记录(请参阅 link)。

来源

您可以在 Boe Prox's blog: More New Stuff in PowerShell V5: Extra PowerShell Auditing

上查看有关日志记录设置(当前和未来)的更多详细信息

挂钩

据我所知,没有直接的方法来挂钩现有模块中的调用,但我有一个糟糕的解决方法。

You can effectively override existing cmdlets/functions by creating functions or aliases with the same name as the original.

使用此方法,您可以围绕要跟踪的特定函数创建包装器。考虑这样的事情:

# Override Get-Process
function Track-GetProcess {
[CmdletBinding()]
param(
    # All the parameters that the original function takes
)
    # Run pre-execution hook here
    & { "before" }

    $params = @{}
    foreach($h in $MyInvocation.MyCommand.Parameters.GetEnumerator()) {
        try {
            $key = $h.Key
            $val = Get-Variable -Name $key -ErrorAction Stop | Select-Object -ExpandProperty Value -ErrorAction Stop
            if (([String]::IsNullOrEmpty($val) -and (!$PSBoundParameters.ContainsKey($key)))) {
                throw "A blank value that wasn't supplied by the user."
            }
            Write-Verbose "$key => '$val'"
            $params[$key] = $val
        } catch {}
    }

    Get-Process @params # call original with splatting

    # run post execution hook here
    & { "after" }
}

中间还有uses splatting to send the given parameters and sending them to the real cmdlet.

最难的部分是手动重新创建参数块。如果您想快速 运行 挂钩任何函数,则可以通过编程方式执行此操作,但这有点超出了此答案的范围。如果您想走那条路,请查看 this New-MofFile.ps1 function 中的一些代码,它使用 powershell 自己的解析器解析 powershell 代码。