nightroman's profileRoman's SpaceBlog Tools Help

Roman's Space

PowerShelf
October 16

Get names of script parameters


This function parses parameters of a script and returns parameter names. For example, I use it in my own TabExpansion procedure. It requires PowerShell V2 CTP2.
# Get names of script parameters
# Author: Roman Kuzmin
function GetScriptParameter ( # Full script path $Path, # Script code (if $Path is not defined) $Script, # Parameter wildcard pattern (to get a subset) $Pattern ) { if ($Path) { $Script = [IO.File]::ReadAllText($Path) } $mode = 0 $param = $true foreach($t in ([Management.Automation.PSParser]::Tokenize($Script, [ref]$null))) { switch($t.Type) { 'NewLine' { break } 'Comment' { break } 'Command' { if ($mode -le 1) { if ($mode -eq 0 -and $t.Content -eq 'param') { $mode = 1 break } return } break } 'Keyword' { if ($mode -eq 0) { if ($t.Content -eq 'param') { $mode = 1 break } } } 'GroupStart' { if ($mode) { ++$mode break } else { return } } 'GroupEnd' { --$mode if ($mode -lt 2) { return } } 'Variable' { if ($mode -eq 2 -and $param) { $param = $false if ((!$Pattern) -or ($t.Content -like $Pattern)) { $t.Content } break } } 'Operator' { if (($mode -eq 2) -and ($t.Content -eq ',')) { $param = $true } } } } }

May 07

V2: Debugger for Graphical PowerShell V2 CTP2

V1 is here...

 

What's new in V2
  • ProcessDebuggerStop is called dot-sourced, so that debug expressions are invoked in the current scope and normally you can change local variables directly;
  • Local variables of ProcessDebuggerStop moved to $global:__DebuggerStop members (to avoid clashes with real variables and debug expressions);
  • 10 ($__DebuggerStop.MaximumHistoryCount) last debug expressions are kept in history and shown in the dialog, you can copy and paste them;
  • <enter> repeats the last step or step-over command (similar to ConsoleHost).
  • Added two new debug commands (Keith Hill's idea and the code):
    • <number>: show debug location in context of <number> lines;
    • + <number>: set location context preference to <number> lines ($__DebuggerStop.ShowDebugLocation). Default is 0, so that only position messages are shown; if it is positive then debug location is shown in context of <number> of lines.

Download: Utility_GPowerShellDebugger2.zip  

May 05

Debugger for Graphical PowerShell V2 CTP2


Graphical PowerShell V2 CTP2 still looks like a demo, basically speaking. Nevertheless, I find it already suitable for some tasks. Unfortunately it does not implement a few host features including default breakpoint debugger action. Breakpoints without action are simply ignored. Fortunately PowerShell provides a way to solve this. Here it is: simple and yet practically useful Add-Debugger.ps1. The archive also contains Test-Debugger.ps1 to play with and see how debugging goes (in any host, actually). Follow instructions in the script headers.

Download: Utility_GPowerShellDebugger.zip (EDIT: the next version is here...)

October 11

PowerShell.hrc for Colorer, version 1.3.4


PowerShell.hrc for Colorer, version 1.3.4

EDIT: updated link: PowerShell.hrc for V2 CTP2

What's new: REGEX and SQL schemes are supported in PowerShell literal strings.

Flexibility and power of COLORER is amazing - it not only supports tons of file formats, but also allows combining schemes together (e.g. HTML scheme supports embedded JScript, VBScript and etc. reusing their schemes). As for the PowerShell, in new version of PowerShell.hrc I tried to use REGEX and SQL schemes in literal strings.

  • REGEX scheme is used in string operand of -match, -notmatch, -replace and etc.
  • Here strings are processed with REGEX or SQL schemes starting with lines #REGEX or --SQL respectively. Note that regex normally should be created with option IgnorePatternWhitespace or it should use inline instruction (?x).


Examples of highlighting in PowerShell strings

### Regex in operands

"ab11* 'foo\'" -notmatch '^ab[0-2](\d+)\*\s+''(\w+)\\'''
'ab11* "foo\"' -match "^ab[0-2]$(2 - 1)\*\s+$($null)$null`"foo\\`""
'2007-9-23' -replace '\b(\d{2,4})-([01]?\d)-([012]?\d)\b', '$3/$2/$1'

### Regex in here strings

$re = @'
#REGEX Id and Name
\#(?<Id>\d+)           # #number
\s+                    # spaces
(?<Name>[_a-zA-Z]\w*)  # name
'@

# how to use such a pattern:
New-Object Regex $re, 'IgnorePatternWhitespace'

### SQL in here strings

@'
--SQL single quoted
SELECT Data1, COUNT(1)
FROM Table1
WHERE Data1 = '$literal'
GROUP BY Data1
'@

@"
--SQL double quoted
SELECT Data1, COUNT(1)
FROM $Table
WHERE $x = '$variable'
GROUP BY Data1
"@


March 16

Example of a PowerShell script converted to HTML with syntax highlighting


This is not a real script, it is a script used for testing of syntax description PowerShell.hrc for Colorer and covering related issues. Perhaps this HTML looks like a Christmas Tree, no problem, it is just a demo. One can configure Colorer according to his preferences. Take a look at how it handles and distinguishes expandable and not expandable string content and escaping rules, is not it a beauty?

Demo-PowerShell.hrc.ps1

##
## Demo script for testing PowerShell.hrc with Colorer
## The content is weird but compilable PowerShell code
##

{ # block begin (test 'Match pair' in Far editor)

### Numbers
.88, .88L, .88Mb, .88Lmb, .88e-88, .88kb, .88lmb # floats with start dot
88., 88.L, 88.gb, 88.lmb # floats with end dot
8e-8, 8e-8L, 8e-8lmb # floats with no dot
8.8, 8.8e-8L, 8.8e-8mb, # other floats
0xF, 0xfl, 0xFmb, 0xFlmb # hex numbers
8, 8l, 8mb, 8lmb # dec numbers
1..111 # range

### Variables
$ERROR, $true, $false # system variables
$var, ${2b`} | `{!2b} # variable with normal and complex name
@($global:var, $env:var) # array with scoped/provider variables
$e=3.14;$e='1234';$e="1234";$e=@(1..9) # variable=value

### Escaped, Expanded, Strings
`Get-`Item *
$x = $(if (Get-Item) {"xx"} else {"yy"})
& {'8;$x;,Get-Item|-eq x $($env:X; `"ps`" -eq 12kb | kb; mb, Get-Item) '' `` `" `n`t ${2b|!2b} gb}}{{ ', $e}
& {"8;$x;,Get-Item|-eq x $($env:X; `"ps`" -eq 12kb | kb; mb, Get-Item) '' `` `" `n`t ${2b|!2b} gb}}{{ ", $e}
$x = @'
$($env:var; "xxx" -like 1; x, Get-Item # not expandable here-string
) ' `" $var }} '' `' `" this is a text in both strings
`n ${2b | !2b} {{ `n "
'@ + (Get-Item L, 1L) + $var
$x = @"
$($env:var; "xxx" -like 1; x, Get-Item # expandable here-string
) ' `" $var }} '' `' `" this is a text in both strings
`n ${2b | !2b} {{ `n "
"@ + (Get-Item L, 1L) + $var

### Types and Indices: mind case, dot, {}, []
[int]; [INT[]]; [system.datetime]; [SYSTEM.DATETIME[]]
& {
    $a = [int[]] 0
    $a[$a[$a[0]]]
}

### Filters and Functions
FILTER f1([string]$s, [int[]]$ai) {} filter f2() {} $(filter f3() {}); filter f4 {filter f5() {}}
FUNCTION fn1
{
    function fn2 {}
    ; function fn3($x) {}
}

### Operators and Parameters: parameters must not be treated as keywords
1 -eq 1; 1 -and 1
fi1 -param -else -filter -function -if
fn1 -Prm1(123) -Prm2'123' -Prm3:123 -Prm4:'123'

### Redirection Operators
# uncomment the end of line to see 2 errors
1 > $null; 1 >> $null; 1 2> $null; 1 2>> $null; 1 2>&1 # 1 < $null; 1 1>&2 $null

# hashes
@{key1 = 11; key2 = 22}
@{
key1 = 11
key2 = 22
}

### Block with some resolved issues
{
    $e, '', $e
    $e, "", $e
    $e, '''', $e
    $e, " `` `a `n `Night ", $e
}

### Foreach
foreach ($x in $x) {} # is keyword
1 | foreach {} ### TODO foreach is not keyword here

### Cmdlets and not cmdlets
$x=Get-Item; $x|Get-Item # are keywords
$x=Get-Item-; $x|Get-Item- # are not keywords

### FIXED ISSUES (DON'T CHANGE!)
$x.Prop/2
"$($_.Name)=$($_.Value)"

} # block end (test 'Match pair' in Far editor)