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

时间:2015-01-16 20:30:42

标签: events powershell logging hook

我想为一堆模块提供一些使用统计信息。

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

1 个答案:

答案 0 :(得分:2)

我并不完全清楚您是否对记录事件或执行代码(挂钩)更感兴趣。

登录

在Powershell写入日志的事件日志中有两个位置:

  • 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中,将提供更详细的日志记录(请参阅链接)。

来源

您可以在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代码。