PoshCode Logo PowerShell Code Repository

Reflection Module 4.1 by Joel Bennett 32 months ago (modification of post by Joel Bennett view diff)
View followups from Joel Bennett | diff | embed code: <script type="text/javascript" src="http://PoshCode.org/embed/3174"></script>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: http://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: http://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: http://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 {
  268. #.Synopsis
  269. #  Ensure a parameter value is set
  270. #.Description
  271. #  Update-PSBoundParameters takes the name of a parameter, a default value, and optionally a min and max value, and ensures that PSBoundParameters has a value for it.
  272. #.Parameter Name
  273. #  The name (key) of the parameter you want to set in PSBoundParameters
  274. #.Parameter Default
  275. #  A Default value for the parameter, in case it's not already set
  276. #.Parameter Min
  277. #  The Minimum allowed value for the parameter
  278. #.Parameter Max
  279. #  The Maximum allowed value for the parameter
  280. #.Parameter PSBoundParameters
  281. #  The PSBoundParameters you want to affect (this picks the local PSBoundParameters object, so you shouldn't have to set it)
  282. Param(
  283.    [Parameter(Mandatory=$true,  Position=0)]
  284.    [String]$Name
  285. ,
  286.    [Parameter(Mandatory=$false, Position=1)]
  287.    $Default
  288. ,
  289.    [Parameter()]
  290.    $Min
  291. ,
  292.    [Parameter()]
  293.    $Max
  294. ,
  295.    [Parameter(Mandatory=$true, Position=99)]
  296.    $PSBoundParameters=$PSBoundParameters
  297. )
  298. end {
  299.    $outBuffer = $null
  300.    ## If it's not set, and you passed a default, we set it to the default
  301.    if($Default) {
  302.       if (!$PSBoundParameters.TryGetValue($Name, [ref]$outBuffer))
  303.       {
  304.          $PSBoundParameters[$Name] = $Default
  305.       }
  306.    }
  307.    ## If you passed a $max, and it's set greater than $max, we set it to $max
  308.    if($Max) {
  309.       if ($PSBoundParameters.TryGetValue($Name, [ref]$outBuffer) -and $outBuffer -gt $Max)
  310.       {
  311.          $PSBoundParameters[$Name] = $Max
  312.       }
  313.    }
  314.    ## If you passed a $min, and it's set less than $min, we set it to $min
  315.    if($Min) {
  316.       if ($PSBoundParameters.TryGetValue($Name, [ref]$outBuffer) -and $outBuffer -lt $Min)
  317.       {
  318.          $PSBoundParameters[$Name] = $Min
  319.       }
  320.    }
  321.    $PSBoundParameters
  322. }
  323. }
  324.  
  325.  
  326. function Get-Constructor {
  327. <#
  328. .Synopsis
  329.    Returns RuntimeConstructorInfo for the (public) constructor methods of the specified Type.
  330. .Description
  331.    Get the RuntimeConstructorInfo for a type and add members "Syntax," "SimpleSyntax," and "Definition" to each one containing the syntax information that can use to call that constructor.
  332. .Parameter Type
  333.    The type to get the constructor for
  334. .Parameter Force
  335.    Force inclusion of Private and Static constructors which are hidden by default.
  336. .Parameter NoWarn
  337.    Serves as the replacement for the broken -WarningAction. If specified, no warnings will be written for types without public constructors.
  338. .Example
  339.    Get-Constructor System.IO.FileInfo
  340.    
  341.    Description
  342.    -----------
  343.    Gets all the information about the single constructor for a FileInfo object.
  344. .Example
  345.    Get-Type System.IO.*info mscorlib | Get-Constructor -NoWarn | Select Syntax
  346.    
  347.    Description
  348.    -----------
  349.    Displays the constructor syntax for all of the *Info objects in the System.IO namespace.
  350.    Using -NoWarn supresses the warning about System.IO.FileSystemInfo not having constructors.
  351.  
  352. .Example
  353.    $path = $pwd
  354.    $driveName = $pwd.Drive
  355.    $fileName = "$Profile"
  356.    Get-Type System.IO.*info mscorlib | Get-Constructor -NoWarn | ForEach-Object { Invoke-Expression $_.Syntax }
  357.    
  358.    Description
  359.    -----------
  360.    Finds and invokes the constructors for DirectoryInfo, DriveInfo, and FileInfo.
  361.    Note that we pre-set the parameters for the constructors, otherwise they would fail with null arguments, so this example isn't really very practical.
  362.  
  363.  
  364. #>
  365. [CmdletBinding()]
  366. param(
  367.    [Parameter(Mandatory=$true, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$true, Position=0)]
  368.    [Alias("ParameterType")]
  369.    [Type]$Type
  370. ,  [Switch]$Force
  371. ,  [Switch]$NoWarn
  372. )
  373.    process {
  374.       $type.GetConstructors() | Where-Object { $Force -or $_.IsPublic -and -not $_.IsStatic } -OutVariable ctor | Select *,
  375.          @{ name = "TypeName"; expression = { $_.ReflectedType.FullName } },
  376.          @{ name = "Definition";
  377.             expression = {Get-MemberSignature $_ -Simple}
  378.          },
  379.          @{ name = "Syntax";
  380.             expression = {Get-MemberSignature $_ -Simple}
  381.          },
  382.          @{ name = "SafeSyntax";
  383.             expression = {Get-MemberSignature $_}
  384.          }
  385.       if(!$ctor -and !$NoWarn) { Write-Warning "There are no public constructors for $($type.FullName)" }
  386.    }
  387. }
  388.  
  389. function Get-Method {
  390. <#
  391. .Synopsis
  392.    Returns MethodInfo for the (public) methods of the specified Type.
  393. .Description
  394.    Get the MethodInfo for a type and add members "Syntax," "SimpleSyntax," and "Definition" to each one containing the syntax information that can use to call that method.
  395. .Parameter Type
  396.    The type to get methods on
  397. .Parameter Name
  398.    The name(s) of the method(s) you want to retrieve (Accepts Wildcard Patterns)
  399. .Parameter Force
  400.    Force inclusion of Private methods and property accessors which are hidden by default.
  401.  
  402. #>
  403. [CmdletBinding(DefaultParameterSetName="Type")]
  404. param(
  405.    [Parameter(ParameterSetName="Type", Mandatory=$true, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$true, Position=0)]
  406.    [Type]$Type
  407. ,
  408.    [Parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$true, Position=1)]
  409.    [String[]]$Name ="*"
  410. ,  [Switch]$Definition
  411. ,  [Switch]$Force
  412. )
  413.    process {
  414.       foreach($method in
  415.          $type.GetMethods() + $type.GetConstructors() | Where-Object { $Force -or $_.IsPublic } |
  416.          # Hide the Property accessor methods
  417.          Where-Object { $Force -or !$_.IsSpecialName -or $_.Name -notmatch "^get_|^set_" } |
  418.          Where-Object { $( foreach($n in $Name) { $_.Name -like $n } ) -contains $True } )
  419.       {
  420.          $method |
  421.          Add-Member NoteProperty TypeName   -Value $($method.ReflectedType.FullName     ) -Passthru |
  422.          Add-Member NoteProperty Definition -Value $(Get-MemberSignature $method -Simple) -Passthru |
  423.          Add-Member AliasProperty Syntax Definition -Passthru |
  424.         #Add-Member NoteProperty Syntax     -Value $(Get-MemberSignature $method -Simple) -Passthru |
  425.          Add-Member NoteProperty SafeSyntax -Value $(Get-MemberSignature $method        ) -Passthru
  426.       }
  427.    }
  428. }
  429.  
  430. function Get-MemberSignature {
  431. [CmdletBinding()]
  432. param(
  433.    [Parameter(ValueFromPipeline=$true,Mandatory=$true)]
  434.    [System.Reflection.MethodBase]$MethodBase,
  435.    [Switch]$Simple
  436. )
  437. process {
  438.    $parameters = $(
  439.       foreach($param in $MethodBase.GetParameters()) {
  440.          # Write-Host $param.ParameterType.FullName.TrimEnd('&'), $param.Name -fore cyan
  441.                  Write-Verbose "$($param.ParameterType.UnderlyingSystemType.FullName) - $($param.ParameterType)"
  442.      
  443.          if($param.ParameterType.Name.EndsWith('&')) { $ref = '[ref]' } else { $ref = '' }
  444.          if($param.ParameterType.IsArray) { $array = ',' } else { $array = '' }
  445.          if($Simple) {
  446.             '{0} {1}' -f $param.ParameterType.ToString(), $param.Name
  447.          } else {
  448.             '{0}({1}[{2}]${3})' -f $ref, $array, $param.ParameterType.ToString().TrimEnd('&'), $param.Name
  449.          }
  450.       }
  451.    )
  452.    
  453.    if($MethodBase.IsConstructor) {
  454.       "New-Object $($MethodBase.ReflectedType.FullName) $($parameters -join ', ')"
  455.    } elseif($Simple) {
  456.       "$($MethodBase.ReturnType.FullName) $($MethodBase.Name)($($parameters -join ', '))"
  457.    } elseif($MethodBase.IsStatic) {
  458.       "[$($MethodBase.ReturnType.FullName)] [$($MethodBase.ReflectedType.FullName)]::$($MethodBase.Name)($($parameters -join ', '))"
  459.    } else {
  460.       "[$($MethodBase.ReturnType.FullName)] `$$($MethodBase.ReflectedType.Name)Object.$($MethodBase.Name)($($parameters -join ', '))"
  461.    }
  462. }
  463. }
  464.  
  465. function Read-Choice {
  466. [CmdletBinding()]
  467. param(
  468.    [Parameter(Mandatory=$true, ValueFromRemainingArguments=$true)]
  469.    [hashtable[]]$Choices
  470. ,
  471.    [Parameter(Mandatory=$False)]
  472.    [string]$Caption = "Please choose!"
  473. ,  
  474.    [Parameter(Mandatory=$False)]
  475.    [string]$Message = "Choose one of the following options:"
  476. ,  
  477.    [Parameter(Mandatory=$False)]
  478.    [int[]]$Default  = 0
  479. ,  
  480.    [Switch]$MultipleChoice
  481. ,
  482.    [Switch]$Passthru
  483. )
  484. begin {
  485.    [System.Collections.DictionaryEntry[]]$choices = $choices | % { $_.GetEnumerator() }
  486. }
  487. process {
  488.    $Descriptions = [System.Management.Automation.Host.ChoiceDescription[]]( $(
  489.                      foreach($choice in $choices) {
  490.                         New-Object System.Management.Automation.Host.ChoiceDescription $choice.Key,$choice.Value
  491.                      }
  492.                    ) )
  493.  
  494.    if(!$MultipleChoice) { [int]$Default = $Default[0] }
  495.  
  496.    [int[]]$Answer = $Host.UI.PromptForChoice($Caption,$Message,$Descriptions,$Default)
  497.  
  498.    if($Passthru) {
  499.       Write-Verbose "$Answer"
  500.       Write-Output  $Descriptions[$Answer]
  501.    } else {
  502.       Write-Output $Answer
  503.    }
  504. }
  505. }
  506.  
  507. function Get-Argument {
  508. param(
  509.    [Type]$Target
  510. ,  [ref]$Method
  511. ,  [Array]$Arguments
  512. )
  513. end {
  514. trap {
  515.    write-error $_
  516.    break
  517. }
  518.  
  519.    $flags = [System.Reflection.BindingFlags]"public,ignorecase,invokemethod,instance"
  520.  
  521.    [Type[]]$Types = @(
  522.       foreach($arg in $Arguments) {
  523.          if($arg -is [type]) {
  524.             $arg
  525.          }
  526.          else {
  527.             $arg.GetType()
  528.          }
  529.       }
  530.    )
  531.    try {
  532.       Write-Verbose "[$($Target.FullName)].GetMethod('$($Method.Value)', [$($Flags.GetType())]'$flags', `$null, ([Type[]]($(@($Types|%{$_.Name}) -join ','))), `$null)"
  533.       $MethodBase = $Target.GetMethod($($Method.Value), $flags, $null, $types, $null)
  534.       $Arguments
  535.       if($MethodBase) {
  536.          $Method.Value = $MethodBase.Name
  537.       }
  538.    } catch { }
  539.    
  540.    if(!$MethodBase) {
  541.       Write-Verbose "Try again to get $($Method.Value) Method on $($Target.FullName):"
  542.       $MethodBase = Get-Method $target $($Method.Value)
  543.       if(@($MethodBase).Count -gt 1) {
  544.          $i = 0
  545.          $i = Read-Choice -Choices $(foreach($mb in $MethodBase) { @{ "$($mb.SafeSyntax) &$($i = $i+1;$i)`b`n" =  $mb.SafeSyntax } }) -Default ($MethodBase.Count-1) -Caption "Choose a Method." -Message "Please choose which method overload to invoke:"
  546.          [System.Reflection.MethodBase]$MethodBase = $MethodBase[$i]
  547.       }
  548.      
  549.      
  550.       ForEach($parameter in $MethodBase.GetParameters()) {
  551.          $found = $false
  552.          For($a =0;$a -lt $Arguments.Count;$a++) {
  553.             if($argument[$a] -as $parameter.ParameterType) {
  554.                Write-Output $argument[$a]
  555.                if($a -gt 0 -and $a -lt $Arguments.Count) {
  556.                   $Arguments = $Arguments | Select -First ($a-1) -Last ($Arguments.Count -$a)
  557.                } elseif($a -eq 0) {
  558.                   $Arguments = $Arguments | Select -Last ($Arguments.Count - 1)
  559.                } else { # a -eq count
  560.                   $Arguments = $Arguments | Select -First ($Arguments.Count - 1)
  561.                }
  562.                $found = $true
  563.                break
  564.             }
  565.          }
  566.          if(!$Found) {
  567.             $userInput = Read-Host "Please enter a [$($parameter.ParameterType.FullName)] value for $($parameter.Name)"
  568.             if($userInput -match '^{.*}$' -and !($userInput -as $parameter.ParameterType)) {
  569.                Write-Output ((Invoke-Expression $userInput) -as $parameter.ParameterType)
  570.             } else {
  571.                Write-Output ($userInput -as $parameter.ParameterType)
  572.             }
  573.          }
  574.       }
  575.    }
  576. }
  577. }
  578.  
  579. function Invoke-Member {
  580. [CmdletBinding()]
  581. param(        
  582.    [parameter(position=10, valuefrompipeline=$true, mandatory=$true)]
  583.    [allowemptystring()]
  584.    $InputObject
  585. ,
  586.    [parameter(position=0, mandatory=$true)]
  587.    [validatenotnullorempty()]
  588.    $Member
  589. ,
  590.    [parameter(position=1, valuefromremainingarguments=$true)]
  591.    [allowemptycollection()]
  592.    $Arguments
  593. ,
  594.    [parameter()]
  595.    [switch]$Static
  596. )
  597. #  begin {
  598.    #  if(!(get-member SafeSyntax -input $Member -type Property)){
  599.       #  if(get-member Name -inpup $Member -Type Property) {
  600.          #  $Member = Get-Method $InputObject $Member.Name
  601.       #  } else {
  602.          #  $Member = Get-Method $InputObject $Member
  603.       #  }
  604.    #  }
  605.    #  $SafeSyntax = [ScriptBlock]::Create( $Member.SafeSyntax )
  606. #  }
  607. process {
  608.    #  if ($InputObject)
  609.    #  {
  610.       #  if ($InputObject | Get-Member $Member -static:$static)
  611.       #  {
  612.  
  613.          if ($InputObject -is [type]) {
  614.              $target = $InputObject
  615.          } else {
  616.              $target = $InputObject.GetType()
  617.          }
  618.      
  619.          if(Get-Member $Member -InputObject $InputObject -Type Properties) {
  620.             $_.$Member
  621.          }
  622.          elseif($Member -match "ctor|constructor") {
  623.             $Member = ".ctor"
  624.             [System.Reflection.BindingFlags]$flags = "CreateInstance"
  625.             $InputObject = $Null
  626.          }
  627.          else {
  628.             [System.Reflection.BindingFlags]$flags = "IgnoreCase,Public,InvokeMethod"
  629.             if($Static) { $flags = "$Flags,Static" } else { $flags = "$Flags,Instance" }
  630.          }
  631.          [ref]$Member = $Member
  632.          [Object[]]$Parameters = Get-Argument $Target $Member $Arguments
  633.          [string]$Member = $Member.Value
  634.  
  635.          Write-Verbose $(($Parameters | %{ '[' + $_.GetType().FullName + ']' + $_ }) -Join ", ")
  636.  
  637.          try {
  638.             Write-Verbose "Invoking $Member on [$target]$InputObject with [$($Flags.GetType())]'$flags' and [$($Parameters.GetType())]($($Parameters -join ','))"
  639.             Write-Verbose "[$($target.FullName)].InvokeMember('$Member', [System.Reflection.BindingFlags]'$flags', `$null, '$InputObject', ([object[]]($(($Parameters | %{ '[' + $_.GetType().FullName + ']''' + $_ + ''''}) -join', '))))"
  640.             $target.InvokeMember($Member, [System.Reflection.BindingFlags]"$flags", $null, $InputObject, $Parameters)
  641.          } catch {
  642.             Write-Warning $_.Exception
  643.              if ($_.Exception.Innerexception -is [MissingMethodException]) {
  644.                  write-warning "Method argument count (or type) mismatch."
  645.              }
  646.          }
  647.       #  } else {
  648.          #  write-warning "Method $Member not found."
  649.       #  }
  650.    #  }
  651. }
  652. }
  653.  
  654. function Invoke-Generic {
  655. #.Synopsis
  656. #  Invoke Generic method definitions via reflection:
  657. [CmdletBinding()]
  658. param(
  659.    [Parameter(Position=0,Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
  660.    [Alias('On')]
  661.    $InputObject
  662. ,
  663.    [Parameter(Position=1,ValueFromPipelineByPropertyName=$true)]
  664.    [Alias('Named')]
  665.    [string]$MethodName
  666. ,
  667.    [Parameter(Position=2)]
  668.    [Alias("Types")]
  669.    [Type[]]$ParameterTypes
  670. ,
  671.    [Parameter(Position=4, ValueFromRemainingArguments=$true, ValueFromPipelineByPropertyName=$true)]
  672.    [Object[]]$WithArgs
  673. ,
  674.    [Switch]$Static
  675. )
  676. begin {
  677.    if($Static) {
  678.       $BindingFlags = [System.Reflection.BindingFlags]"IgnoreCase,Public,Static"
  679.    } else {
  680.       $BindingFlags = [System.Reflection.BindingFlags]"IgnoreCase,Public,Instance"
  681.    }
  682. }
  683. process {
  684.    $Type = $InputObject -as [Type]
  685.    if(!$Type) { $Type = $InputObject.GetType() }
  686.    
  687.    if($WithArgs -and -not $ParameterTypes) {
  688.       $ParameterTypes = $withArgs | % { $_.GetType() }
  689.    } elseif(!$ParameterTypes) {
  690.       $ParameterTypes = [Type]::EmptyTypes
  691.    }  
  692.    
  693.    
  694.    trap { continue }
  695.    $MemberInfo = $Type.GetMethod($MethodName, $BindingFlags)
  696.    if(!$MemberInfo) {
  697.       $MemberInfo = $Type.GetMethod($MethodName, $BindingFlags, $null, $NonGenericArgumentTypes, $null)
  698.    }
  699.    if(!$MemberInfo) {
  700.       $MemberInfo = $Type.GetMethods($BindingFlags) | Where-Object {
  701.          $MI = $_
  702.          [bool]$Accept = $MI.Name -eq $MethodName
  703.          if($Accept){
  704.          Write-Verbose "$Accept = $($MI.Name) -eq $($MethodName)"
  705.             [Array]$GenericTypes = @($MI.GetGenericArguments() | Select -Expand Name)
  706.             [Array]$Parameters = @($MI.GetParameters() | Add-Member ScriptProperty -Name IsGeneric -Value {
  707.                                        $GenericTypes -Contains $this.ParameterType
  708.                                     } -Passthru)
  709.  
  710.                                     $Accept = $ParameterTypes.Count -eq $Parameters.Count
  711.             Write-Verbose "  $Accept = $($Parameters.Count) Arguments"
  712.             if($Accept) {
  713.                for($i=0;$i -lt $Parameters.Count;$i++) {
  714.                   $Accept = $Accept -and ( $Parameters[$i].IsGeneric -or ($ParameterTypes[$i] -eq $Parameters[$i].ParameterType))
  715.                   Write-Verbose "   $Accept =$(if($Parameters[$i].IsGeneric){' GENERIC or'}) $($ParameterTypes[$i]) -eq $($Parameters[$i].ParameterType)"
  716.                }
  717.             }
  718.          }
  719.          return $Accept
  720.       } | Sort { @($_.GetGenericArguments()).Count } | Select -First 1
  721.    }
  722.    Write-Verbose "Time to make generic methods."
  723.    Write-Verbose $MemberInfo
  724.    [Type[]]$GenericParameters = @()
  725.    [Array]$ConcreteTypes = @($MemberInfo.GetParameters() | Select -Expand ParameterType)
  726.    for($i=0;$i -lt $ParameterTypes.Count;$i++){
  727.       Write-Verbose "$($ParameterTypes[$i]) ? $($ConcreteTypes[$i] -eq $ParameterTypes[$i])"
  728.       if($ConcreteTypes[$i] -ne $ParameterTypes[$i]) {
  729.          $GenericParameters += $ParameterTypes[$i]
  730.       }
  731.       $ParameterTypes[$i] = Add-Member -in $ParameterTypes[$i] -Type NoteProperty -Name IsGeneric -Value $($ConcreteTypes[$i] -ne $ParameterTypes[$i]) -Passthru
  732.    }
  733.  
  734.     $ParameterTypes | Where-Object { $_.IsGeneric }
  735.    Write-Verbose "$($GenericParameters -join ', ') generic parameters"
  736.  
  737.    $MemberInfo = $MemberInfo.MakeGenericMethod( $GenericParameters )
  738.    Write-Verbose $MemberInfo
  739.  
  740.    if($WithArgs) {
  741.       [Object[]]$Arguments = $withArgs | %{ $_.PSObject.BaseObject }
  742.       Write-Verbose "Arguments: $(($Arguments | %{ $_.GetType().Name }) -Join ', ')"
  743.       $MemberInfo.Invoke( $InputObject, $Arguments )
  744.    } else {
  745.       $MemberInfo.Invoke( $InputObject )
  746.    }
  747. } }
  748.  
  749. # get a reference to the Type  
  750. $xlr8r = [psobject].assembly.gettype("System.Management.Automation.TypeAccelerators")
  751.  
  752. function Import-Namespace {
  753. [CmdletBinding()]
  754. param(
  755.    [Parameter(ValueFromPipeline=$true)]
  756.    [string]$Namespace
  757. ,  
  758.    [Switch]$Force
  759. )
  760.    Get-Type -Namespace $Namespace -Force:$Force | Add-Accelerator
  761. }
  762.  
  763. function Add-Accelerator {
  764. <#
  765.    .Synopsis
  766.       Add a type accelerator to the current session
  767.    .Description
  768.       The Add-Accelerator function allows you to add a simple type accelerator (like [regex]) for a longer type (like [System.Text.RegularExpressions.Regex]).
  769.    .Example
  770.       Add-Accelerator list System.Collections.Generic.List``1
  771.       $list = New-Object list[string]
  772.      
  773.       Creates an accelerator for the generic List[T] collection type, and then creates a list of strings.
  774.    .Example
  775.       Add-Accelerator "List T", "GList" System.Collections.Generic.List``1
  776.       $list = New-Object "list t[string]"
  777.      
  778.       Creates two accelerators for the Generic List[T] collection type.
  779.    .Parameter Accelerator
  780.       The short form accelerator should be just the name you want to use (without square brackets).
  781.    .Parameter Type
  782.       The type you want the accelerator to accelerate (without square brackets)
  783.    .Notes
  784.       When specifying multiple values for a parameter, use commas to separate the values.
  785.       For example, "-Accelerator string, regex".
  786.      
  787.       PowerShell requires arguments that are "types" to NOT have the square bracket type notation, because of the way the parsing engine works.  You can either just type in the type as System.Int64, or you can put parentheses around it to help the parser out: ([System.Int64])
  788.  
  789.       Also see the help for Get-Accelerator and Remove-Accelerator
  790.    .Link
  791.       http://huddledmasses.org/powershell-2-ctp3-custom-accelerators-finally/
  792. #>
  793. [CmdletBinding()]
  794. param(
  795.    [Parameter(Position=0,ValueFromPipelineByPropertyName=$true)]
  796.    [Alias("Key","Name")]
  797.    [string[]]$Accelerator
  798. ,
  799.    [Parameter(Position=1,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
  800.    [Alias("Value","FullName")]
  801.    [type]$Type
  802. )
  803. process {
  804.    # add a user-defined accelerator  
  805.    foreach($a in $Accelerator) {
  806.       if($xlr8r::AddReplace) {
  807.          $xlr8r::AddReplace( $a, $Type)
  808.       } else {
  809.          $null = $xlr8r::Remove( $a )
  810.          $xlr8r::Add( $a, $Type)
  811.       }
  812.       trap [System.Management.Automation.MethodInvocationException] {
  813.          if($xlr8r::get.keys -contains $a) {
  814.             if($xlr8r::get[$a] -ne $Type) {
  815.                Write-Error "Cannot add accelerator [$a] for [$($Type.FullName)]`n                  [$a] is already defined as [$($xlr8r::get[$a].FullName)]"
  816.             }
  817.             Continue;
  818.          }
  819.          throw
  820.       }
  821.    }
  822. }
  823. }
  824.  
  825. function Get-Accelerator {
  826. <#
  827.    .Synopsis
  828.       Get one or more type accelerator definitions
  829.    .Description
  830.       The Get-Accelerator function allows you to look up the type accelerators (like [regex]) defined on your system by their short form or by type
  831.    .Example
  832.       Get-Accelerator System.String
  833.      
  834.       Returns the KeyValue pair for the [System.String] accelerator(s)
  835.    .Example
  836.       Get-Accelerator ps*,wmi*
  837.      
  838.       Returns the KeyValue pairs for the matching accelerator definition(s)
  839.    .Parameter Accelerator
  840.       One or more short form accelerators to search for (Accept wildcard characters).
  841.    .Parameter Type
  842.       One or more types to search for.
  843.    .Notes
  844.       When specifying multiple values for a parameter, use commas to separate the values.
  845.       For example, "-Accelerator string, regex".
  846.      
  847.       Also see the help for Add-Accelerator and Remove-Accelerator
  848.    .Link
  849.       http://huddledmasses.org/powershell-2-ctp3-custom-accelerators-finally/
  850. #>
  851. [CmdletBinding(DefaultParameterSetName="ByType")]
  852. param(
  853.    [Parameter(Position=0, ParameterSetName="ByAccelerator", ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
  854.    [Alias("Key","Name")]
  855.    [string[]]$Accelerator
  856. ,
  857.    [Parameter(Position=0, ParameterSetName="ByType", ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
  858.    [Alias("Value","FullName")]
  859.    [type[]]$Type
  860. )
  861. process {
  862.    # add a user-defined accelerator  
  863.    switch($PSCmdlet.ParameterSetName) {
  864.       "ByAccelerator" {
  865.          $xlr8r::get.GetEnumerator() | % {
  866.             foreach($a in $Accelerator) {
  867.                if($_.Key -like $a) { $_ }
  868.             }
  869.          }
  870.          break
  871.       }
  872.       "ByType" {
  873.          if($Type -and $Type.Count) {
  874.             $xlr8r::get.GetEnumerator() | ? { $Type -contains $_.Value }
  875.          }
  876.          else {
  877.             $xlr8r::get.GetEnumerator() | %{ $_ }
  878.          }
  879.          break
  880.       }
  881.    }
  882. }
  883. }
  884.  
  885. function Remove-Accelerator {
  886. <#
  887.    .Synopsis
  888.       Remove a type accelerator from the current session
  889.    .Description
  890.       The Remove-Accelerator function allows you to remove a simple type accelerator (like [regex]) from the current session. You can pass one or more accelerators, and even wildcards, but you should be aware that you can remove even the built-in accelerators.
  891.  
  892.    .Example
  893.       Remove-Accelerator int
  894.       Add-Accelerator int Int64
  895.  
  896.       Removes the "int" accelerator for Int32 and adds a new one for Int64. I can't recommend doing this, but it's pretty cool that it works:
  897.  
  898.       So now, "$(([int]3.4).GetType().FullName)" would return "System.Int64"
  899.    .Example
  900.       Get-Accelerator System.Single | Remove-Accelerator
  901.  
  902.       Removes both of the default accelerators for System.Single: [float] and [single]
  903.    .Example
  904.       Get-Accelerator System.Single | Remove-Accelerator -WhatIf
  905.  
  906.       Demonstrates that Remove-Accelerator supports -Confirm and -Whatif. Will Print:
  907.          What if: Removes the alias [float] for type [System.Single]
  908.          What if: Removes the alias [single] for type [System.Single]
  909.    .Parameter Accelerator
  910.       The short form accelerator that you want to remove (Accept wildcard characters).
  911.    .Notes
  912.       When specifying multiple values for a parameter, use commas to separate the values.
  913.       For example, "-Accel string, regex".
  914.  
  915.       Also see the help for Add-Accelerator and Get-Accelerator
  916.    .Link
  917.       http://huddledmasses.org/powershell-2-ctp3-custom-accelerators-finally/
  918. #>
  919. [CmdletBinding(SupportsShouldProcess=$true)]
  920. param(
  921.    [Parameter(Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
  922.    [Alias("Key","FullName")]
  923.    [string[]]$Accelerator
  924. )
  925. process {
  926.    foreach($a in $Accelerator) {
  927.       foreach($key in $xlr8r::Get.Keys -like $a) {
  928.          if($PSCmdlet.ShouldProcess( "Removes the alias [$($Key)] for type [$($xlr8r::Get[$key].FullName)]",
  929.                                      "Remove the alias [$($Key)] for type [$($xlr8r::Get[$key].FullName)]?",
  930.                                      "Removing Type Accelerator" )) {
  931.             # remove a user-defined accelerator
  932.             $xlr8r::remove($key)  
  933.          }
  934.       }
  935.    }
  936. }
  937. }
  938.  
  939. ###############################################################################
  940. ##### Imported from PowerBoots
  941.  
  942. $Script:CodeGenContentProperties = 'Content','Child','Children','Frames','Items','Pages','Blocks','Inlines','GradientStops','Source','DataPoints', 'Series', 'VisualTree'
  943. $DependencyProperties = @{}
  944. if(Test-Path $PSScriptRoot\DependencyPropertyCache.xml) {
  945.         #$DependencyProperties = [System.Windows.Markup.XamlReader]::Parse( (gc $PSScriptRoot\DependencyPropertyCache.xml) )
  946.         $DependencyProperties = Import-CliXml  $PSScriptRoot\DependencyPropertyCache.xml
  947. }
  948.  
  949. function Get-ReflectionModule { $executioncontext.sessionstate.module }
  950.  
  951. function Set-ObjectProperties {
  952. [CmdletBinding()]
  953. param( $Parameters, [ref]$DObject )
  954.  
  955.    if($DObject.Value -is [System.ComponentModel.ISupportInitialize]) { $DObject.Value.BeginInit() }
  956.  
  957.    if($DebugPreference -ne "SilentlyContinue") { Write-Host; Write-Host ">>>> $($Dobject.Value.GetType().FullName)" -fore Black -back White }
  958.    foreach ($param in $Parameters) {
  959.       if($DebugPreference -ne "SilentlyContinue") { Write-Host "Processing Param: $($param|Out-String )" }
  960.       ## INGORE DEPENDENCY PROPERTIES FOR NOW :)
  961.       if($param.Key -eq "DependencyProps") {
  962.       ## HANDLE EVENTS ....
  963.       }
  964.       elseif ($param.Key.StartsWith("On_")) {
  965.          $EventName = $param.Key.SubString(3)
  966.          if($DebugPreference -ne "SilentlyContinue") { Write-Host "Event handler $($param.Key) Type: $(@($param.Value)[0].GetType().FullName)" }
  967.          $sb = $param.Value -as [ScriptBlock]
  968.          if(!$sb) {
  969.             $sb = (Get-Command $param.Value -CommandType Function,ExternalScript).ScriptBlock
  970.          }
  971.          $Dobject.Value."Add_$EventName".Invoke( $sb );
  972.          # $Dobject.Value."Add_$EventName".Invoke( ($sb.GetNewClosure()) );
  973.  
  974.          # $Dobject.Value."Add_$EventName".Invoke( $PSCmdlet.MyInvocation.MyCommand.Module.NewBoundScriptBlock( $sb.GetNewClosure() ) );
  975.  
  976.  
  977.       } ## HANDLE PROPERTIES ....
  978.       else {
  979.          try {
  980.             ## TODO: File a BUG because Write-DEBUG and Write-VERBOSE die here.
  981.             if($DebugPreference -ne "SilentlyContinue") {
  982.                Write-Host "Setting $($param.Key) of $($Dobject.Value.GetType().Name) to $($param.Value.GetType().FullName): $($param.Value)" -fore Gray
  983.             }
  984.             if(@(foreach($sb in $param.Value) { $sb -is [ScriptBlock] }) -contains $true) {
  985.                $Values = @()
  986.                foreach($sb in $param.Value) {
  987.                   $Values += & (Get-ReflectionModule) $sb
  988.                }
  989.             } else {
  990.                $Values = $param.Value
  991.             }
  992.  
  993.             if($DebugPreference -ne "SilentlyContinue") { Write-Host ([System.Windows.Markup.XamlWriter]::Save( $Dobject.Value )) -foreground green }
  994.             if($DebugPreference -ne "SilentlyContinue") { Write-Host ([System.Windows.Markup.XamlWriter]::Save( @($Values)[0] )) -foreground green }
  995.  
  996.             Set-Property $Dobject $Param.Key $Values
  997.  
  998.             if($DebugPreference -ne "SilentlyContinue") { Write-Host ([System.Windows.Markup.XamlWriter]::Save( $Dobject.Value )) -foreground magenta }
  999.  
  1000.             if($DebugPreference -ne "SilentlyContinue") {
  1001.                if( $Dobject.Value.$($param.Key) -ne $null ) {
  1002.                   Write-Host $Dobject.Value.$($param.Key).GetType().FullName -fore Green
  1003.                }
  1004.             }
  1005.          }
  1006.          catch [Exception]
  1007.          {
  1008.             Write-Host "COUGHT AN EXCEPTION" -fore Red
  1009.             Write-Host $_ -fore Red
  1010.             Write-Host $this -fore DarkRed
  1011.          }
  1012.       }
  1013.  
  1014.       while($DependencyProps) {
  1015.          $name, $value, $DependencyProps = $DependencyProps
  1016.          $name = ([string]@($name)[0]).Trim("-")
  1017.          if($name -and $value) {
  1018.             Set-DependencyProperty -Element $Dobject.Value -Property $name -Value $Value
  1019.          }
  1020.       }
  1021.    }
  1022.    if($DebugPreference -ne "SilentlyContinue") { Write-Host "<<<< $($Dobject.Value.GetType().FullName)" -fore Black -back White; Write-Host }
  1023.  
  1024.    if($DObject.Value -is [System.ComponentModel.ISupportInitialize]) { $DObject.Value.EndInit() }
  1025.  
  1026. }
  1027.  
  1028. function Set-Property {
  1029. PARAM([ref]$TheObject, $Name, $Values)
  1030.    $DObject = $TheObject.Value
  1031.  
  1032.    if($DebugPreference -ne "SilentlyContinue") { Write-Host ([System.Windows.Markup.XamlWriter]::Save( $DObject )) -foreground DarkMagenta }
  1033.    if($DebugPreference -ne "SilentlyContinue") { Write-Host ([System.Windows.Markup.XamlWriter]::Save( @($Values)[0] )) -foreground DarkMagenta }
  1034.  
  1035.    $PropertyType = $DObject.GetType().GetProperty($Name).PropertyType
  1036.    if('System.Windows.FrameworkElementFactory' -as [Type] -and $PropertyType -eq [System.Windows.FrameworkElementFactory] -and $DObject -is [System.Windows.FrameworkTemplate]) {
  1037.       if($DebugPreference -ne "SilentlyContinue") { Write-Host "Loading a FrameworkElementFactory" -foreground Green}
  1038.  
  1039.       # [Xml]$Template = [PoshWpf.XamlHelper]::ConvertToXaml( $DObject )
  1040.       # [Xml]$Content = [PoshWpf.XamlHelper]::ConvertToXaml( (@($Values)[0]) )
  1041.       # In .Net 3.5 the recommended way to programmatically create a template is to load XAML from a string or a memory stream using the Load method of the XamlReader class.
  1042.       [Xml]$Template = [System.Windows.Markup.XamlWriter]::Save( $DObject )
  1043.       [Xml]$Content = [System.Windows.Markup.XamlWriter]::Save( (@($Values)[0]) )
  1044.  
  1045.       $Template.DocumentElement.PrependChild( $Template.ImportNode($Content.DocumentElement, $true) ) | Out-Null
  1046.  
  1047.       $TheObject.Value = [System.Windows.Markup.XamlReader]::Parse( $Template.get_OuterXml() )
  1048.    }
  1049.    elseif('System.Windows.Data.Binding' -as [Type] -and @($Values)[0] -is [System.Windows.Data.Binding] -and !$PropertyType.IsAssignableFrom([System.Windows.Data.BindingBase])) {
  1050.       $Binding = @($Values)[0];
  1051.       if($DebugPreference -ne "SilentlyContinue") { Write-Host "$($DObject.GetType())::$Name is $PropertyType and the value is a Binding: $Binding" -fore Cyan}
  1052.  
  1053.       if(!$Binding.Source -and !$Binding.ElementName) {
  1054.          $Binding.Source = $DObject.DataContext
  1055.       }
  1056.       if($DependencyProperties.ContainsKey($Name)) {
  1057.          $field = @($DependencyProperties.$Name.Keys | Where { $DObject -is $_ -and $PropertyType -eq ([type]$DependencyProperties.$Name.$_.PropertyType)})[0] #  -or -like "*$Class" -and ($Param1.Value -as ([type]$_.PropertyType)
  1058.          if($field) {
  1059.             if($DebugPreference -ne "SilentlyContinue") { Write-Host "$($field)" -fore Blue }
  1060.             if($DebugPreference -ne "SilentlyContinue") { Write-Host "Binding: ($field)::`"$($DependencyProperties.$Name.$field.Name)`" to $Binding" -fore Blue}
  1061.  
  1062.             $DObject.SetBinding( ([type]$field)::"$($DependencyProperties.$Name.$field.Name)", $Binding ) | Out-Null
  1063.          } else {
  1064.             throw "Couldn't figure out $( @($DependencyProperties.$Name.Keys) -join ', ' )"
  1065.          }
  1066.       } else {
  1067.          if($DebugPreference -ne "SilentlyContinue") {
  1068.             Write-Host "But $($DObject.GetType())::${Name}Property is not a Dependency Property, so it probably can't be bound?" -fore Cyan
  1069.          }
  1070.          try {
  1071.  
  1072.             $DObject.SetBinding( ($DObject.GetType()::"${Name}Property"), $Binding ) | Out-Null
  1073.  
  1074.             if($DebugPreference -ne "SilentlyContinue") {
  1075.                Write-Host ([System.Windows.Markup.XamlWriter]::Save( $Dobject )) -foreground yellow
  1076.             }
  1077.          } catch {
  1078.             Write-Host "Nope, was not able to set it." -fore Red
  1079.             Write-Host $_ -fore Red
  1080.             Write-Host $this -fore DarkRed
  1081.          }
  1082.       }
  1083.    }
  1084.    elseif($PropertyType -ne [Object] -and $PropertyType.IsAssignableFrom( [System.Collections.IEnumerable] ) -and ($DObject.$($Name) -eq $null)) {
  1085.       if($Values -is [System.Collections.IEnumerable]) {
  1086.          if($DebugPreference -ne "SilentlyContinue") { Write-Host "$Name is $PropertyType which is IEnumerable, and the value is too!" -fore Cyan }
  1087.          $DObject.$($Name) = $Values
  1088.       } else {
  1089.          if($DebugPreference -ne "SilentlyContinue") { Write-Host "$Name is $PropertyType which is IEnumerable, but the value is not." -fore Cyan }
  1090.          $DObject.$($Name) = new-object "System.Collections.ObjectModel.ObservableCollection[$(@($Values)[0].GetType().FullName)]"
  1091.          $DObject.$($Name).Add($Values)
  1092.       }
  1093.    }
  1094.    elseif($DObject.$($Name) -is [System.Collections.IList]) {
  1095.       foreach ($value in @($Values)) {
  1096.          try {
  1097.             $null = $DObject.$($Name).Add($value)
  1098.          }
  1099.          catch
  1100.          {
  1101.             # Write-Host "CAUGHT array problem" -fore Red
  1102.             if($_.Exception.Message -match "Invalid cast from 'System.String' to 'System.Windows.UIElement'.") {
  1103.                $null = $DObject.$($Name).Add( (New-System.Windows.Controls.TextBlock $value) )
  1104.             } else {
  1105.                Write-Error $_.Exception
  1106.             throw
  1107.             }
  1108.          }
  1109.       }
  1110.    }
  1111.    else {
  1112.       ## If they pass an array of 1 when we only want one, we just use the first value
  1113.       if($Values -is [System.Collections.IList] -and $Values.Count -eq 1) {
  1114.          if($DebugPreference -ne "SilentlyContinue") { Write-Host "Value is an IList ($($Values.GetType().FullName))" -fore Cyan}
  1115.          if($DebugPreference -ne "SilentlyContinue") { Write-Host "But we'll just use the first ($($Values[0].GetType().FullName))" -fore Cyan}
  1116.  
  1117.          if($DebugPreference -ne "SilentlyContinue") { Write-Host ([System.Windows.Markup.XamlWriter]::Save( $Values[0] )) -foreground White}
  1118.          try {
  1119.             $DObject.$($Name) = $Values[0]
  1120.          }
  1121.          catch [Exception]
  1122.          {
  1123.             # Write-Host "CAUGHT collection value problem" -fore Red
  1124.             if($_.Exception.Message -match "Invalid cast from 'System.String' to 'System.Windows.UIElement'.") {
  1125.                $null = $DObject.$($Name).Add( (TextBlock $Values[0]) )
  1126.             }else {
  1127.                throw
  1128.             }
  1129.          }
  1130.       }
  1131.       else ## If they pass an array when we only want one, we try to use it, and failing that, cast it to strings
  1132.       {
  1133.          if($DebugPreference -ne "SilentlyContinue") { Write-Host "Value is just $Values" -fore Cyan}
  1134.          try {
  1135.             $DObject.$($Name) = $Values
  1136.          } catch [Exception]
  1137.          {
  1138.             # Write-Host "CAUGHT value problem" -fore Red
  1139.             if($_.Exception.Message -match "Invalid cast from 'System.String' to 'System.Windows.UIElement'.") {
  1140.                $null = $DObject.$($Name).Add( (TextBlock $values) )
  1141.             }else {
  1142.                throw
  1143.             }
  1144.          }
  1145.       }
  1146.    }
  1147. }
  1148.  
  1149. function Set-DependencyProperty {
  1150. [CmdletBinding()]
  1151. PARAM(
  1152.    [Parameter(Position=0,Mandatory=$true)]
  1153.    $Property
  1154. ,
  1155.    [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
  1156.    $Element
  1157. ,
  1158.    [Parameter()]
  1159.    [Switch]$Passthru
  1160. )
  1161.  
  1162. DYNAMICPARAM {
  1163.    $paramDictionary = new-object System.Management.Automation.RuntimeDefinedParameterDictionary
  1164.    $Param1 = new-object System.Management.Automation.RuntimeDefinedParameter
  1165.    $Param1.Name = "Value"
  1166.    # $Param1.Attributes.Add( (New-ParameterAttribute -Position 1) )
  1167.    $Param1.Attributes.Add( (New-Object System.Management.Automation.ParameterAttribute -Property @{ Position = 1 }) )
  1168.  
  1169.    if( $Property ) {
  1170.       if($Property.GetType() -eq ([System.Windows.DependencyProperty]) -or
  1171.          $Property.GetType().IsSubclassOf(([System.Windows.DependencyProperty])))
  1172.       {
  1173.          $Param1.ParameterType = $Property.PropertyType
  1174.       }
  1175.       elseif($Property -is [string] -and $Property.Contains(".")) {
  1176.          $Class,$Property = $Property.Split(".")
  1177.          if($DependencyProperties.ContainsKey($Property)){
  1178.             $type = $DependencyProperties.$Property.Keys -like "*$Class"
  1179.             if($type) {
  1180.                $Param1.ParameterType = [type]@($DependencyProperties.$Property.$type)[0].PropertyType
  1181.             }
  1182.          }
  1183.  
  1184.       } elseif($DependencyProperties.ContainsKey($Property)){
  1185.          if($Element) {
  1186.             if($DependencyProperties.$Property.ContainsKey( $element.GetType().FullName )) {
  1187.                $Param1.ParameterType = [type]$DependencyProperties.$Property.($element.GetType().FullName).PropertyType
  1188.             }
  1189.          } else {
  1190.             $Param1.ParameterType = [type]$DependencyProperties.$Property.Values[0].PropertyType
  1191.          }
  1192.       }
  1193.       else
  1194.       {
  1195.          $Param1.ParameterType = [PSObject]
  1196.       }
  1197.    }
  1198.    else
  1199.    {
  1200.       $Param1.ParameterType = [PSObject]
  1201.    }
  1202.    $paramDictionary.Add("Value", $Param1)
  1203.    return $paramDictionary
  1204. }
  1205. PROCESS {
  1206.    trap {
  1207.       Write-Host "ERROR Setting Dependency Property" -Fore Red
  1208.       Write-Host "Trying to set $Property to $($Param1.Value)" -Fore Red
  1209.       continue
  1210.    }
  1211.    if($Property.GetType() -eq ([System.Windows.DependencyProperty]) -or
  1212.       $Property.GetType().IsSubclassOf(([System.Windows.DependencyProperty]))
  1213.    ){
  1214.       trap {
  1215.          Write-Host "ERROR Setting Dependency Property" -Fore Red
  1216.          Write-Host "Trying to set $($Property.FullName) to $($Param1.Value)" -Fore Red
  1217.          continue
  1218.       }
  1219.       $Element.SetValue($Property, ($Param1.Value -as $Property.PropertyType))
  1220.    }
  1221.         else {
  1222.       if("$Property".Contains(".")) {
  1223.          $Class,$Property = "$Property".Split(".")
  1224.       }
  1225.  
  1226.       if( $DependencyProperties.ContainsKey("$Property" ) ) {
  1227.          $fields = @( $DependencyProperties.$Property.Keys -like "*$Class" | ? { $Param1.Value -as ([type]$DependencyProperties.$Property.$_.PropertyType) } )
  1228.                         if($fields.Count -eq 0 ) {
  1229.             $fields = @($DependencyProperties.$Property.Keys -like "*$Class" )
  1230.          }                     
  1231.          if($fields.Count) {
  1232.             $success = $false
  1233.             foreach($field in $fields) {
  1234.                trap {
  1235.                   Write-Host "ERROR Setting Dependency Property" -Fore Red
  1236.                   Write-Host "Trying to set $($field)::$($DependencyProperties.$Property.$field.Name) to $($Param1.Value) -as $($DependencyProperties.$Property.$field.PropertyType)" -Fore Red
  1237.                   continue
  1238.                }
  1239.                $Element.SetValue( ([type]$field)::"$($DependencyProperties.$Property.$field.Name)", ($Param1.Value -as ([type]$DependencyProperties.$Property.$field.PropertyType)))
  1240.                if($?) { $success = $true; break }
  1241.             }
  1242.                                
  1243.             if(!$success) {
  1244.                                         throw "food"
  1245.                                 }                              
  1246.          } else {
  1247.             Write-Host "Couldn't find the right property: $Class.$Property on $( $Element.GetType().Name ) of type $( $Param1.Value.GetType().FullName )" -Fore Red
  1248.          }
  1249.                 }
  1250.                 else {
  1251.          Write-Host "Unknown Dependency Property Key: $Property on $($Element.GetType().Name)" -Fore Red
  1252.       }
  1253.    }
  1254.        
  1255.    if( $Passthru ) { $Element }
  1256. }
  1257. }
  1258.  
  1259. Add-Type -Assembly WindowsBase
  1260. function Add-ConstructorFunction {
  1261. <#
  1262. .Synopsis
  1263.    Add support for a new class by creating the dynamic constructor function(s).
  1264. .Description
  1265.    Creates a New-Namespace.Type function for each type passed in, as well as a short form "Type" alias.
  1266.  
  1267.    Exposes all of the properties and events of the type as perameters to the function.
  1268.  
  1269.    NOTE: The Type MUST have a default parameterless constructor.
  1270. .Parameter Assembly
  1271.         The Assembly you want to generate constructors for. All public types within it will be generated if possible.
  1272. .Parameter Type
  1273.    The type you want to create a constructor function for.  It must have a default parameterless constructor.
  1274. .Example
  1275.    Add-ConstructorFunction System.Windows.Controls.Button
  1276.  
  1277.    Creates a new function for the Button control.
  1278.  
  1279. .Example
  1280.    [Reflection.Assembly]::LoadWithPartialName( "PresentationFramework" ).GetTypes() | Add-ConstructorFunction
  1281.  
  1282.    Will create constructor functions for all the WPF components in the PresentationFramework assembly.  Note that you could also load that assembly using GetAssembly( "System.Windows.Controls.Button" ) or Load( "PresentationFramework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" )
  1283.  
  1284. .Example
  1285.    Add-ConstructorFunction -Assembly PresentationFramework
  1286.  
  1287.    Will create constructor functions for all the WPF components in the PresentationFramework assembly.
  1288.  
  1289. .Links
  1290.    http://HuddledMasses.org/powerboots
  1291. .ReturnValue
  1292.    The name(s) of the function(s) created -- so you can export them, if necessary.
  1293. .Notes
  1294.  AUTHOR:    Joel Bennett http://HuddledMasses.org
  1295.  LASTEDIT:  2009-01-13 16:35:23
  1296. #>
  1297. [CmdletBinding(DefaultParameterSetName="FromType")]
  1298. PARAM(
  1299.    [Parameter(Position=0,ValueFromPipeline=$true,ParameterSetName="FromType",Mandatory=$true)]
  1300.    [type[]]$type
  1301. ,
  1302.    [Alias("FullName")]
  1303.    [Parameter(Position=0,ValueFromPipelineByPropertyName=$true,ParameterSetName="FromAssembly",Mandatory=$true)]
  1304.    [string[]]$Assembly
  1305. ,
  1306.    [Parameter()]
  1307.         [string]$Path = "$PSScriptRoot\Types_Generated"
  1308. ,
  1309.    [switch]$Force
  1310. ,
  1311.    [switch]$ShortAliases
  1312. ,
  1313.    [Switch]$Quiet
  1314. )
  1315. BEGIN {
  1316.    [Type[]]$Empty=@()
  1317.    if(!(Test-Path $Path)) {
  1318.       MkDir $Path
  1319.    }
  1320.    $ErrorList = @()
  1321. }
  1322. END {
  1323.    #Set-Content -Literal $PSScriptRoot\DependencyPropertyCache.xml -Value ([System.Windows.Markup.XamlWriter]::Save( $DependencyProperties ))
  1324.         Export-CliXml -Path $PSScriptRoot\DependencyPropertyCache.xml -InputObject $DependencyProperties
  1325.        
  1326.    if($ErrorList.Count) { Write-Warning "Some New-* functions not aliased." }
  1327.    $ErrorList | Write-Error
  1328. }
  1329. PROCESS {
  1330.    if($PSCmdlet.ParameterSetName -eq "FromAssembly") {
  1331.       [type[]]$type = @()
  1332.       foreach($lib in $Assembly) {
  1333.          $asm =  $null
  1334.          trap { continue }
  1335.          if(Test-Path $lib) {
  1336.             $asm =  [Reflection.Assembly]::LoadFrom( (Convert-Path (Resolve-Path $lib -EA "SilentlyContinue") -EA "SilentlyContinue") )
  1337.          }
  1338.          if(!$asm) {
  1339.             ## BUGBUG: LoadWithPartialName is "Obsolete" -- but it still works in 2.0/3.5
  1340.             $asm =  [Reflection.Assembly]::LoadWithPartialName( $lib )
  1341.          }
  1342.          if($asm) {
  1343.             $type += $asm.GetTypes() | ?{ $_.IsPublic    -and !$_.IsEnum      -and
  1344.                                          !$_.IsAbstract  -and !$_.IsInterface -and
  1345.                                           $_.GetConstructor( "Instance,Public", $Null, $Empty, @() )}
  1346.          } else {
  1347.             Write-Error "Can't find the assembly $lib, please check your spelling and try again"
  1348.          }
  1349.       }
  1350.    }
  1351.  
  1352.    foreach($T in $type) {
  1353.       $TypeName = $T.FullName
  1354.       $ScriptPath = Join-Path $Path "New-$TypeName.ps1"
  1355.       Write-Verbose $TypeName
  1356.  
  1357.       ## Collect all dependency properties ....
  1358.       $T.GetFields() |
  1359.          Where-Object { $_.FieldType -eq [System.Windows.DependencyProperty] } |
  1360.          ForEach-Object {
  1361.             [string]$Field = $_.DeclaringType::"$($_.Name)".Name
  1362.             [string]$TypeName = $_.DeclaringType.FullName
  1363.  
  1364.             if(!$DependencyProperties.ContainsKey( $Field )) {
  1365.                $DependencyProperties.$Field = @{}
  1366.             }
  1367.  
  1368.             $DependencyProperties.$Field.$TypeName = @{
  1369.                Name         = [string]$_.Name
  1370.                PropertyType = [string]$_.DeclaringType::"$($_.Name)".PropertyType.FullName
  1371.             }
  1372.          }
  1373.  
  1374.                 if(!( Test-Path $ScriptPath ) -OR $Force) {
  1375.          $Pipelineable = @();
  1376.          ## Get (or generate) a set of parameters based on the the Type Name
  1377.          $PropertyNames = New-Object System.Text.StringBuilder "@("
  1378.  
  1379.          $Parameters = New-Object System.Text.StringBuilder "[CmdletBinding(DefaultParameterSetName='Default')]`nPARAM(`n"
  1380.                  
  1381.          ## Add all properties
  1382.          $Properties = $T.GetProperties("Public,Instance,FlattenHierarchy") |
  1383.             Where-Object { $_.CanWrite -Or $_.PropertyType.GetInterface([System.Collections.IList]) }
  1384.                        
  1385.          $Properties = ($T.GetEvents("Public,Instance,FlattenHierarchy") + $Properties) | Sort-Object Name -Unique
  1386.  
  1387.          foreach ($p in $Properties) {
  1388.             $null = $PropertyNames.AppendFormat(",'{0}'",$p.Name)
  1389.             switch( $p.MemberType ) {
  1390.                Event {
  1391.                   $null = $PropertyNames.AppendFormat(",'{0}__'",$p.Name)
  1392.                   $null = $Parameters.AppendFormat(@'
  1393.         [Parameter()]
  1394.         [PSObject]${{On_{0}}}
  1395. ,
  1396. '@, $p.Name)
  1397.                }
  1398.                Property {
  1399.                   if($p.Name -match "^$($CodeGenContentProperties -Join '$|^')`$") {
  1400.                      $null = $Parameters.AppendFormat(@'
  1401.         [Parameter(Position=1,ValueFromPipeline=$true)]
  1402.         [Object[]]${{{0}}}
  1403. ,
  1404. '@, $p.Name)
  1405.                      $Pipelineable += @(Add-Member -in $p.Name -Type NoteProperty -Name "IsCollection" -Value $($p.PropertyType.GetInterface([System.Collections.IList]) -ne $null) -Passthru)
  1406.                   }
  1407.                   elseif($p.PropertyType -eq [System.Boolean])
  1408.                   {
  1409.                      $null = $Parameters.AppendFormat(@'
  1410.         [Parameter()]
  1411.         [Switch]${{{0}}}
  1412. ,
  1413. '@, $p.Name)
  1414.                   }
  1415.                   else
  1416.                   {
  1417.                      $null = $Parameters.AppendFormat(@'
  1418.         [Parameter()]
  1419.         [Object[]]${{{0}}}
  1420. ,
  1421. '@, $p.Name)
  1422.                   }
  1423.                }
  1424.             }
  1425.          }
  1426.                 $null = $Parameters.Append('    [Parameter(ValueFromRemainingArguments=$true)]
  1427.         [string[]]$DependencyProps
  1428. )')
  1429.                 $null = $PropertyNames.Remove(2,1).Append(')')
  1430.                        
  1431.       $collectable = [bool]$(@(foreach($p in @($Pipelineable)){$p.IsCollection}) -contains $true)
  1432.       $ofs = "`n";
  1433.  
  1434. $function = $(
  1435. "
  1436. if(!( '$TypeName' -as [Type] )) {
  1437. $(
  1438.   if( $T.Assembly.GlobalAssemblyCache ) {
  1439. "  `$null = [Reflection.Assembly]::Load( '$($T.Assembly.FullName)' ) "
  1440.   } else {
  1441. "  `$null = [Reflection.Assembly]::LoadFrom( '$($T.Assembly.Location)' ) "
  1442.   }
  1443. )
  1444. }
  1445. ## if(`$ExecutionContext.SessionState.Module.Guid -ne (Get-ReflectionModule).Guid) {
  1446. ##      Write-Warning `"$($T.Name) not invoked in ReflectionModule context. Attempting to reinvoke.`"
  1447. ##    # `$scriptParam = `$PSBoundParameters
  1448. ##    # return iex `"& (Get-ReflectionModule) '`$(`$MyInvocation.MyCommand.Path)' ```@PSBoundParameters`"
  1449. ## }
  1450. Write-Verbose ""$($T.Name) in module `$(`$executioncontext.sessionstate.module) context!""
  1451.  
  1452. function New-$TypeName {
  1453. <#
  1454. .Synopsis
  1455.   Create a new $($T.Name) object
  1456. .Description
  1457.   Generates a new $TypeName object, and allows setting all of it's properties.
  1458.   (From the $($T.Assembly.GetName().Name) assembly v$($T.Assembly.GetName().Version))
  1459. .Notes
  1460. GENERATOR : $((Get-ReflectionModule).Name) v$((Get-ReflectionModule).Version) by Joel Bennett http://HuddledMasses.org
  1461. GENERATED : $(Get-Date)
  1462. ASSEMBLY  : $($T.Assembly.FullName)
  1463. FULLPATH  : $($T.Assembly.Location)
  1464. #>
  1465.  
  1466. $Parameters
  1467. BEGIN {
  1468.   `$DObject = New-Object $TypeName
  1469.   `$All = $PropertyNames
  1470. }
  1471. PROCESS {
  1472. "
  1473. if(!$collectable) {
  1474. "
  1475.   # The content of $TypeName is not a collection
  1476.   # So if we're in a pipeline, make a new $($T.Name) each time
  1477.   if(`$_) {
  1478.      `$DObject = New-Object $TypeName
  1479.   }
  1480. "
  1481. }
  1482. @'
  1483. foreach($key in @($PSBoundParameters.Keys) | where { $PSBoundParameters[$_] -is [ScriptBlock] }) {
  1484.   $PSBoundParameters[$key] = $PSBoundParameters[$key].GetNewClosure()
  1485. }
  1486. Set-ObjectProperties @($PSBoundParameters.GetEnumerator() | Where { [Array]::BinarySearch($All,($_.Key -replace "^On_(.*)",'$1__')) -ge 0 } ) ([ref]$DObject)
  1487. '@
  1488.  
  1489. if(!$collectable) {
  1490. @'
  1491.   Microsoft.PowerShell.Utility\Write-Output $DObject
  1492. } #Process
  1493. '@
  1494.    } else {
  1495. @'
  1496. } #Process
  1497. END {
  1498.   Microsoft.PowerShell.Utility\Write-Output $DObject
  1499. }
  1500. '@
  1501.    }
  1502. @"
  1503. }
  1504. ## New-$TypeName `@PSBoundParameters
  1505. "@
  1506. )
  1507.  
  1508.          Set-Content -Path $ScriptPath -Value $Function
  1509.       }
  1510.  
  1511.       # Note: set the aliases global for now, because it's too late to export them
  1512.                 # E.g.: New-Button = New-System.Windows.Controls.Button
  1513.                 Set-Alias -Name "New-$($T.Name)" "New-$TypeName" -ErrorAction SilentlyContinue -ErrorVariable +ErrorList -Scope Global -Passthru:(!$Quiet)
  1514.                 if($ShortAliases) {
  1515.                 # E.g.: Button = New-System.Windows.Controls.Button
  1516.                         Set-Alias -Name $T.Name "New-$TypeName" -ErrorAction SilentlyContinue -ErrorVariable +ErrorList -Scope Global -Passthru:(!$Quiet)
  1517.                 }
  1518.                
  1519.       New-AutoLoad -Name $ScriptPath -Alias "New-$TypeName"
  1520.    }
  1521. }#PROCESS
  1522. }
  1523.  
  1524. function Import-ConstructorFunctions {
  1525. #.Synopsis
  1526. #  Autoload pre-generated constructor functions and generate aliases for them.
  1527. #.Description
  1528. #  Parses the New-* scripts in the specified path, and uses the Autoload module to pre-load them as commands and set up aliases for them, without parsing them into memory.
  1529. #.Parameter Path
  1530. #  The path to a folder with functions to preload
  1531. param(
  1532.    [Parameter()]
  1533.    [Alias("PSPath")]
  1534.         [string[]]$Path = "$PSScriptRoot\Types_Generated"
  1535. )
  1536. end {
  1537.         $Paths = $(foreach($p in $Path) { Join-Path $p "New-*.ps1" })
  1538.         Write-Verbose "Importing Constructors from: `n`t$($Paths -join "`n`t")"
  1539.  
  1540.         foreach($script in Get-ChildItem $Paths -ErrorAction 0) {
  1541.                 $TypeName = $script.Name -replace 'New-(.*).ps1','$1'
  1542.       $ShortName = ($TypeName -split '\.')[-1]
  1543.       Write-Verbose "Importing constructor for type: $TypeName ($ShortName)"
  1544.                
  1545.       # Note: set the aliases global for now, because it's too late to export them
  1546.                 # E.g.: New-Button = New-System.Windows.Controls.Button
  1547.                 Set-Alias -Name "New-$ShortName" "New-$TypeName" -ErrorAction SilentlyContinue -ErrorVariable +ErrorList -Scope Global -Passthru:(!$Quiet)
  1548.                 if($ShortAliases) {
  1549.                 # E.g.: Button = New-System.Windows.Controls.Button
  1550.                         Set-Alias -Name $ShortName "New-$TypeName" -ErrorAction SilentlyContinue -ErrorVariable +ErrorList -Scope Global -Passthru:(!$Quiet)
  1551.                 }
  1552.  
  1553.                 New-Autoload -Name $Script.FullName -Alias "New-$TypeName"
  1554.                 # Write-Host -fore yellow $(Get-Command "New-$TypeName" | Out-String)
  1555.                 Get-Command "New-$TypeName"
  1556.         }
  1557. }
  1558. }
  1559.  
  1560. #.Parameter Snapin
  1561. #  The full path to where the snapin .dll is
  1562. #.Parameter OutputPath
  1563. #  Force the module manifest(s) to output in a different location than where the snapin .dll is
  1564. #.Parameter ModuleName
  1565. #  Override the snapin name(s) for the module manifest
  1566. #.Parameter Author
  1567. #  Overrides the Company Name from the manifest when generating the module's "Author" comment
  1568. #.Parameter Passthru
  1569. #  Returns the ModuleManifest (same as -Passthru on New-ModuleManifest)
  1570. #.Example
  1571. #  New-ModuleManifestFromSnapin ".\Quest Software\Management Shell for AD" -ModuleName QAD
  1572. #
  1573. #  Description
  1574. #  -----------
  1575. #  Generates a new module manifest file: QAD.psd1 in the folder next to the Quest.ActiveRoles.ArsPowerShellSnapIn.dll
  1576. #.Example
  1577. #  New-ModuleManifestFromSnapin "C:\Program Files (x86)\Microsoft SQL Server\100\Tools\Binn\" -Output $pwd
  1578. #
  1579. #  Description
  1580. #  -----------
  1581. #  Generates module manifest files for the SqlServer PSSnapins and stores them in the current folder
  1582. function New-ModuleManifestFromSnapin {
  1583. param(
  1584.    [Parameter(Mandatory=$true, Position="0", ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
  1585.    [Alias("FullName")]
  1586.    [String[]]$Snapin
  1587. ,
  1588.    [Parameter()]
  1589.    $OutputPath
  1590. ,
  1591.    [Parameter()]
  1592.    $ModuleName
  1593. ,
  1594.    [Parameter()]
  1595.    [String]$Author
  1596. ,
  1597.    [Switch]$Passthru
  1598. )
  1599.  
  1600. # $SnapinPath = $(Get-ChildItem $SnapinPath -Filter *.dll)
  1601. $EAP = $ErrorActionPreference
  1602. $ErrorActionPreference = "SilentlyContinue"
  1603. Add-Assembly $Snapin
  1604. $ErrorActionPreference = $EAP
  1605.  
  1606. $SnapinTypes = Get-Assembly $Snapin | Get-Type -BaseType System.Management.Automation.PSSnapIn, System.Management.Automation.CustomPSSnapIn -WarningAction SilentlyContinue
  1607.  
  1608.  
  1609. foreach($SnapinType in $SnapinTypes) {
  1610.    $Installer = New-Object $SnapinType
  1611.  
  1612.    if(!$PSBoundParameters.ContainsKey("OutputPath")) {
  1613.       $OutputPath = (Split-Path $SnapinType.Assembly.Location)
  1614.    }
  1615.  
  1616.    if(!$PSBoundParameters.ContainsKey("ModuleName")) {
  1617.       $ModuleName = $Installer.Vendor
  1618.    }
  1619.    if(!$PSBoundParameters.ContainsKey("Author")) {
  1620.       $Author = $Installer.Name
  1621.    }
  1622.    $ManifestPath = (Join-Path $OutputPath "$ModuleName.psd1")
  1623.  
  1624.    Write-Verbose "Creating Module Manifest: $ManifestPath"
  1625.  
  1626.    $RequiredAssemblies = @( $SnapinType.Assembly.GetReferencedAssemblies() | Get-Assembly | Where-Object { (Split-Path $_.Location) -eq (Split-Path $SnapinType.Assembly.Location) } | Select-Object -Expand Location | Resolve-Path -ErrorAction Continue)
  1627.  
  1628.    # New-ModuleManifest has a bad bug -- it makes paths relative to the current location (and it does it wrong).
  1629.    Push-Location $OutputPath
  1630.  
  1631.    if($Installer -is [System.Management.Automation.CustomPSSnapIn]) {
  1632.       $Cmdlets = $Installer.Cmdlets | Select-Object -Expand Name
  1633.       $Types = $Installer.Types | Select-Object -Expand FileName | %{ $path = Resolve-Path $_ -ErrorAction Continue; if(!$path){ $_ } else { $path } }
  1634.       $Formats = $Installer.Formats | Select-Object -Expand FileName | %{ $path = Resolve-Path $_ -ErrorAction Continue; if(!$path){ $_ } else { $path } }
  1635.    } else {
  1636.       $Types = $Installer.Types |  %{ $path = Resolve-Path $_ -ErrorAction Continue; if(!$path){ $_ } else { $path } }
  1637.       $Formats = $Installer.Formats |  %{ $path = Resolve-Path $_ -ErrorAction Continue; if(!$path){ $_ } else { $path } }
  1638.    }
  1639.    if(!$Cmdlets) { $Cmdlets = "*" }
  1640.    if(!$Types) { $Types = @() }
  1641.    if(!$Formats) { $Formats = @() }
  1642.  
  1643.    New-ModuleManifest -Path $ManifestPath -Author $Author -Company $Installer.Vendor -Description $Installer.Description `
  1644.                       -ModuleToProcess $SnapinType.Assembly.Location -Types $Types -Formats $Formats -Cmdlets $Cmdlets `
  1645.                       -RequiredAssemblies $RequiredAssemblies  -Passthru:$Passthru `
  1646.                       -NestedModules @() -Copyright $Installer.Vendor -FileList @()
  1647.    Pop-Location
  1648. }
  1649. }
  1650.  
  1651.  
  1652. Add-Accelerator list System.Collections.Generic.List``1
  1653. Add-Accelerator dictionary System.Collections.Generic.Dictionary``2
  1654.  
  1655. Set-Alias aasm Add-Assembly
  1656. Set-Alias gt Get-Type
  1657. Set-Alias gasm Get-Assembly
  1658. Set-Alias gctor Get-Constructor

Submit a correction or amendment below (
click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:


Remember me