10

Thought about it while answering this question.

How can you avoid the need to fully qualify every single type in a namespace?

It's really, really tedious to write System.Security.Cryptography.X509Certificates.X509Store instead of X509Store, or [System.Security.Cryptography.X509Certificates.StoreName]::My instead of [StoreName]::My.

In C# you have using directives... what about Powershell?


EDIT 1 - This works for types:

$ns = "System.Security.Cryptography.X509Certificates"
$store = New-Object "$ns.X509Store"(StoreName,StoreLocation)

New-Object takes a string literal as the type definition, so it can be built programmatically.


EDIT 2 - This works for enumeration members used as parametes:

$store = New-Object "$ns.X509Store"("My","LocalMachine")

Where "My" is [System.Security.Cryptography.X509Certificates.StoreName]::My and "LocalMachine" is [System.Security.Cryptography.X509Certificates.StoreLocation]::LocalMachine.
Literal names are automatically converted to enumeration members, if placed where an enumeration member is expected.

Massimo
  • 68,714
  • 56
  • 196
  • 319

3 Answers3

11

I know, it's a little bit late, but PowerShell v5 adds tons of cool language stuff. One of it is 'using namespace'.

PS> using namespace System.Security.Cryptography.X509Certificates; [X509Store]


IsPublic IsSerial Name                                     BaseType                                     
-------- -------- ----                                     --------                                     
True     False    X509Store                                System.Object                                
xvorsx
  • 226
  • 2
  • 4
6

For enumerations you don't have to specify the whole type name. For example:

You can do this:

New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext([System.DirectoryServices.ActiveDirectory.DirectoryContextType]::Domain)

or the much more simple version:

New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Domain')

You can use strings to identify the enumerations you want to use without having to use the fully decorated name. PowerShell handles the typecasting for you to convert the strings to the enumeration values. Using the specific example you showed above, that means you can do this:

[System.Security.Cryptography.X509Certificates.OpenFlags]'ReadWrite'

And Powershell will properly convert it (so passing 'ReadWrite' to a parameter that takes an OpenFlags enumeration value will work just fine). If you want to pass multiple values, you can do it like this:

[System.Security.Cryptography.X509Certificates.OpenFlags]@('ReadWrite','IncludeArchived')

Note that I'm prefixing these commands with the type name, but if you were passing them to a typed parameter you would simply leave that out.

That should get you one step closer to being able to write scripts that work with a specific namespace without having to decorate all of the names.

Falcon Momot
  • 24,975
  • 13
  • 61
  • 92
Poshoholic
  • 399
  • 1
  • 4
  • This works great, thanks. I just hope to never find an overloaded method that can take as a parameter two different enumerations that have a member with the same name :-) – Massimo Oct 15 '09 at 19:23
  • Accepting this one because the tip is useful, but the issue is still quite far from resolved... :-/ – Massimo Oct 19 '09 at 06:35
0

The right way?

$_m = [math]
$_m::sin((45*($_m::pi/180))) 

And this seems to work:

[Reflection.Assembly]::Load("System.Security, Version=2.0.0.0, Culture=Neutral, PublicKeyToken=b03f5f7f11d50a3a")

$stoopidnamespace = 'System.Security.Cryptography.X509Certificates.X509Store'
New-Object $stoopidnamespace($null)

But it's ugly when you do this:

$stoopidnamespace = 'System.Security.Cryptography.X509Certificates'
New-Object $stoopidnamespace'.X509Store'($null)
Joseph Kern
  • 9,809
  • 3
  • 31
  • 55