我有带有日志功能的基本PowerShell脚本和一些要运行的命令。我正在寻找一种登录日志文件命令的解决方案。
目前,我只知道这一点,但是复制+粘贴所有命令以被记录是非常烦人的:
$LogPath = "C:\Logs"
$FileName = (Get-Item $PSCommandPath).Basename
$LogFile = $LogPath + "\" + $FileName + ".log"
Function WriteLog
{
Param ([string]$LogString)
$Stamp = (Get-Date).toString("yyyy-MM-dd HH:mm:ss")
$LogMessage = "$Stamp $LogString"
Add-content $LogFile -value $LogMessage
}
WriteLog "***********************"
WriteLog ""
WriteLog "Command1"
Command1
WriteLog "Command2"
Command2
WriteLog "Command3"
Command3
WriteLog "Command4"
Command4
WriteLog "Command5"
Command5
WriteLog ""
WriteLog "***********************"发布于 2022-11-07 22:25:52
我建议如下:
{ ... })。# Create the logging function in a *dynamic module* (see below).
# Place this at the top of your script.
$null = New-Module {
# Define the log-file path.
$LogPath = 'C:\Logs'
$FileName = (Get-Item $PSCommandPath).Basename
$LogFile = $LogPath + '\' + $FileName + '.log'
# Create / truncate the file.
New-Item -Force -ErrorAction Stop $LogFile
function Add-LogMessage {
[CmdletBinding(DefaultParameterSetName = 'String')]
param(
[Parameter(Position = 0, Mandatory, ParameterSetName = 'ScriptBlock')]
[scriptblock] $ScriptBlock
,
[Parameter(Position = 0, ParameterSetName = 'String')]
[string] $String
)
# If a script block was given, use its string representation
# as the log string.
if ($ScriptBlock) {
# Make the string representation single-line by replacing newlines
# (and line-leading whitespace) with "; "
$String = $ScriptBlock.ToString().Trim() -replace '\r?\n *', '; '
}
# Create a timestamped message and append it to the log file.
$stamp = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss")
$logMessage = "$stamp $String"
Add-Content -LiteralPath $LogFile -Value $logMessage
# If a script block was given, execute it now.
if ($ScriptBlock) {
# Because this function is defined in a (dynamic) module,
# its invocation doesn't create a child scope of the *caller's* scope,
# and invoking the given script block, which is bound to the caller's scope,
# with . (dot-sourcing) runs it *directly in the caller's scope*.
. $ScriptBlock
}
}
}注意:
Add,这是一个认可动词;但是,为了简洁起见,也执行执行的方面( Invoke将是已批准的动词)没有反映在名称中。然后,您的脚本将如下所示:
Add-LogMessage "***********************"
Add-LogMessage ""
Add-LogMessage { Command1 }
Add-LogMessage { Command2 }
# ...
Add-LogMessage "***********************"注意:
New-Module中,它的调用不会创建调用方作用域的子作用域。{ ... })创建的脚本块时,可以使用.调用它,点源运算符直接在调用方的作用域中执行它,这意味着脚本块的代码可以自由地修改脚本的变量,就像将该代码直接放在脚本中一样。Tee-Object,如下所示(为了简单起见,我假设相同的目标日志文件,根据需要进行调整):
。$ScriptBlock / Tee-Object -Append -FilePath $LogFile- **Caveat**: As of PowerShell 7.2.x, `Tee-Object` uses a _fixed_ character encoding, namely UTF-16LE ("Unicode") in _Windows PowerShell_ and BOM-less UTF-8 in _PowerShell (Core) 7+_. [GitHub issue #11104](https://github.com/PowerShell/PowerShell/issues/11104) suggests adding an `-Encoding` parameter (which only future _PowerShell (Core)_ versions would benefit from).- Therefore, if you're using _Windows PowerShell_ and you're targeting the _same_ log file for capturing the output, be sure to modify the `Add-Content` call with `-Encoding Unicode` as follows:Add- -Encoding Unicode -LiteralPath $LogFile -Value $logMessage
- Alternatively, if you want to avoid UTF-16LE ("Unicode") files for their size (with all-ASCII characters, they're twice the size of ANSI and UTF-8 files), you can use one of the **workarounds** discussed in [this answer](https://stackoverflow.com/a/58922982/45375).https://stackoverflow.com/questions/74351332
复制相似问题