Poshoholic raises the question of PowerShell namespaces.
I’ve been thinking about this, too. I think it’s important for usability to keep the naming uncluttered, which is why you’ll find Get-VM as opposed to Get-VMWVM or some such in the VMworld presentation I posted last week.
That said, the potential for naming collisions isn’t something to simply dismiss and also plays into usability. I’ve been thinking along the same namespace lines as Kirk. It turns out that we already have some amount of namespace support in PowerShell as long as we’re talking about snapins. Based on that, here’s a strawman of something that might work today:
1 |
function Set-NameSpace {<br /> param($ns = $null)<br /><br /> $oldNamespace = @{}<br /> foreach ($key in $ns.Keys) {<br /> $oldMapping = Get-Command $key -CommandType Cmdlet -ErrorAction SilentlyContinue<br /> if ($oldMapping -ne $null) {<br /> $oldNamespace[$key] = $oldMapping.PSSnapin.Name + "\" + $oldMapping.Name<br /> } else {<br /> $oldNamespace[$key] = $null<br /> }<br /><br /> $newMapping = $ns[$key]<br /> if ($newMapping -eq $null) {<br /> del alias:$key<br /> } else {<br /> Set-Alias $key $ns[$key] -Scope 1<br /> }<br /> }<br /><br /> $oldNamespace<br />} |
Now imagine that each snapin defines a namespace mapping variable. To make it concrete, let’s imagine a snapin named foo that wants to use the names get-host and get-process itself. So that snapin defines its namespace mapping like this:
1 |
$fooNamespace = @{"get-host" = "foo\get-vmhost"; "get-process" = "foo\get-process"} |
With this, we can achieve the affect of a "using namespace" construct like this:
1 |
PS C:\ws\powershell> $old = set-namespace $fooNamespace<br />PS C:\ws\powershell> $old<br /><br />Name Value<br />---- -----<br />get-process Microsoft.PowerShell.Management\Get-Process<br />get-host Microsoft.PowerShell.Utility\Get-Host<br /><br /><br />PS C:\ws\powershell> get-process<br />Cannot resolve alias 'get-process' because it refers to term 'foo\get-process',<br /> which is not recognized as a cmdlet, function, operable program, or script fil<br />e. Verify the term and try again.<br />At line:1 char:11<br />+ get-process <<<<<br />PS C:\ws\powershell> get-host<br />Cannot resolve alias 'get-host' because it refers to term 'foo\get-vmhost', whi<br />ch is not recognized as a cmdlet, function, operable program, or script file. V<br />erify the term and try again.<br />At line:1 char:8<br />+ get-host <<<< |
So we see based on the errors that our invocations were in the correct "namespace" as we’re trying to invoke these cmdlets from the foo snapin. And now to stop using that namespace:
1 |
PS C:\ws\powershell> set-namespace $old | Out-Null<br />PS C:\ws\powershell> get-host<br /><br /><br />Name : ConsoleHost<br />Version : 1.0.0.0<br />InstanceId : d2f07d5a-8be5-45e8-9bf4-8e32b531f410<br />UI : System.Management.Automation.Internal.Host.InternalHostUserI<br /> nterface<br />CurrentCulture : en-US<br />CurrentUICulture : en-US<br />PrivateData : Microsoft.PowerShell.ConsoleHost+ConsoleColorProxy |
This could be made much more like a "using namespace" construct as in Kirk’s post by passing the commands to be executed as a script block and resetting the namespace after execution.
Aside from that, this is obviously incomplete, not taking into account aliases instead of or in addition to cmdlets, etc. And it doesn’t work at all for functions which don’t have a snapin to distinguish them (any thoughts on alternatives?). But maybe it’s a reasonable strawman for dealing with the problem using existing mechanisms. What do you think? Better suggestions?
Antonio Dias
Update:
I used Get-Process and Get-Host as examples because we’re all familiar with them. This obviously isn’t an encouragement to stomp on existing names, just a thought exercise around alternatives to prefixing the nouns.
I’d also want to see a way to cover functions. Namesspaces are great for developers who can use them, but from my POV as a sysadmin who won’t be creating cmdlets but who will be creating functions, this may still an important need to me. I try to use the same naming standards for my functions as shown in MSDN as devs are encouraged to use for cmdlets.
Getting back to this months later: you could actually do something similar for functions, defining them in the “namespace” as above with the cmdlets and then “attaching” them to the function: namespace. Conceptually doing something like this as part of the set-namespace described above:
PS C:\> function foo { write-host foo }
PS C:\> foo
foo
PS C:\> $foo = (dir function:\foo)
PS C:\> del function:\foo
PS C:\> foo
The term ‘foo’ is not recognized as a cmdlet, function, operable program, or sc
ript file. Verify the term and try again.
At line:1 char:3
+ foo cd function:
PS Function:\> new-item -name foo -value $foo
CommandType Name Definition
———– —- ———-
Function foo write-host foo
PS Function:\> c:
PS C:\> foo
foo
PS C:\>
On the positive side, it looks like the PowerShell team’s looking at this issue: http://imaverick.wordpress.com/2007/12/06/namepaces-in-powershell/#comment-40
Also see what Imaverick is looking at: http://imaverick.wordpress.com/2007/12/06/namepaces-in-powershell/
how can I manage to run the Roblox platform on VMware suite and can it run on 4 GB ram computer?
Get all types of Gaming modules, gaming products from the official website of Game Shopee.
The quality of information you have delivered in this blog is remarkable.
Tips, Tricks and Hacks for Everything, do check it out.