# create a new custom validation attribute named "LogVariableAttribute": classIdentifyTypeAttribute : System.Management.Automation.ValidateArgumentsAttribute {
# this gets called whenever a new value is assigned to the variable:
[void]Validate([object]$value, [System.Management.Automation.EngineIntrinsics]$engineIntrinsics) { # get the global variable that logs all changes: [System.Management.Automation.PSVariable]$variable = Get-Variable"loggedTypes"-Scope global -ErrorAction Ignore # if the variable exists and does not contain an ArrayList, delete it: if ($variable-ne$null-and$variable.Value -isnot [System.Collections.ArrayList]) { $variable = $null } # if the variable does not exist, set up an empty new ArrayList: if ($variable-eq$null) { $variable = Set-Variable-Name"loggedTypes"-Value ([System.Collections.ArrayList]@()) -Scope global -PassThru }
# log the type contained in the variable $null = $variable.Value.Add([PSCustomObject]@{ # use the optional source name that can be defined by the attribute: Value = $value.GetType() Timestamp = Get-Date # use the callstack to find out where the assignment took place: Name = [regex]::Match($line, $pattern).Groups[1] Position = [regex]::Match($line, $pattern).Groups[1].Index + (Get-PSCallStack)[-1].Position.StartOffset Line = (Get-PSCallStack).ScriptLineNumber | Select-Object-Last1 Path = (Get-PSCallStack).ScriptName | Select-Object-Last1 })
} } }
现在,在您的脚本中,在开始时,通过添加新属性来初始化要跟踪的所有变量:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
[IdentifyType()]$test = 1 [IdentifyType()]$x = 0
# start using the variables: for ($x = 1000; $x-lt3000; $x += 300) { "Frequency $x Hz" [Console]::Beep($x, 500) }
functionInvoke-Selection { try { # get the selected text: $selectedText = $psise.CurrentFile.Editor.SelectedText # if no text was selected... if ($selectedText.Length -eq0) { # ...select the line the caret is in and get this line instead: $psise.CurrentFile.Editor.SelectCaretLine() $selectedText = $psise.CurrentFile.Editor.SelectedText }
# try and parse the code $sb = [ScriptBlock]::Create($selectedText)
# get the missing variable content from the underlying file: $currentFile = $psise.CurrentFile.FullPath $currentFolder = Split-Path-Path$currentFile
# append the selected code with these automatic variables, and set them: $runcode = @" `$PSCommandPath = '$currentFile' `$PSScriptRoot = '$currentFolder' $selectedText "@ # turn text into script block... $scriptblock = [ScriptBlock]::Create($runcode) # ...and execute it without private scope: . $scriptblock