Die wichtigsten Namespaces im Überblick:
- System.Management.Automation - This is the root namespace for Windows PowerShell. It contains the classes, enumerations, and interfaces required to implement custom cmdlets. In particular, the Cmdlet class is the base class from which all custom cmdlet classes must be derived from.
- System.Management.Automation.Provider - This namespace contains the classes, enumerations, and interfaces required to implement a Windows PowerShell provider. In particular, the CmdletProvider class is the base class from which all Windows PowerShell provider classes must be derived.
- Microsoft.PowerShell.Commands: This namespace contains the cmdlets implemented by Windows PowerShell. In a similar fashion, it is recommended that you create a [YourName].Commands namespace for those cmdlets that you implement.
- System.Management.Automation.Host: This namespace contains the classes, enumerations, and interfaces that the cmdlet uses to interact with the Host application user.
- System.Management.Automation.Internal: This namespace contains the base classes used by other namespace classes. For example, the CmdletMetadataAttribute class is the base class for the CmdletAttribute class.
- System.Management.Automation.Runspaces: This namespace contains the classes, enumerations, and interfaces used to create an Windows PowerShell Runspace. In this context, the Windows PowerShell Runspace is the context in which one or more Windows PowerShell pipelines invoke cmdlets. That is, cmdlets do their work within the context of an Windows PowerShell Runspace.
Die Cmdlets in diesem und den nächsten Beispielen bieten Zugriff auf die ID3Tag-Informationen von MP3-Dateien. Ist nicht wirklich aufregend und ich bin mir sicher, dass ich nicht der erste bin, der auf diese Idee kommt. Um die verschiedenen Facetten der Cmdlet-Entwicklung zu betrachten, sollte das aber ausreichen.
Zum Auslesen der ID3Tags verwende ich die ID3Sharp Library von Chris Woods, die man auf sourceforge.net finden kann.
In einem Klassenbibliothek-Projekt müssen zunächst zwei Verweise hinzugefügt werden:
- System.Management.Automation - siehe oben, wird immer gebraucht, wenn ein Cmdlet erstellt werden soll. Im Verweis hinzufügen-Dialog auf den Tab Durchsuchen wechseln und die Dll C:\Program Files\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0\System.Management.Automation.dll auswählen
- System.Configuration.Install.dll - wird für das Snap-in benötigt, das unser Cmdlet später in der Powershell registriert. Näheres später. Zu finden im Verweis hinzufügen-Dialog auf dem Tab .Net
Ein Cmdlet muss immer die Basisklasse System.Management.Automation.Cmdlet erweitern. In Powershell setzt sich der Name von Cmdlets aus einem Verb-Substantiv-Paar zusammen, so z.B. Get-Service, Move-Item, etc... Die Namensgebung ist durchgängig und dabei recht einfach zu durchschauen. Die gängigsten Verben finden sich, nach Kategorien gruppiert, in einigen Enumerationen im System.Management.Automation-Namensraum, z.B. VerbsCommon, VerbsSecurity. Diese sollte man nach Möglichkeit auch in eigenen Cmdlets verwenden, um Konsistenz in der Powershell-Benutzung für den Anwender zu wahren.
[Cmdlet(VerbsCommon.Get, "Mp3FileInfo")]
public class GetMp3FileInfoCommand : Cmdlet
{
protected override void ProcessRecord()
{
// Ausgabeobjekte in die Pipeline geben
WriteObject("Das Mp3FileInfo Cmdlet steht zur Verfügung");
}
}
Um den Namen für das Cmdlet zu definieren, wird die öffentliche Klasse mit dem Cmdlet-Attribut versehen, dem Verb und Substantiv mitgegeben werden. Der Klassenname selbst ist unerheblich für die Verwendung in Powershell. Die einzige Methode, die überschrieben werden muss, is ProcessRecord(). In dieser Methode führt das Cmdlet seine Funktionen aus. Die Rückgabeobjekte werden dann mit Hilfe der WriteObject-Methode der Basisklasse in die Powershell-Pipeline geschrieben.
Das war's auch schon. Ziemlich unspektakulär.
Was zum ersten Test noch fehlt, ist ein Snap-in. Snap-ins registrieren benutzerdefinierte Cmdlets und Provider in der Powershell, damit diese von der Kommandozeile aus aufrufbar werden.
Zwei Sorten von Snap-ins stehen zur Auswahl. Ich wähle hier die einfache Variante, die die Klasse PSSnapIn erweitert. Diese Art von Snap-in registriert alle verfügbaren Cmdlets und Provider innerhalb der eigenen Assembly. Die Luxusvariante erweitert CustomPSSnapIn. Mit einem CustomPSSnapIn ist es möglich, nur bestimmte Cmdlets und/oder Provider innerhalb der eigenen, oder einer anderen Assembly zu registrieren.
Für das Snap-in wird eine neue Klasse zum Projekt hinzugefügt.
[RunInstaller(true)]
public class Mp3FileInfoSnapIn : PSSnapIn
{
public Mp3FileInfoSnapIn()
: base()
{
}
/// <summary>
/// Specify the name of the PowerShell snap-in.
/// </summary>
public override string Name
{
get
{
return "Mp3FileInfoSnapIn";
}
}
/// <summary>
/// Specify the vendor for the PowerShell snap-in.
/// </summary>
public override string Vendor
{
get
{
return "ESCde";
}
}
/// <summary>
/// Specify the localization resource information for the vendor.
/// Use the format: resourceBaseName,VendorName.
/// </summary>
public override string VendorResource
{
get
{
return "Mp3FileInfoSnapIn,ESCde";
}
}
/// <summary>
/// Specify a description of the PowerShell snap-in.
/// </summary>
public override string Description
{
get
{
return "Registers all Mp3FileInfo Cmdlets.";
}
}
/// <summary>
/// Specify the localization resource information for the description.
/// Use the format: resourceBaseName,Description.
/// </summary>
public override string DescriptionResource
{
get
{
return "Mp3FileInfoSnapIn,Registers all Mp3FileInfo Cmdlets.";
}
}
}
Sieht nach viel aus, ist es aber nicht. Das einzige, was der Entwickler hier zu tun hat, ist das Überschreiben von fünf String-Eigenschaften zur Beschreibung des Snap-ins. Der Rest wird von der Basisklasse geregelt. Wichtig ist, dass die Snap-in-Klasse von dem RunInstaller(true)-Attribut dekoriert wird. Das Attribut ist im System.ComponentModel Namespace definiert. Das RunInstaller-Attribut dient dem Installutil Tool bei der Installation der Assembly als Hinweis. Installutil.exe überprüft die angegebene Assembly mittels Reflexion und sucht alle Installer-Typen, bei denen für das RunInstaller-Attribut true festgelegt wurde. Anschließend führt das Tool für jede Instanz des Installer-Typs entweder die Install-Methode oder die Uninstall-Methode aus. PSSnapin ist indirekt von solch einem Installer abgeleitet, der in der referenzierten Assembly System.Configuration.Install.dll definiert ist.
Jetzt kann das Projekt kompiliert werden.