如何跟踪某些模块的所有函数调用?
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
上查看有关日志记录设置(当前和未来)的更多详细信息
挂钩
据我所知,没有直接的方法来挂钩现有模块中的调用,但我有一个糟糕的解决方法。
使用此方法,您可以围绕要跟踪的特定函数创建包装器。考虑这样的事情:
# 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 代码。
我想要一些我的模块的使用统计数据。
如果我可以 运行 在从一组模块调用函数时编写代码,那将会很方便。可行吗? 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
上查看有关日志记录设置(当前和未来)的更多详细信息挂钩
据我所知,没有直接的方法来挂钩现有模块中的调用,但我有一个糟糕的解决方法。
使用此方法,您可以围绕要跟踪的特定函数创建包装器。考虑这样的事情:
# 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 代码。