Udostępnij za pomocą


Tworzenie dostawcy kontenerów Windows PowerShell

Ten temat opisuje, jak stworzyć dostawcę Windows PowerShell, który może pracować na wielowarstwowych magazynach danych. W tego typu magazynie danych najwyższy poziom magazynu zawiera elementy główne, a każdy kolejny poziom nazywany jest węzłem elementów potomnych. Pozwalając użytkownikowi na pracę nad tymi węzłami potomnymi, może on wchodzić w interakcje hierarchiczne poprzez magazyn danych.

Dostawcy zdolni do pracy z wielopoziomowymi magazynami danych nazywani są dostawcami kontenerów Windows PowerShell. Należy jednak pamiętać, że dostawca kontenerów Windows PowerShell może być używany tylko wtedy, gdy istnieje jeden kontener (bez zagnieżdżonych kontenerów) zawierający elementy. Jeśli są zagnieżdżone kontenery, musisz zaimplementować dostawcę nawigacji Windows PowerShell. Więcej informacji o implementacji dostawcy nawigacji Windows PowerShell można znaleźć w artykule Tworzenie dostawcy nawigacji Windows PowerShell.

Uwaga / Notatka

Możesz pobrać plik źródłowy C# (AccessDBSampleProvider04.cs) tego dostawcy za pomocą Microsoft Windows Software Development Kit for Windows Vista oraz .NET Framework 3.0 Runtime Components. Instrukcje pobrania można znaleźć w sekcji Jak zainstalować Windows PowerShell oraz pobierz Windows PowerShell SDK. Pobrane pliki źródłowe są dostępne w katalogu <PowerShell Samples> . Więcej informacji o innych implementacjach dostawców Windows PowerShell można znaleźć w artykule Projektowanie swojego dostawcy Windows PowerShell.

Opisany tutaj dostawca kontenera Windows PowerShell definiuje bazę danych jako pojedynczy kontener, a tabele i wiersze bazy danych są zdefiniowane jako elementy kontenera.

Ostrzeżenie

Pamiętaj, że ten projekt zakłada bazę danych z polem z identyfikatorem nazwy, a typ pola to LongInteger.

Definiowanie klasy dostawcy kontenera Windows PowerShell

Dostawca kontenerów Windows PowerShell musi zdefiniować klasę .NET wywodzącą się z klasy bazowej System.Management.Automation.Provider.ContainerCmdletProvider . Oto definicja klasy dostawcy kontenerów Windows PowerShell opisana w tej sekcji.

[CmdletProvider("AccessDB", ProviderCapabilities.None)]
public class AccessDBProvider : ContainerCmdletProvider

Zauważ, że w tej definicji klasy atrybut System.Management.Automation.Provider.CmdletProviderAttribute zawiera dwa parametry. Pierwszy parametr określa przyjazną dla użytkownika nazwę dostawcy używanego przez Windows PowerShell. Drugi parametr określa specyficzne możliwości Windows PowerShell, które dostawca udostępnia środowisku wykonawczym Windows PowerShell podczas przetwarzania poleceń. Dla tego dostawcy nie dodano żadnych specyficznych funkcji Windows PowerShell.

Definiowanie funkcjonalności bazowej

Jak opisano w Designing Your Windows PowerShell Provider, klasa System.Management.Automation.Provider.ContainerCmdletProvider pochodzi z kilku innych klas, które zapewniały różne funkcje dostawców. Dostawca kontenerów Windows PowerShell musi więc zdefiniować całą funkcjonalność oferowaną przez te klasy.

Aby zaimplementować funkcje dodawania informacji inicjalizacyjnych specyficznych dla sesji oraz uwalniania zasobów używanych przez dostawcę, zobacz Tworzenie podstawowego dostawcy Windows PowerShell. Jednak większość dostawców (w tym opisany tutaj) może korzystać z domyślnej implementacji tej funkcjonalności oferowanej przez Windows PowerShell.

Aby uzyskać dostęp do magazynu danych, dostawca musi wdrożyć metody podstawowej klasy System.Management.Automation.Provider.DriveCmdletProvider . Więcej informacji o implementacji tych metod można znaleźć w artykule Tworzenie dostawcy dysków Windows PowerShell.

Aby manipulować elementami magazynu danych, takimi jak pobieranie, ustawianie i czyszczenie elementów, dostawca musi wdrożyć metody dostępne przez klasę bazową System.Management.Automation.Provider.ItemCmdletProvider . Więcej informacji o implementacji tych metod można znaleźć w artykule Tworzenie dostawcy elementów Windows PowerShell.

Odzyskiwanie przedmiotów dla dzieci

Aby pobrać element potomny, dostawca kontenera Windows PowerShell musi nadpisać metodę System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItems*, aby wspierać wywołania z cmdletu Get-ChildItem . Ta metoda pobiera elementy potomne ze zbioru danych i zapisuje je do potoku jako obiekty. Jeśli recurse parametr cmdletu jest podany, metoda pobiera wszystkie dzieci niezależnie od ich poziomu. Jeśli parametr recurse nie jest określony, metoda pobiera tylko jeden poziom potomków.

Oto implementacja metody System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItems* dla tego dostawcy. Zauważ, że ta metoda pobiera elementy potomne we wszystkich tabelach bazy danych, gdy ścieżka wskazuje bazę Access, a także pobiera elementy potomne z wierszy tej tabeli, jeśli ścieżka wskazuje na tabelę danych.

protected override void GetChildItems(string path, bool recurse)
{
    // If path represented is a drive then the children in the path are 
    // tables. Hence all tables in the drive represented will have to be
    // returned
    if (PathIsDrive(path))
    {
        foreach (DatabaseTableInfo table in GetTables())
        {
            WriteItemObject(table, path, true);

            // if the specified item exists and recurse has been set then 
            // all child items within it have to be obtained as well
            if (ItemExists(path) && recurse)
            {
                GetChildItems(path + pathSeparator + table.Name, recurse);
            }
        } // foreach (DatabaseTableInfo...
    } // if (PathIsDrive...
    else
    {
        // Get the table name, row number and type of path from the
        // path specified
        string tableName;
        int rowNumber;

        PathType type = GetNamesFromPath(path, out tableName, out rowNumber);

        if (type == PathType.Table)
        {
            // Obtain all the rows within the table
            foreach (DatabaseRowInfo row in GetRows(tableName))
            {
                WriteItemObject(row, path + pathSeparator + row.RowNumber,
                        false);
            } // foreach (DatabaseRowInfo...
        }
        else if (type == PathType.Row)
        {
            // In this case the user has directly specified a row, hence
            // just give that particular row
            DatabaseRowInfo row = GetRow(tableName, rowNumber);
            WriteItemObject(row, path + pathSeparator + row.RowNumber,
                        false);
        }
        else
        {
            // In this case, the path specified is not valid
            ThrowTerminatingInvalidPathException(path);
        }
    } // else
} // GetChildItems

Rzeczy, o których warto pamiętać przy wdrażaniu GetChildItems

Następujące warunki mogą mieć zastosowanie do Twojej implementacji System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItems*:

Przypisywanie parametrów dynamicznych do Get-ChildItem Cmdlet

Czasami Get-ChildItem cmdlet wywołujący System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItems* wymaga dodatkowych parametrów, które są określane dynamicznie w czasie działania. Aby zapewnić te parametry dynamiczne, dostawca kontenerów Windows PowerShell musi zaimplementować metodę System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItemsDynamicParameters* . Ta metoda pobiera parametry dynamiczne dla elementu na wskazanej ścieżce i zwraca obiekt o właściwościach i polach o atrybutach parsowania podobnych do klasy cmdlet lub obiektu System.Management.Automation.RuntimeDefinedParameterDictionary . Środowisko uruchomieniowe Windows PowerShell wykorzystuje zwrócony obiekt do dodawania parametrów do cmdletu Get-ChildItem .

Ten dostawca kontenerów Windows PowerShell nie implementuje tej metody. Jednak poniższy kod jest domyślną implementacją tej metody.

Pobieranie nazw przedmiotów potomnych

Aby pobrać nazwy elementów potomnych, dostawca kontenera Windows PowerShell musi nadpisać metodę System.Management.Automation.Provider.ContainerCmdletProvider.GetChildNames*, aby wspierać wywołania z Get-ChildItem cmdletu, gdy parametr jest określony Name . Ta metoda pobiera nazwy elementów potomnych dla określonej ścieżki lub nazwy elementów potomnych dla wszystkich kontenerów, jeśli returnAllContainers parametr cmdletu jest określony. Imię dziecka to część liściowa ścieżki. Na przykład nazwa potomna ścieżki C:\windows\system32\abc.dll to "abc.dll". Nazwa potomna katalogu C:\windows\system32 to "system32".

Oto implementacja metody System.Management.Automation.Provider.ContainerCmdletProvider.GetChildNames* dla tego dostawcy. Zwróć uwagę, że metoda pobiera nazwy tabel, jeśli wskazana ścieżka wskazuje bazę danych Access (dysk), a numery wierszy, jeśli ścieżka wskazuje tabelę.

protected override void GetChildNames(string path,
                              ReturnContainers returnContainers)
{
    // If the path represented is a drive, then the child items are
    // tables. get the names of all the tables in the drive.
    if (PathIsDrive(path))
    {
        foreach (DatabaseTableInfo table in GetTables())
        {
            WriteItemObject(table.Name, path, true);
        } // foreach (DatabaseTableInfo...
    } // if (PathIsDrive...
    else
    {
        // Get type, table name and row number from path specified
        string tableName;
        int rowNumber;

        PathType type = GetNamesFromPath(path, out tableName, out rowNumber);

        if (type == PathType.Table)
        {
            // Get all the rows in the table and then write out the 
            // row numbers.
            foreach (DatabaseRowInfo row in GetRows(tableName))
            {
                WriteItemObject(row.RowNumber, path, false);
            } // foreach (DatabaseRowInfo...
        }
        else if (type == PathType.Row)
        {
            // In this case the user has directly specified a row, hence
            // just give that particular row
            DatabaseRowInfo row = GetRow(tableName, rowNumber);

            WriteItemObject(row.RowNumber, path, false);
        }
        else
        {
            ThrowTerminatingInvalidPathException(path);
        }
    } // else
} // GetChildNames

Rzeczy, o których warto pamiętać przy wdrażaniu GetChildNames

Następujące warunki mogą mieć zastosowanie do Twojej implementacji System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItems*:

Przypisywanie parametrów dynamicznych do Get-ChildItem Cmdlet (nazwa)

Czasami Get-ChildItem cmdlet (wraz z parametrem Name ) wymaga dodatkowych parametrów, które są określane dynamicznie w czasie działania. Aby zapewnić te parametry dynamiczne, dostawca kontenera Windows PowerShell musi zaimplementować metodę System.Management.Automation.Provider.ContainerCmdletProvider.GetChildNamesDynamicParameters* . Ta metoda pobiera parametry dynamiczne dla elementu na wskazanej ścieżce i zwraca obiekt o właściwościach i polach z atrybutami parsowania podobnymi do klasy cmdlet lub obiektu System.Management.Automation.RuntimeDefinedParameterDictionary . Środowisko uruchomieniowe Windows PowerShell wykorzystuje zwrócony obiekt do dodawania parametrów do cmdletu Get-ChildItem .

Ten dostawca nie wdraża tej metody. Jednak poniższy kod jest domyślną implementacją tej metody.

Przemianowanie przedmiotów

Aby zmienić nazwę elementu, dostawca kontenerów Windows PowerShell musi nadpisać metodę System.Management.Automation.Provider.ContainerCmdletProvider.RenameItem* , aby wspierać wywołania z cmdletu Rename-Item . Ta metoda zmienia nazwę elementu na określonej ścieżce na nową podaną nazwę. Nowa nazwa musi zawsze być względna względem nadrzędnego elementu (kontenera).

Ten dostawca nie nadpisuje metody System.Management.Automation.Provider.ContainerCmdletProvider.RenameItem* . Jednak domyślna implementacja jest następująca.

Rzeczy, o których warto pamiętać przy wdrażaniu RenameItem

Następujące warunki mogą mieć zastosowanie do Twojej implementacji System.Management.Automation.Provider.ContainerCmdletProvider.RenameItem*:

Przypisywanie parametrów dynamicznych do Rename-Item Cmdlet

Czasami Rename-Item cmdlet wymaga dodatkowych parametrów, które są określane dynamicznie w czasie działania. Aby zapewnić te dynamiczne parametry, dostawca kontenerów Windows PowerShell musi wdrożyć metodę System.Management.Automation.Provider.ContainerCmdletProvider.RenameItemDynamicParameters* . Ta metoda pobiera parametry elementu na wskazanej ścieżce i zwraca obiekt o właściwościach i polach z atrybutami parsowania podobnymi do klasy cmdlet lub obiektu System.Management.Automation.RuntimeDefinedParameterDictionary . Środowisko uruchomieniowe Windows PowerShell wykorzystuje zwrócony obiekt do dodawania parametrów do cmdletu Rename-Item .

Ten dostawca kontenera nie wdraża tej metody. Jednak poniższy kod jest domyślną implementacją tej metody.

Tworzenie nowych przedmiotów

Aby tworzyć nowe elementy, dostawca kontenerów musi wdrożyć metodę System.Management.Automation.Provider.ContainerCmdletProvider.NewItem*, aby wspierać wywołania z cmdletu New-Item . Ta metoda tworzy element danych znajdujący się na określonej ścieżce. Parametr type cmdletu zawiera typ zdefiniowany przez dostawcę dla nowego elementu. Na przykład dostawca systemu plików używa parametru type o wartości "plik" lub "katalog". Parametr newItemValue cmdletu określa wartość specyficzną dla dostawcy dla nowego elementu.

Oto implementacja metody System.Management.Automation.Provider.ContainerCmdletProvider.NewItem* dla tego dostawcy.

protected override void NewItem( string path, string type, object newItemValue )
{
    // Create the new item here after
    // performing necessary validations
    //
    // WriteItemObject(newItemValue, path, false);

    // Example
    //
    // if (ShouldProcess(path, "new item"))
    // {
    //      // Create a new item and then call WriteObject
    //      WriteObject(newItemValue, path, false);
    // }

} // NewItem
{
    case 1:
        {
            string name = pathChunks[0];

            if (TableNameIsValid(name))
            {
                tableName = name;
                retVal = PathType.Table;
            }
        }
        break;

    case 2:
        {
            string name = pathChunks[0];

Rzeczy, o których warto pamiętać przy wdrażaniu NewItem

Następujące warunki mogą mieć zastosowanie do implementacji System.Management.Automation.Provider.ContainerCmdletProvider.NewItem*:

Przypisywanie parametrów dynamicznych do New-Item Cmdlet

Czasami New-Item cmdlet wymaga dodatkowych parametrów, które są określane dynamicznie w czasie działania. Aby zapewnić te parametry dynamiczne, dostawca kontenera musi zaimplementować metodę System.Management.Automation.Provider.ContainerCmdletProvider.NewItemDynamicParameters* . Ta metoda pobiera parametry elementu na wskazanej ścieżce i zwraca obiekt o właściwościach i polach z atrybutami parsowania podobnymi do klasy cmdlet lub obiektu System.Management.Automation.RuntimeDefinedParameterDictionary . Środowisko uruchomieniowe Windows PowerShell wykorzystuje zwrócony obiekt do dodawania parametrów do cmdletu New-Item .

Ten dostawca nie wdraża tej metody. Jednak poniższy kod jest domyślną implementacją tej metody.

Usuwanie przedmiotów

Aby usunąć elementy, dostawca Windows PowerShell musi nadpisać metodę System.Management.Automation.Provider.ContainerCmdletProvider.RemoveItem*, aby wspierać wywołania z cmdletu Remove-Item . Ta metoda usuwa element z magazynu danych na wyznaczonej ścieżce. Jeśli parametr Remove-Item cmdletu jest ustawiony recurse na true, metoda usuwa wszystkie elementy potomne niezależnie od ich poziomu. Jeśli parametr jest ustawiony na false, metoda usuwa tylko jeden element na określonej ścieżce.

Ten dostawca nie obsługuje usuwania przedmiotów. Jednak poniższy kod jest domyślną implementacją System.Management.Automation.Provider.ContainerCmdletProvider.RemoveItem*.

Rzeczy, o których warto pamiętać przy wdrażaniu RemoveItem

Następujące warunki mogą mieć zastosowanie do implementacji System.Management.Automation.Provider.ContainerCmdletProvider.NewItem*:

Przypisywanie parametrów dynamicznych do Remove-Item Cmdlet

Czasami Remove-Item cmdlet wymaga dodatkowych parametrów, które są określane dynamicznie w czasie działania. Aby dostarczyć te parametry dynamiczne, dostawca kontenera musi wdrożyć metodę System.Management.Automation.Provider.ContainerCmdletProvider.RemoveItemDynamicParameters* do obsługi tych parametrów. Ta metoda pobiera parametry dynamiczne dla elementu na wskazanej ścieżce i zwraca obiekt o właściwościach i polach z atrybutami parsowania podobnymi do klasy cmdlet lub obiektu System.Management.Automation.RuntimeDefinedParameterDictionary . Środowisko uruchomieniowe Windows PowerShell wykorzystuje zwrócony obiekt do dodawania parametrów do cmdletu Remove-Item .

Ten dostawca kontenera nie wdraża tej metody. Jednak poniższy kod jest domyślną implementacją System.Management.Automation.Provider.ContainerCmdletProvider.RemoveItemDynamicParameters*.

Zapytanie o elementy poddane

Aby sprawdzić, czy elementy potomne znajdują się na określonej ścieżce, dostawca kontenera Windows PowerShell musi nadpisać metodę System.Management.Automation.Provider.ContainerCmdletProvider.HasChildItems* . Ta metoda zwraca, true jeśli element ma potomki, a false w przeciwnym razie nie. Dla ścieżki zerowej lub pustej metoda traktuje wszystkie elementy w magazynie danych za dzieci i zwraca true.

Oto nadpisanie dla metody System.Management.Automation.Provider.ContainerCmdletProvider.HasChildItems* . Jeśli metoda pomocnicza ChunkPath tworzy więcej niż dwie części ścieżki, metoda zwraca false, ponieważ zdefiniowane są tylko kontener bazy danych i kontener tabeli. Więcej informacji o tej metodzie pomocniczej można znaleźć w artykule Metoda ChunkPath omówiona w artykule Creating a Windows PowerShell Item Provider.

protected override bool HasChildItems( string path )
{
    return false;
} // HasChildItems
        ErrorCategory.InvalidOperation, tableName));
}

return results;

Rzeczy, o których warto pamiętać przy wdrażaniu HasChildItems

Następujące warunki mogą mieć zastosowanie do Twojej implementacji System.Management.Automation.Provider.ContainerCmdletProvider.HasChildItems*:

Kopiowanie elementów

Aby skopiować elementy, dostawca kontenera musi wdrożyć metodę System.Management.Automation.Provider.ContainerCmdletProvider.CopyItem , aby wspierać wywołania z cmdletu Copy-Item . Ta metoda kopiuje element danych z lokalizacji wskazanej parametrem path cmdletu do lokalizacji wskazanej przez parametr.copyPath Jeśli recurse parametr jest określony, metoda kopiuje wszystkie podkontenery. Jeśli parametr nie jest określony, metoda kopiuje tylko jeden poziom elementów.

Ten dostawca nie wdraża tej metody. Jednak poniższy kod jest domyślną implementacją System.Management.Automation.Provider.ContainerCmdletProvider.CopyItem.

Rzeczy, o których warto pamiętać przy wdrażaniu CopyItem

Następujące warunki mogą mieć zastosowanie do Twojej implementacji System.Management.Automation.Provider.ContainerCmdletProvider.CopyItem:

Przypisywanie parametrów dynamicznych do Copy-Item Cmdlet

Czasami Copy-Item cmdlet wymaga dodatkowych parametrów, które są określane dynamicznie w czasie działania. Aby zapewnić te parametry dynamiczne, dostawca kontenerów Windows PowerShell musi zaimplementować metodę System.Management.Automation.Provider.ContainerCmdletProvider.CopyItemDynamicParameters*, aby obsługiwać te parametry. Ta metoda pobiera parametry elementu na wskazanej ścieżce i zwraca obiekt o właściwościach i polach z atrybutami parsowania podobnymi do klasy cmdlet lub obiektu System.Management.Automation.RuntimeDefinedParameterDictionary . Środowisko uruchomieniowe Windows PowerShell wykorzystuje zwrócony obiekt do dodawania parametrów do cmdletu Copy-Item .

Ten dostawca nie wdraża tej metody. Jednak poniższy kod jest domyślną implementacją System.Management.Automation.Provider.ContainerCmdletProvider.CopyItemDynamicParameters*.

Przykładowy kod

Pełny przykładowy kod można znaleźć w AccessDbProviderSample04 Code Sample.

Budowanie dostawcy Windows PowerShell

Zobacz Jak rejestrować cmdlety, dostawców i aplikacje hostów.

Testowanie dostawcy Windows PowerShell

Gdy Twój dostawca Windows PowerShell zostanie zarejestrowany w Windows PowerShell, możesz go przetestować, uruchamiając obsługiwane cmdlets w wierszu poleceń. Należy pamiętać, że poniższy przykład wychodzi z fikcyjnej bazy danych Access.

  1. Uruchom Get-ChildItem przycisk cmdlet, aby pobrać listę elementów potomnych z tabeli Klienci w bazie Access.

    Get-ChildItem mydb:customers
    

    Pojawia się następujący wynik.

    PSPath        : AccessDB::customers
    PSDrive       : mydb
    PSProvider    : System.Management.Automation.ProviderInfo
    PSIsContainer : True
    Data          : System.Data.DataRow
    Name          : Customers
    RowCount      : 91
    Columns       :
    
  2. Uruchom Get-ChildItem ponownie cmdlet, aby pobrać dane tabeli.

    (Get-ChildItem mydb:customers).Data
    

    Pojawia się następujący wynik.

    TABLE_CAT   : C:\PS\northwind
    TABLE_SCHEM :
    TABLE_NAME  : Customers
    TABLE_TYPE  : TABLE
    REMARKS     :
    
  3. Teraz użyj Get-Item cmdletu, aby pobrać elementy z wiersza 0 w tabeli danych.

    Get-Item mydb:\customers\0
    

    Pojawia się następujący wynik.

    PSPath        : AccessDB::customers\0
    PSDrive       : mydb
    PSProvider    : System.Management.Automation.ProviderInfo
    PSIsContainer : False
    Data          : System.Data.DataRow
    RowNumber     : 0
    
  4. Ponowne użycie Get-Item do pobrania danych dla elementów w wierszu 0.

    (Get-Item mydb:\customers\0).Data
    

    Pojawia się następujący wynik.

    CustomerID   : 1234
    CompanyName  : Fabrikam
    ContactName  : Eric Gruber
    ContactTitle : President
    Address      : 4567 Main Street
    City         : Buffalo
    Region       : NY
    PostalCode   : 98052
    Country      : USA
    Phone        : (425) 555-0100
    Fax          : (425) 555-0101
    
  5. Teraz użyj New-Item cmdletu, aby dodać wiersz do istniejącej tabeli. Parametr Path określa pełną ścieżkę do wiersza i musi wskazywać numer wiersza większy niż istniejąca liczba wierszy w tabeli. Parametr wskazuje, TypeRow aby określić, jaki typ elementu należy dodać. Na koniec Value parametr określa listę wartości kolumn oddzieloną przecinkami dla wiersza.

    New-Item -Path mydb:\Customers\3 -ItemType "Row" -Value "3,CustomerFirstName,CustomerLastName,CustomerEmailAddress,CustomerTitle,CustomerCompany,CustomerPhone, CustomerAddress,CustomerCity,CustomerState,CustomerZip,CustomerCountry"
    
  6. Sprawdź poprawność operacji nowego elementu w następujący sposób.

    PS mydb:\> cd Customers
    PS mydb:\Customers> (Get-Item 3).Data
    

    Pojawia się następujący wynik.

    ID        : 3
    FirstName : Eric
    LastName  : Gruber
    Email     : ericgruber@fabrikam.com
    Title     : President
    Company   : Fabrikam
    WorkPhone : (425) 555-0100
    Address   : 4567 Main Street
    City      : Buffalo
    State     : NY
    Zip       : 98052
    Country   : USA
    

Zobacz też

Tworzenie dostawców Windows PowerShell

Projektowanie dostawcy Windows PowerShell

Implementacja dostawcy Windows PowerShell Element

Implementacja dostawcy nawigacji Windows PowerShell

Jak rejestrować cmdlety, dostawców i aplikacje hostowane

Windows PowerShell SDK

Przewodnik dla programistów Windows PowerShell