-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
22 changed files
with
1,516 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
function Expand-PSOneToken | ||
{ | ||
<# | ||
.SYNOPSIS | ||
Expands all nested token from a token of type "StringExpandable" | ||
.DESCRIPTION | ||
Recursively emits all tokens embedded in a token of type "StringExpandable" | ||
The original token is also emitted. | ||
.EXAMPLE | ||
Get-PSOneToken -Code '"Hello $host"' -TokenKind StringExpandable | Expand-PSOneToken | ||
Emits all tokens, including the embedded (nested) tokens | ||
.LINK | ||
https://powershell.one/powershell-internals/parsing-and-tokenization/advanced-tokenizer | ||
https://github.com/TobiasPSP/Modules.PSOneTools/blob/master/PSOneTools/1.4/Expand-PSOneToken.ps1 | ||
#> | ||
|
||
# use the most specific parameter as default: | ||
[CmdletBinding(DefaultParameterSetName='ExpandableString')] | ||
param | ||
( | ||
# binds a token of type "StringExpandableToken" | ||
[Parameter(Mandatory,ParameterSetName='ExpandableString', | ||
Position=0,ValueFromPipeline)] | ||
[Management.Automation.Language.StringExpandableToken] | ||
$StringExpandable, | ||
|
||
# binds all tokens | ||
[Parameter(Mandatory,ParameterSetName='Token', | ||
Position=0,ValueFromPipeline)] | ||
[Management.Automation.Language.Token] | ||
$Token | ||
) | ||
|
||
process | ||
{ | ||
switch($PSCmdlet.ParameterSetName) | ||
{ | ||
# recursively expand token of type "StringExpandable" | ||
'ExpandableString' { | ||
$StringExpandable | ||
$StringExpandable.NestedTokens | | ||
Where-Object { $_ } | | ||
Expand-PSOneToken | ||
} | ||
# return regular token as-is: | ||
'Token' { $Token } | ||
# should never occur: | ||
default { Write-Warning $_ } | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
function Foreach-ObjectFast | ||
{ | ||
<# | ||
.SYNOPSIS | ||
Faster Foreach-Object | ||
.DESCRIPTION | ||
Foreach-ObjectFast can replace the built-in Foreach-Object and improves pipeline speed considerably. | ||
Foreach-ObjectFast supports only the most commonly used parameters -Begin, -Process, and -End, so you can replace | ||
1..100 | Foreach-Object { 'Server{0:d3}' -f $_ } | ||
with | ||
1..100 | Foreach-ObjectFast { 'Server{0:d3}' -f $_ } | ||
but you cannot currently replace instances of Foreach-Object that uses the less commonly used parameters, | ||
like -RemainingScripts, -MemberNames, and -ArgumentList | ||
Foreach-ObjectFast has a performance benefit per iteration, so the more objects | ||
you send through the pipeline, the more significant performace benefits you will see. | ||
Foreach-ObjectFast is using a steppable pipeline internally which performs better. | ||
However because of this, the debugging experience will be different, and internal | ||
variables such as $MyInvocation may yield different results. For most every-day tasks, | ||
these changes are not important. | ||
A complete explanation of what Where-ObjectFast does can be found here: | ||
https://powershell.one/tricks/performance/pipeline | ||
.EXAMPLE | ||
$stopwatch = [System.Diagnostics.Stopwatch]::StartNew() | ||
$result = 1..1000000 | Foreach-ObjectFast -Process { | ||
"I am at $_" | ||
} | ||
$report = '{0} elements in {1:n2} seconds' | ||
$report -f $result.Count, $stopwatch.Elapsed.TotalSeconds | ||
Demos the speed improvements. Run this script to see how well it performs, | ||
then replace Foreach-ObjectFast with the default Foreach-Object, and check out | ||
the performace difference. $result is the same in both cases. | ||
.LINK | ||
https://powershell.one/tricks/performance/pipeline | ||
https://github.com/TobiasPSP/Modules.PSOneTools/blob/master/PSOneTools/1.2/Foreach-ObjectFast.ps1 | ||
#> | ||
|
||
param | ||
( | ||
# executes for each pipeline element | ||
[ScriptBlock] | ||
$Process, | ||
|
||
# executes once before the pipeline is started. | ||
# can be used for initialization routines | ||
[ScriptBlock] | ||
$Begin, | ||
|
||
# executes once after all pipeline elements have been processed | ||
# can be used to do cleanup work | ||
[ScriptBlock] | ||
$End | ||
) | ||
|
||
begin | ||
{ | ||
# construct a hard-coded anonymous simple function from | ||
# the submitted scriptblocks: | ||
$code = @" | ||
& { | ||
begin | ||
{ | ||
$Begin | ||
} | ||
process | ||
{ | ||
$Process | ||
} | ||
end | ||
{ | ||
$End | ||
} | ||
} | ||
"@ | ||
# turn code into a scriptblock and invoke it | ||
# via a steppable pipeline so we can feed in data | ||
# as it comes in via the pipeline: | ||
$pip = [ScriptBlock]::Create($code).GetSteppablePipeline($myInvocation.CommandOrigin) | ||
$pip.Begin($true) | ||
} | ||
process | ||
{ | ||
# forward incoming pipeline data to the custom scriptblock: | ||
$pip.Process($_) | ||
} | ||
end | ||
{ | ||
$pip.End() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
|
||
|
||
function Get-PSOneToken | ||
{ | ||
<# | ||
.SYNOPSIS | ||
Parses a PowerShell Script (*.ps1, *.psm1, *.psd1) and returns the token | ||
.DESCRIPTION | ||
Invokes the advanced PowerShell Parser and returns tokens and syntax errors | ||
.EXAMPLE | ||
Get-PSOneToken -Path c:\test.ps1 | ||
Parses the content of c:\test.ps1 and returns tokens and syntax errors | ||
.EXAMPLE | ||
Get-ChildItem -Path $home -Recurse -Include *.ps1,*.psm1,*.psd1 -File | | ||
Get-PSOneToken | | ||
Out-GridView | ||
parses all PowerShell files found anywhere in your user profile | ||
.EXAMPLE | ||
Get-ChildItem -Path $home -Recurse -Include *.ps1,*.psm1,*.psd1 -File | | ||
Get-PSOneToken | | ||
Where-Object Errors | ||
parses all PowerShell files found anywhere in your user profile | ||
and returns only those files that contain syntax errors | ||
.LINK | ||
https://powershell.one/powershell-internals/parsing-and-tokenization/advanced-tokenizer | ||
https://github.com/TobiasPSP/Modules.PSOneTools/blob/master/PSOneTools/1.4/Get-PSOneToken.ps1 | ||
#> | ||
|
||
[CmdletBinding(DefaultParameterSetName='Path')] | ||
param | ||
( | ||
# Path to PowerShell script file | ||
# can be a string or any object that has a "Path" | ||
# or "FullName" property: | ||
[String] | ||
[Parameter(Mandatory,ValueFromPipeline,ParameterSetName='Path')] | ||
[Alias('FullName')] | ||
$Path, | ||
|
||
# PowerShell Code as ScriptBlock | ||
[ScriptBlock] | ||
[Parameter(Mandatory,ValueFromPipeline,ParameterSetName='ScriptBlock')] | ||
$ScriptBlock, | ||
|
||
|
||
# PowerShell Code as String | ||
[String] | ||
[Parameter(Mandatory, ValueFromPipeline,ParameterSetName='Code')] | ||
$Code, | ||
|
||
# the kind of token requested. If neither TokenKind nor TokenFlag is requested, | ||
# a full tokenization occurs | ||
[System.Management.Automation.Language.TokenKind[]] | ||
$TokenKind = $null, | ||
|
||
# the kind of token requested. If neither TokenKind nor TokenFlag is requested, | ||
# a full tokenization occurs | ||
[System.Management.Automation.Language.TokenFlags[]] | ||
$TokenFlag = $null, | ||
|
||
# include nested token that are contained inside | ||
# ExpandableString tokens | ||
[Switch] | ||
$IncludeNestedToken | ||
|
||
) | ||
|
||
begin | ||
{ | ||
# create variables to receive tokens and syntax errors: | ||
$errors = | ||
$tokens = $null | ||
|
||
# return tokens only? | ||
# when the user submits either one of these parameters, the return value should | ||
# be tokens of these kinds: | ||
$returnTokens = ($PSBoundParameters.ContainsKey('TokenKind')) -or | ||
($PSBoundParameters.ContainsKey('TokenFlag')) | ||
} | ||
process | ||
{ | ||
# if a scriptblock was submitted, convert it to string | ||
if ($PSCmdlet.ParameterSetName -eq 'ScriptBlock') | ||
{ | ||
$Code = $ScriptBlock.ToString() | ||
} | ||
|
||
# if a path was submitted, read code from file, | ||
if ($PSCmdlet.ParameterSetName -eq 'Path') | ||
{ | ||
$code = Get-Content -Path $Path -Raw -Encoding Default | ||
$name = Split-Path -Path $Path -Leaf | ||
$filepath = $Path | ||
|
||
# parse the file: | ||
$ast = [System.Management.Automation.Language.Parser]::ParseFile( | ||
$Path, | ||
[ref] $tokens, | ||
[ref]$errors) | ||
} | ||
else | ||
{ | ||
# else the code is already present in $Code | ||
$name = $Code | ||
$filepath = '' | ||
|
||
# parse the string code: | ||
$ast = [System.Management.Automation.Language.Parser]::ParseInput( | ||
$Code, | ||
[ref] $tokens, | ||
[ref]$errors) | ||
} | ||
|
||
if ($IncludeNestedToken) | ||
{ | ||
# "unwrap" nested token | ||
$tokens = $tokens | Expand-PSOneToken | ||
} | ||
|
||
if ($returnTokens) | ||
{ | ||
# filter token and use fast scriptblock filtering instead of Where-Object: | ||
$tokens | | ||
& { process { if ($TokenKind -eq $null -or | ||
$TokenKind -contains $_.Kind) | ||
{ $_ } | ||
}} | | ||
& { process { | ||
$token = $_ | ||
if ($TokenFlag -eq $null) { $token } | ||
else { | ||
$TokenFlag | | ||
Foreach-Object { | ||
if ($token.TokenFlags.HasFlag($_)) | ||
{ $token } } | | ||
Select-Object -First 1 | ||
} | ||
} | ||
} | ||
|
||
} | ||
else | ||
{ | ||
# return the results as a custom object | ||
[PSCustomObject]@{ | ||
Name = $name | ||
Path = $filepath | ||
Tokens = $tokens | ||
# "move" nested "Extent" up one level | ||
# so all important properties are shown immediately | ||
Errors = $errors | | ||
Select-Object -Property Message, | ||
IncompleteInput, | ||
ErrorId -ExpandProperty Extent | ||
Ast = $ast | ||
} | ||
} | ||
} | ||
} |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
|
||
function Test-PSOnePing | ||
{ | ||
<# | ||
.SYNOPSIS | ||
Sends a ping (ICMP) to a computer | ||
.DESCRIPTION | ||
Sends a ping (ICMP) to a computer | ||
.EXAMPLE | ||
Test-PSOnePing -ComputerName 127.0.0.1, microsoft.com, powershell.one -Timeout 2000 | ||
Pings three computers with a maximum timeout of 2000 milliseconds | ||
.EXAMPLE | ||
'127.0.0.1', 'microsoft.com', 'powershell.one' | Test-PSOnePing -Timeout 2000 | ||
Pings three computers with a maximum timeout of 2000 milliseconds | ||
.EXAMPLE | ||
Get-ADComputer -Filter * | Select-Object -ExpandProperty Name | Test-PSOnePing -Timeout 2000 | ||
Pings all computers received from Get-ADComputer with a maximum timeout of 2000 milliseconds | ||
Module "ActiveDirectory" required for Get-ADComputer | ||
.LINK | ||
https://powershell.one/tricks/network/ping | ||
#> | ||
|
||
|
||
param | ||
( | ||
# Computername or IP address to ping | ||
[Parameter(Mandatory,ValueFromPipeline)] | ||
[string[]] | ||
$ComputerName, | ||
|
||
# Timeout in milliseconds | ||
[int] | ||
[ValidateRange(100,50000)] | ||
$Timeout = 2000 | ||
) | ||
|
||
begin | ||
{ | ||
$Online = @{ | ||
Name = 'Online' | ||
Expression = { $_.Status -eq 'Success' } | ||
} | ||
$obj = New-Object System.Net.NetworkInformation.Ping | ||
} | ||
|
||
process | ||
{ | ||
$ComputerName | | ||
ForEach-Object { | ||
$obj.Send($_, $timeout) | | ||
Select-Object -Property $Online, Status, Address | | ||
Add-Member -MemberType NoteProperty -Name Name -Value $_ -PassThru | ||
} | ||
} | ||
} |
Oops, something went wrong.