2014-11-13 15 views
7

Angenommen ich ein Skript mit mehreren Funktionen haben exakt die gleichen Parameter, in den gleichen Positionen und mit den gleichen Typen und Einschränkungen, wie dies unter:Kann ein 'param'-Block über mehrere Funktionen hinweg wiederverwendet werden?

function Verb1-MyValue { 
    [CmdletBinding()] 
    param (
     [parameter(Mandatory = $true)][String]$Param1, 
     [parameter(Mandatory = $true)][String]$Param2, 
     [ValidateSet("Value1","Value2")][String]$Param3 = "Value1" 
    ) 
    # code ... 
} 

function Verb2-MyValue { 
    [CmdletBinding()] 
    param (
     [parameter(Mandatory = $true)][String]$Param1, 
     [parameter(Mandatory = $true)][String]$Param2, 
     [ValidateSet("Value1","Value2")][String]$Param3 = "Value1" 
    ) 
    # code ... 
} 

# and so on ... 

ich den param Block mit allen Funktionen teilen wollte zu vermeiden mögliche Probleme (sie brauchen, um für alle von ihnen gleich zu sein) und die Redundanz zu vermeiden.

Gibt es in PowerShell eine Möglichkeit, den Block param für mehrere Funktionen im selben Skript zu verwenden? Wenn nicht, gibt es Alternativen dazu?

+1

Schreiben Sie dies als Powershell-Skript obligatorisch? Was ist mit einem C# -Projekt, das in ein Powershell-Modul eingebaut wurde? Wenn dies eine Option ist, können Sie eine beliebige Basisklasse für alle Cmdlets mit derselben Parameterstruktur verwenden. – Travis

+0

Eigentlich nein, das als Skript ist überhaupt nicht zwingend. Könnten Sie Ihren Kommentar als eine Antwort bearbeiten, die zeigt, wie das möglich wäre? Ich bin sehr interessiert. Weißt du, ob es unmöglich ist, dies nur mit Skript zu erreichen? – julealgon

+0

Ich kann nicht darüber nachdenken, es nur in Skript zu tun – Travis

Antwort

3

Wenn Sie können, würde ich mit dem Ansatz "C# -Projekt, das ein Powershell-Modul erstellt" gehen. Abhängig von Ihrer Situation, gibt es eine Vielzahl von Vorteilen, von denen einige umfassen:

  1. Kompilierzeit Sicherheit. Ich weiß, ein paar Entwickler würden kompilierte/stark typisierte Sprachen wegen der zusätzlichen Sicherheit bevorzugen
  2. Einfacher zu automatisierten Tests schreiben. Dies mag strittig sein, aber in meiner Meinung, Bibliotheken wie nUnit und andere Test-Frameworks sind ein großes Plus
  3. Language Vertrautheit. Ich habe viele Entwickler kennen gelernt, die mit C#, aber nicht powershell vertraut sind, und so haben sie Kampf.

Um zu beginnen, fand ich this article. Im Grunde genommen sagt es einen Verweis auf System.Management.Automation.dll zu einem Projekt hinzuzufügen, und dann ein sehr einfaches Cmdlets würde wie folgt aussehen:

using System; 
using System.Collection.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Management.Automation; 

namespace MyModule 
{ 
    [Cmdlet(VerbsCommon.Get, "Saluation")] 
    public class GetSaluation : PSCmdlet 
    { 
     private string[] nameCollection; 

     [Parameter(
      Mandatory = true, 
      ValueFromPipelineByPropertyName = true, 
      ValueFromPipelin = true, 
      Position = 0, 
      HelpMessage = "Name to get salutation for." 
     )] 
     [Alias("Person", "FirstName")] 
     public string[] Name 
     { 
      get { return nameCollection;} 
      set { nameCollection = value;} 
     } 

     protected override void BeginProcessing() 
     { 
      base.BeginProcessing(); 
     } 

     protected override void ProcessRecord() 
     { 
      foreach (string name in nameCollection) 
      { 
       WriteVerbose("Creating salutation for " + name); 
       string salutation = "Hello, " + name; 
       WriteObject(salutation); 
      } 
     } 

     protected override void EndProcessing() 
     { 
      base.EndProcessing(); 
     } 

    } 

Dann dieses Modul zu verwenden, öffnen Sie eine Powershell Auffordern, navigieren Sie zu dem Ort, an dem Ihre DLL erstellt wurde, und verwenden Sie das Cmdlet Import-Module.

Und dann für Ihre spezielle Frage (Wie Wiederverwendung ich param Blöcke mit verschiedenen Cmdlets?) Sie eine Basis Cmdlets haben können, die die Parameter definiert, und alle Cmdlets wünschen Sie, dass von der Basis erben schreiben Klasse.

2

Ich würde empfehlen, Travis 'Vorschlag zu verwenden und die kompilierte Cmdlet-Route zu gehen. Sie haben in einem Ihrer Kommentare gefragt, ob das mit nur einem Skript möglich wäre, also werde ich versuchen, ein Beispiel dafür zu geben. Erweiterte Funktionen unterstützen die Erstellung dynamischer Parameter, und Sie können diese Fähigkeit kombinieren mit dem Cmdlet Get-Command dynamische Versionen eines bestimmten Befehls-Parameter zu erstellen:

function GetDynamicParamDictionary { 
    [CmdletBinding()] 
    param(
     [Parameter(ValueFromPipeline=$true, Mandatory=$true)] 
     [string] $CommandName 
    ) 

    begin { 
     # Get a list of params that should be ignored (they're common to all advanced functions) 
     $CommonParameterNames = [System.Runtime.Serialization.FormatterServices]::GetUninitializedObject([type] [System.Management.Automation.Internal.CommonParameters]) | 
      Get-Member -MemberType Properties | 
      Select-Object -ExpandProperty Name 
    } 

    process { 

     # Create the dictionary that this scriptblock will return: 
     $DynParamDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary 

     # Convert to object array and get rid of Common params: 
     (Get-Command $CommandName | select -exp Parameters).GetEnumerator() | 
      Where-Object { $CommonParameterNames -notcontains $_.Key } | 
      ForEach-Object { 
       $DynamicParameter = New-Object System.Management.Automation.RuntimeDefinedParameter (
        $_.Key, 
        $_.Value.ParameterType, 
        $_.Value.Attributes 
       ) 
       $DynParamDictionary.Add($_.Key, $DynamicParameter) 
      } 

     # Return the dynamic parameters 
     $DynParamDictionary 
    } 
} 

function TestFunction { 
    # Create some dummy params 
    param(
     [string] $StringParam, 
     [switch] $Switch1, 
     [switch] $Switch2, 
     [int] $IntParam 
    ) 
} 

function MimicTestFunction { 
    [CmdletBinding()] 
    # Empty param block (you could add extra params here) 
    param() 

    # Mimic TestFunction's parameters 
    dynamicparam { GetDynamicParamDictionary TestFunction } 
    process { $PSBoundParameters } 
} 

function MimicGetChildItem { 
    [CmdletBinding()] 
    param() 

    dynamicparam { GetDynamicParamDictionary Get-ChildItem } 
    process { $PSBoundParameters } 
} 

Dies sollte außer arbeiten, wenn eine der Referenz Befehl hat auch dynamische Parameter.

Verwandte Themen