spacer PowerShell Code Repository

Reflection Module 4.1 by Joel Bennett 14 months ago (modification of post by Joel Bennett view diff)
View followups from Joel Bennett | diff | embed code: <script type="text/javascript" src="/img/spacer.gif"> download | new post

Helpers for working with .Net classes: Get-Constructor, Get-Assembly, Add-Assembly, Get-Type

Now includes the New-ConstructorFunction (formerly in PowerBoots) which depends on the Autoload Module …

In this version I fixed a minor problem with PowerShell 3 CTP1

  1. #requires -version 2.0
  2. # ALSO REQUIRES Autoload for some functionality (Latest version: poshcode.org/3173)
  3. # You should create a Reflection.psd1 with the contents:
  4. #    @{ ModuleToProcess="Reflection.psm1"; RequiredModules = @("Autoload"); GUID="64b5f609-970f-4e65-b02f-93ccf3e60cbb"; ModuleVersion="4.1.0.0" }
  5. #History:
  6. # 1.0  - First public release (March 19, 2010)
  7. # 2.0  - Private Build
  8. #      - Included the Accelerator function inline
  9. #      - Added a few default aliases
  10. # 3.0  - September 3, 2010
  11. #      - Included the New-ConstructorFunction feature (ripped from PowerBoots to serve a more generic and powerful purpose!)
  12. #      - New-ConstructorFunction and Import-ConstructorFunctions depend on the Autoload Module: poshcode.org/2312
  13. # 3.5  - January 28, 2011
  14. #      - Fixed several bugs in Add-Assembly, Get-Assembly, Get-MemberSignature
  15. #      - Fixed alias exporting so aliases will show up now
  16. #      - Added New-ModuleManifestFromSnapin to create module manifests from snapin assemblies
  17. # 3.6  - January 28, 2011
  18. #      - Added *basic* support for CustomPSSnapin to New-ModuleManifestFromSnapin
  19. # 3.7  - February 1, 2001 - NOT RELEASED
  20. #      - Added [TransformAttribute] type
  21. # 3.8  - May 4, 2011 - NOT RELEASED
  22. #      - Huge rewrite of Invoke-Generic (also published separately: poshcode.org/2649)
  23. # 3.9  - May 25, 2011 - NOT RELEASED
  24. #      - Added "Interface" parameter to Get-Type
  25. # 4.0  - Sept 27, 2011
  26. #      - Fix conflicts with PowerShell 3
  27. # 4.1  - Oct 27, 2011
  28. #      - Fix PowerShell 3 changes so they don't break PowerShell 2 (huy!)
  29.  
  30. Add-Type -TypeDefinition @"
  31. using System;
  32. using System.ComponentModel;
  33. using System.Management.Automation;
  34. using System.Collections.ObjectModel;
  35.  
  36. [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
  37. public class TransformAttribute : ArgumentTransformationAttribute {
  38.   private ScriptBlock _scriptblock;
  39.   private string _noOutputMessage = "Transform Script had no output.";
  40.  
  41.   public override string ToString() {
  42.      return string.Format("[Transform(Script='{{{0}}}')]", Script);
  43.   }
  44.  
  45.   public override Object Transform( EngineIntrinsics engine, Object inputData) {
  46.      try {
  47.         Collection<PSObject> output =
  48.            engine.InvokeCommand.InvokeScript( engine.SessionState, Script, inputData );
  49.        
  50.         if(output.Count > 1) {
  51.            Object[] transformed = new Object[output.Count];
  52.            for(int i =0; i < output.Count;i++) {
  53.               transformed[i] = output[i].BaseObject;
  54.            }
  55.            return transformed;
  56.         } else if(output.Count == 1) {
  57.            return output[0].BaseObject;
  58.         } else {
  59.            throw new ArgumentTransformationMetadataException(NoOutputMessage);
  60.         }
  61.      } catch (ArgumentTransformationMetadataException) {
  62.         throw;
  63.      } catch (Exception e) {
  64.         throw new ArgumentTransformationMetadataException(string.Format("Transform Script threw an exception ('{0}'). See `$Error[0].Exception.InnerException.InnerException for more details.",e.Message), e);
  65.      }
  66.   }
  67.  
  68.   public TransformAttribute() {
  69.      this.Script = ScriptBlock.Create("{`$args}");
  70.   }
  71.  
  72.   public TransformAttribute( ScriptBlock Script ) {
  73.      this.Script = Script;
  74.   }
  75.  
  76.   public ScriptBlock Script {
  77.      get { return _scriptblock; }
  78.      set { _scriptblock = value; }
  79.   }
  80.  
  81.   public string NoOutputMessage {
  82.      get { return _noOutputMessage; }
  83.      set { _noOutputMessage = value; }
  84.   }  
  85. }
  86. "@
  87.  
  88.  
  89.  
  90. function Get-Type {
  91.    <#
  92.    .Synopsis
  93.       Gets the types that are currenty loaded in .NET, or gets information about a specific type
  94.    .Description
  95.       Gets information about one or more loaded types, or gets the possible values for an enumerated type or value.
  96.    .Parameter Assembly
  97.       The Assemblies to search for types.
  98.       Can be an actual Assembly object or a regex to pass to Get-Assembly.
  99.    .Parameter TypeName
  100.       The type name(s) to search for (wildcard patterns allowed).
  101.    .Parameter BaseType
  102.       A Base type they should derive from (wildcard patterns allowed).
  103.    .Parameter Interface
  104.       An interface they should implement (wildcard patterns allowed).
  105.    .Parameter Enum
  106.       An enumeration to list all of enumeration values for
  107.    .Parameter Namespace
  108.       A namespace to restrict where we selsect types from (wildcard patterns allowed).
  109.    .Parameter Force
  110.       Causes Private types to be included
  111.    .Example
  112.       Get-Type
  113.        
  114.       Gets all loaded types (takes a VERY long time to print out)
  115.    .Example
  116.       Get-Type -Assembly ([PSObject].Assembly)
  117.        
  118.       Gets types from System.Management.Automation
  119.    .Example
  120.       [Threading.Thread]::CurrentThread.ApartmentState | Get-Type
  121.        
  122.       Gets all of the possible values for the ApartmentState property
  123.    .Example
  124.       [Threading.ApartmentState] | Get-Type
  125.        
  126.       Gets all of the possible values for an apartmentstate
  127.    #>
  128.    [CmdletBinding(DefaultParameterSetName="Assembly")]  
  129.    param(
  130.    # The assembly to collect types from
  131.    [Parameter(ValueFromPipeline=$true)]
  132.    [PsObject[]]$Assembly
  133. ,
  134.    # The type names to return from
  135.    [Parameter(Mandatory=$false,Position=0)]
  136.    [String[]]$TypeName
  137. ,
  138.    # The type names to return from
  139.    [Parameter(Mandatory=$false)]
  140.    [String[]]$Namespace
  141. ,
  142.    # A Base Type they should derive from
  143.    [Parameter(Mandatory=$false)]
  144.    [String[]]$BaseType
  145. ,
  146.    # An Interface they should implement
  147.    [Parameter(Mandatory=$false)]
  148.    [String[]]$Interface
  149. ,
  150.    # The enumerated value to get all of the possibilties of
  151.    [Parameter(ParameterSetName="Enum")]
  152.    [PSObject]$Enum
  153. ,
  154.    [Parameter()][Alias("Private","ShowPrivate")]
  155.    [Switch]$Force
  156.    )
  157.  
  158.    process {
  159.       if($psCmdlet.ParameterSetName -eq 'Enum') {
  160.          if($Enum -is [Enum]) {
  161.             [Enum]::GetValues($enum.GetType())
  162.          } elseif($Enum -is [Type] -and $Enum.IsEnum) {
  163.             [Enum]::GetValues($enum)
  164.          } else {
  165.             throw "Specified Enum is neither an enum value nor an enumerable type"
  166.          }
  167.       }
  168.       else {
  169.          if($Assembly -as [Reflection.Assembly[]]) {
  170.             ## This is what we expected, move along
  171.          } elseif($Assembly -as [String[]]) {
  172.             $Assembly = Get-Assembly $Assembly
  173.          } elseif(!$Assembly) {
  174.             $Assembly = [AppDomain]::CurrentDomain.GetAssemblies()
  175.          }
  176.  
  177.          :asm foreach ($asm in $assembly) {
  178.             Write-Verbose "Testing Types from Assembly: $($asm.Location)"
  179.             if ($asm) {
  180.                trap {
  181.                   if( $_.Exception.LoaderExceptions[0] -is [System.IO.FileNotFoundException] ) {
  182.                      $PSCmdlet.WriteWarning( "Unable to load some types from $($asm.Location), required assemblies were not found. Use -Debug to see more detail")
  183.                      continue asm
  184.                   }
  185.                   Write-Error "Unable to load some types from $($asm.Location). Try with -Debug to see more detail"
  186.                   Write-Debug $( $_.Exception.LoaderExceptions | Out-String )
  187.                   continue asm
  188.                }
  189.                $asm.GetTypes() | Where {
  190.                   ( $Force -or $_.IsPublic ) -AND
  191.                   ( !$Namespace -or $( foreach($n in $Namespace) { $_.Namespace -like $n  } ) ) -AND
  192.                   ( !$TypeName -or $( foreach($n in $TypeName) { $_.Name -like $n -or $_.FullName -like $n } ) -contains $True ) -AND
  193.                   ( !$BaseType -or $( foreach($n in $BaseType) { $_.BaseType -like $n } ) -contains $True ) -AND
  194.                   ( !$Interface -or @( foreach($n in $Interface) { $_.GetInterfaces() -like $n } ).Count -gt 0 )
  195.                }
  196.             }
  197.          }
  198.       }
  199.    }
  200. }
  201.  
  202. function Add-Assembly {
  203. #.Synopsis
  204. #  Load assemblies
  205. #.Description
  206. #  Load assemblies from a folder
  207. #.Parameter Path
  208. #  Specifies a path to one or more locations. Wildcards are permitted. The default location is the current directory (.).
  209. #.Parameter Passthru
  210. #  Returns System.Runtime objects that represent the types that were added. By default, this cmdlet does not generate any output.
  211. #  Aliased to -Types
  212. #.Parameter Recurse
  213. #  Gets the items in the specified locations and in all child items of the locations.
  214. #
  215. #  Recurse works only when the path points to a container that has child items, such as C:\Windows or C:\Windows\*, and not when it points to items that do not have child items, such as C:\Windows\*.dll
  216. [CmdletBinding()]
  217. param(
  218.    [Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true, Position=0)]
  219.    [Alias("PSPath")]
  220.    [string[]]$Path = "."
  221. ,
  222.    [Alias("Types")]
  223.    [Switch]$Passthru
  224. ,
  225.    [Switch]$Recurse
  226. )
  227. process {
  228.    foreach($file in Get-ChildItem $Path -Filter *.dll -Recurse:$Recurse) {
  229.       Add-Type -Path $file.FullName -Passthru:$Passthru | Where { $_.IsPublic }
  230.    }
  231. }
  232. }
  233.  
  234. function Get-Assembly {
  235. <#
  236. .Synopsis
  237.    Get a list of assemblies available in the runspace
  238. .Description
  239.    Returns AssemblyInfo for all the assemblies available in the current AppDomain, optionally filtered by partial name match
  240. .Parameter Name
  241.    A regex to filter the returned assemblies. This is matched against the .FullName or Location (path) of the assembly.
  242. #>
  243. [CmdletBinding()]
  244. param(
  245.    [Parameter(ValueFromPipeline=$true, Position=0)]
  246.    [string[]]$Name = ''
  247. )
  248. process {
  249.    [appdomain]::CurrentDomain.GetAssemblies() | Where {
  250.       $Assembly = $_
  251.       if($Name){
  252.          $(
  253.             foreach($n in $Name){
  254.                if(Resolve-Path $n -ErrorAction 0) {
  255.                   $n = [Regex]::Escape( (Resolve-Path $n).Path )
  256.                }
  257.                $Assembly.FullName -match $n -or $Assembly.Location -match $n -or ($Assembly.Location -and (Split-Path $Assembly.Location) -match $n)
  258.             }
  259.          ) -contains $True
  260.       } else { $true }
  261.    }
  262.      
  263. }
  264. }
  265.  
  266.  
  267. function Update-PSBoundParameters {
gipoco.com is neither affiliated with the authors of this page nor responsible for its contents. This is a safe-cache copy of the original web site.