using namespace For The Win
PowerShell works smooth with .NET from day one. But calling .NET APIs was pretty verbose exercise.
To illustrate my point, let’s try to call some .NET reflection API.
Alternate string via reflection
System.String
is generally immutable in .NET:
when you call 'abc'.Substring(1)
it creates a new object to represent 'bc'
and so on.
You can modify strings with reflection.
Strings are immutable for a very good reason and you don’t usually want to do that. I peek this example just to show the technique.
This code creates System.String
object and change it’s length to access some random bytes from the heap.
Note: be careful, it can crash PowerShell process.
$s = 'abc'
$handle = [string].GetField('m_stringLength', [System.Reflection.BindingFlags]::NonPublic -bor `
[System.Reflection.BindingFlags]::Instance)
$handle.SetValue($s, 20)
$s
# Output:
# abc 櫠奙翹 洘
This repeating System.Reflection.BindingFlags
forced me break line for readability.
Write it shorter with ‘using namespace’
PowerShell v5 introduce using namespace
construct that you can add to the beginning of a script.
It allows you reference .NET types by the short name (exactly the same as C# using
).
using namespace System.Reflection
$s = 'abc'
$handle = [string].GetField('m_stringLength', [BindingFlags]::NonPublic -bor [BindingFlags]::Instance)
$handle.SetValue($s, 20)
# Output:
# abc 櫠奙翹 洘
That’s how you can save a lot of text, working with .NET APIs.
Poke module
When I talk about reflection and PowerShell, I cannot avoid mentioning poke module by @oising. It’s pure awesome: you can call and explore private members as easy as public ones. Here is how I would rewrite the same code with poke
Import-Module poke
$s = 'abc'
$pokedS = $s | peek
$pokedS.m_stringLength = 20
$s
# Output:
# abc 櫠奙翹 洘