Friday, August 31, 2012

One character drama


I work with several large brown field PowerShell projects, which were developed by different peoples, both amateurs and pro in PS. I saw different, ugly and beautiful things.

The most confusing are one char syntax, that powershell is rich of. Some of this are common, some of this are rare and even redundant.
Here is short listing:
  1. # Explicit provider  
  2. Get-Content -Path Function:prompt  
  3.   
  4. # Old good string format  
  5. 'This is my post about {1} number {0}' -F 3, 'powershell'  
  6.   
  7. # Escaping  
  8. "First line`r`nSecond one"  
  9.   
  10. # Explicit scope  
  11. $Global:test = 'GlobalTest'  
  12.   
  13. # Hashtable 
  14. $hash = @{ Name = 'Hashtable'; Description = 'Ordinary Collections.Hashtable'; }  
  15.   
  16. # Call operators  
  17. & 'Get-Process'  
  18. . 'Get-Process'  
  19.   
  20. # Use bool in switch argument  
  21. $someBool = $true  
  22. New-Item -Path Variable:SwitchTest -Value 1 -Verbose:$someBool  
  23.   
  24. # Simple scriptblock  
  25. $sb = { Get-Process }   
  26.   
  27. # Foreach-Object and Where-Object aliases  
  28. Get-Process | ?{ $_.PM -gt 1000 } | %{ $_.ProcessName }  

Explicit provider

  1. Get-Content -Path Function:prompt  
PowerShell have one approach for navigating and managing list and tree like stores, as file system, registry, certificates, even variables and loaded functions ( Get-Command -Noun Item ). They called PowerShell Providers ( Get-PSProvider ).
So you can iterate current variables and functions as well, try it:
  1. Get-ChildItem Function:*  
  2. Get-ChildItem Variable:*  
In our example we getting the body of one interesting function; prompt function called by PowerShell before user input, usually it's result looks like:
 PS C:\Windows>
You can reassign it, to show some additional or interesting information.
PS — If you like to use your own prompt function by default, you can add it's assigning to Profile.ps1 file in powershell folder, usually C:\Windows\System32\WindowsPowerShell\v1.0\.

String format

  1. 'This is my post about {1} number {0}' -F 3, 'powershell'  
This is ordinary String.Format(string pattern, params object[] args) invocation.

Escaping

  1. "First line`r`nSecond one"  
Due its command line processor roots PowerShell use ` symbol for escaping special symbols instead \. This small symbol is located on same key as ~. So you can use `r`n as new line, `t as tab symbol, `" as quote in quoted string. etc.

Explicit scopes

  1. $Global:test = 'GlobalTest'   
You will be scarred, after help About_Scopes invocation. In general, powershell scopes are like .NET scopes. They are:
  • Global is like public
  • Script is like internal
  • Private is private
  • Local is current stack level
  • Numbered scopes are from 0 (same to Local) to 1..n where each step is up to stack level
Here is simple example, which describes usage and effects of scopes:
  1. $test = 'Global Scope'  
  2. Function Foo {  
  3.     $test = 'Function Scope'  
  4.     Write-Host $Global:test # Global Scope  
  5.     Write-Host $Local:test # Function Scope  
  6.     Write-Host (Get-Variable -Name test -ValueOnly -Scope 0) # Function Scope  
  7.     Write-Host (Get-Variable -Name test -ValueOnly -Scope 1) # Global Scope   
  8. }  
  9. Foo  
As you can see, you can use $Global:test like syntax only with named scopes, $0:test will be always $null.

Hashtables

  1. $hash = @{   
  2.     Name = 'Hashtable';   
  3.     Description = 'Ordinary Collections.Hashtable';  
  4. }  
Hashtables are common for PowerShell. Because they very handy:
  1. $hash.Description # Will return 'Ordinary Collections.Hashtable'
  2. $hash.NewField = 'Some new field' 

Call operators

  1. 'Get-Process'  
  2. 'Get-Process'  
They used for invocation of string literals or variables as scripts. So you can write:
  1. $app = Read-Host "Input application name or exe path: "  
  2. $app  
So, what the difference between dot and ampersand?
When you invoke powershell script file (*.ps1) by dot, it's content added to local scope, but, script invoked by ampersand will not be added to any scope.
  1. . C:\SomeScript.ps1       # Script functions and variables will be added to current (local) scope  
  2. & C:\SomeOtherScript.ps1  # Script not added to scope at all  

Bool to switch

  1. $someBool = $true  
  2. New-Item -Path Variable:SwitchTest -Value 1 -Verbose:$someBool  
There is such thing as [switch] type of function or scriptblock argument. It used to laconic input to cmdlets:
  1. Function Write-HelloWorld {  
  2.     Param(  
  3.         [switch]$Elite  
  4.     )  
  5.     If ($Elite) {  
  6.         Write-Host 'h3110 w0r1d'  
  7.     } Else {  
  8.         Write-Host 'Hello world'  
  9.     }      
  10. }  
  11. Write-HelloWorld -Elite    # Elite-like 
  12. Write-HelloWorld           # Simple
So, when you need to use some bool value as switch, you can translate it as it shown in example.

Scriptblock

  1. $sb = { Get-Process }   
Think about script block as lambda expression, it's almost the same. You can create it, assign to variable and invoke as you did with strings . $sb
ScriptBlocks are base of PowerShell.

ForEach-Object and Where-Object

  1. Get-Process | ?{ $_.PM -gt 1000 } | %{ $_.ProcessName }  
These aliases (you can find them in Get-Alias results) are more common, than ordinary cmdlets names.

1 comment:

  1. There are actually plenty of particulars like that to take into consideration. That may be a nice level to convey up. I provide the ideas above as normal inspiration however clearly there are questions just like the one you bring up the place crucial factor can be working in trustworthy good faith. I don?t know if finest practices have emerged round issues like that, however I'm positive that your job is clearly identified as a good game. Both girls and boys feel the affect of just a moment’s pleasure, for the remainder of their lives. online casino bonus

    ReplyDelete