Поделиться через


Создание провайдера контейнеров для Windows PowerShell

В этой теме описывается, как создать провайдера Windows PowerShell, который может работать с многоуровневыми хранилищами данных. Для такого типа хранилища хранилища верхний уровень хранилища содержит корневые элементы, а каждый следующий уровень называется узлом дочерних элементов. Позволяя пользователю работать с этими дочерними узлами, он может взаимодействовать иерархически через хранилище данных.

Провайдеры, способные работать с многоуровневыми хранилищами данных, называются провайдерами контейнеров Windows PowerShell. Однако имейте в виду, что провайдер контейнеров Windows PowerShell можно использовать только при наличии одного контейнера (без вложенных контейнеров) с элементами. Если есть вложенные контейнеры, то необходимо реализовать навигационного провайдера Windows PowerShell. Для получения дополнительной информации о внедрении навигационного провайдера Windows PowerShell см. раздел «Создание провайдера навигации Windows PowerShell».

Замечание

Вы можете скачать исходный файл на C# (AccessDBSampleProvider04.cs) для этого провайдера с помощью Microsoft Windows Software Development Kit for Windows Vista и компонентов выполнения .NET Framework 3.0. Инструкции по скачиванию смотрите в разделе «Как установить Windows PowerShell» и «Скачать Windows PowerShell SDK». Загруженные исходные файлы доступны в каталоге <PowerShell Samples> . Для получения дополнительной информации о других реализациях провайдеров Windows PowerShell см. раздел «Проектирование вашего провайдера Windows PowerShell».

Поставщик контейнеров Windows PowerShell, описанный здесь, определяет базу данных как единый контейнер, при этом таблицы и строки базы определяются как элементы контейнера.

Caution

Имейте в виду, что эта конструкция предполагает наличие базы данных с полем с идентификатором имени, и тип поля — LongInwhole число.

Определение класса провайдера контейнера Windows PowerShell

Провайдер контейнера Windows PowerShell должен определить класс .NET, который происходит из базового класса System.Management.Automation.Provider.ContainerCmdletProvider . Вот определение класса для провайдера контейнеров Windows PowerShell, описанного в этом разделе.

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

Обратите внимание, что в этом определении класса атрибут System.Management.Automation.Provider.CmdletProviderAttribute включает два параметра. Первый параметр задаёт удобное для пользователя имя провайдера, используемое Windows PowerShell. Второй параметр определяет специфические для Windows PowerShell возможности, которые провайдер открывает в процессе выполнения Windows PowerShell во время обработки команд. Для этого провайдера нет добавленных специфических возможностей Windows PowerShell.

Определение базовой функциональности

Как описано в статье «Проектирование вашего Windows PowerShell Provider», класс System.Management.Automation.Provider.ContainerCmdletProvider происходит из нескольких других классов, предоставлявших разные функциональности провайдеров. Таким образом, поставщик контейнеров Windows PowerShell должен определить все функции, предоставляемые этими классами.

Чтобы реализовать функционал добавления информации о инициализации, специфичной для сессии, и для выпуска ресурсов, используемых провайдером, см. раздел «Создание базового провайдера Windows PowerShell». Однако большинство провайдеров (включая описанного здесь провайдера) могут использовать стандартную реализацию этой функции, предоставляемую Windows PowerShell.

Чтобы получить доступ к хранилищу данных, провайдер должен реализовать методы базового класса System.Management.Automation.Provider.DriveCmdletProvider . Для получения дополнительной информации о внедрении этих методов см. раздел «Создание провайдера дисков Windows PowerShell».

Для обработки элементов хранилища данных, таких как получение, установка и очистка элементов, провайдер должен реализовать методы, предоставляемые базовым классом System.Management.Automation.Provider.ItemCmdletProvider . Для получения дополнительной информации о реализации этих методов см. раздел «Создание поставщика элементов Windows PowerShell».

Извлечение дочерних предметов

Чтобы получить дочерний элемент, провайдер контейнера Windows PowerShell должен переопределить метод System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItems* для поддержки вызовов из Get-ChildItem cmdlet. Этот метод извлекает дочерние элементы из хранилища данных и записывает их в конвейер как объекты. Если recurse параметр cmdlet указан, метод получает все потомки независимо от их уровня. Если recurse параметр не указан, метод извлекает только один уровень дочерних элементов.

Вот реализация метода System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItems* для этого провайдера. Обратите внимание, что этот метод извлекает дочерние элементы во всех таблицах базы данных, когда путь указывает на базу данных доступа, и извлекает дочерние элементы из строк этой таблицы, если путь указывает на таблицу данных.

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

Что стоит помнить о внедрении GetChildItems

К вашей реализации System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItems* могут применяться следующие условия:

Прикрепление динамических параметров к командоустройству Get-ChildItem

Иногда Get-ChildItem cmdlet, вызывающий System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItems* , требует дополнительных параметров, которые динамически задаются во время выполнения. Для предоставления этих динамических параметров провайдер контейнеров Windows PowerShell должен реализовать метод System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItemsDynamicParameters* . Этот метод извлекает динамические параметры для элемента по указанному пути и возвращает объект с свойствами и полями с атрибутами разбора, похожими на класс cmdlet или объект System.Management.Automation.RuntimeDefinedParameterDictionary . Runtime Windows PowerShell использует возвращённый объект для добавления параметров в Get-ChildItem cmdlet.

Этот провайдер контейнеров Windows PowerShell не реализует этот метод. Однако следующий код является стандартной реализацией этого метода.

Получение имён дочерних элементов

Чтобы получить имена дочерних элементов, провайдер контейнера Windows PowerShell должен переопределить метод System.Management.Automation.Provider.ContainerCmdletProvider.GetChildNames* для поддержки вызовов из Get-ChildItem cmdlet при указании его Name параметра. Этот метод получает имена дочерних элементов для указанного пути или названия дочерних элементов для всех контейнеров, если returnAllContainers параметр cmdlet указан. Имя для ребёнка — это листовая часть дорожки. Например, дочернее имя пути C:\windows\system32\abc.dll — «abc.dll». Дочернее имя каталога C:\windows\system32 — «system32».

Вот реализация метода System.Management.Automation.Provider.ContainerCmdletProvider.GetChildNames* для этого провайдера. Обратите внимание, что метод получает имена таблиц, если указанный путь указывает на базу данных доступа (диск), а также номера строк, если путь указывает на таблицу.

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

Что нужно помнить о внедрении GetChildNames

К вашей реализации System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItems* могут применяться следующие условия:

Прикрепление динамических параметров к Get-ChildItem cmdlet (Name)

Иногда cmdlet Get-ChildItem (с параметром Name ) требует дополнительных параметров, которые задаются динамически во время выполнения. Для предоставления этих динамических параметров провайдер контейнеров Windows PowerShell должен реализовать метод System.Management.Automation.Provider.ContainerCmdletProvider.GetChildNamesDynamicParameters* . Этот метод извлекает динамические параметры элемента по указанному пути и возвращает объект с свойствами и полями с атрибутами разбора, похожими на класс cmdlet или объект System.Management.Automation.RuntimeDefinedParameterDictionary . Runtime Windows PowerShell использует возвращённый объект для добавления параметров в Get-ChildItem cmdlet.

Этот провайдер не реализует этот метод. Однако следующий код является стандартной реализацией этого метода.

Переименование предметов

Для переименования элемента провайдер контейнера Windows PowerShell должен переопределить метод System.Management.Automation.Provider.ContainerCmdletProvider.RenameItem* для поддержки вызовов из cmdlet Rename-Item . Этот метод меняет имя элемента на указанном пути на новое, предоставленное имя. Новое имя всегда должно быть относительно родительского элемента (контейнера).

Этот провайдер не отменяет метод System.Management.Automation.Provider.ContainerCmdletProvider.RenameItem* . Однако ниже приведена стандартная реализация.

Что нужно помнить о внедрении RenameItem

К вашей реализации System.Management.Automation.Provider.ContainerCmdletProvider.RenameItem* могут применяться следующие условия:

Прикрепление динамических параметров к командоустройству Rename-Item

Иногда cmdlet Rename-Item требует дополнительных параметров, которые динамически задаются во время выполнения. Для предоставления этих динамических параметров провайдер контейнеров Windows PowerShell должен реализовать метод System.Management.Automation.Provider.ContainerCmdletProvider.RenameItemDynamicParameters* . Этот метод извлекает параметры элемента по указанному пути и возвращает объект с свойствами и полями с атрибутами разбора, похожими на класс cmdlet или объект System.Management.Automation.RuntimeDefinedParameterDictionary . Runtime Windows PowerShell использует возвращённый объект для добавления параметров в Rename-Item cmdlet.

Этот контейнерный провайдер не реализует этот метод. Однако следующий код является стандартной реализацией этого метода.

Создание новых предметов

Для создания новых элементов контейнерный провайдер должен реализовать метод System.Management.Automation.Provider.ContainerCmdletProvider.NewItem* для поддержки вызовов из New-Item cmdlet. Этот метод создаёт элемент данных, расположенный на указанном пути. Параметр type cmdlet содержит тип, определённый провайдером для нового элемента. Например, провайдер FileSystem использует type параметр со значением «file» или «directory». newItemValue Параметр cmdlet указывает значение, специфичное для провайдера, для нового элемента.

Вот реализация метода System.Management.Automation.Provider.ContainerCmdletProvider.NewItem* для этого провайдера.

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];

Что нужно помнить при внедрении NewItem

К вашей реализации System.Management.Automation.Provider.ContainerCmdletProvider.NewItem* могут применяться следующие условия:

Прикрепление динамических параметров к командоустройству New-Item

Иногда cmdlet New-Item требует дополнительных параметров, которые динамически задаются во время выполнения. Для предоставления этих динамических параметров контейнерный провайдер должен реализовать метод System.Management.Automation.Provider.ContainerCmdletProvider.NewItemDynamicParameters* . Этот метод извлекает параметры элемента по указанному пути и возвращает объект с свойствами и полями с атрибутами разбора, похожими на класс cmdlet или объект System.Management.Automation.RuntimeDefinedParameterDictionary . Runtime Windows PowerShell использует возвращённый объект для добавления параметров в New-Item cmdlet.

Этот провайдер не реализует этот метод. Однако следующий код является стандартной реализацией этого метода.

Удаление предметов

Для удаления элементов провайдер Windows PowerShell должен переопределить метод System.Management.Automation.Provider.ContainerCmdletProvider.RemoveItem* для поддержки вызовов из Remove-Item cmdlet. Этот метод удаляет элемент из хранилища данных на указанном пути. Если recurse параметр Remove-Item cmdlet установлен на true, метод удаляет все дочерние элементы независимо от их уровня. Если параметр установлен в false, метод удаляет только один элемент на указанном пути.

Этот провайдер не поддерживает удаление предметов. Однако следующий код является стандартной реализацией System.Management.Automation.Provider.ContainerCmdletProvider.RemoveItem*.

Что нужно помнить при внедрении RemoveItem

К вашей реализации System.Management.Automation.Provider.ContainerCmdletProvider.NewItem* могут применяться следующие условия:

Прикрепление динамических параметров к командоустройству Remove-Item

Иногда cmdlet Remove-Item требует дополнительных параметров, которые динамически задаются во время выполнения. Для предоставления этих динамических параметров контейнерный провайдер должен реализовать метод System.Management.Automation.Provider.ContainerCmdletProvider.RemoveItemDynamicParameters* для обработки этих параметров. Этот метод извлекает динамические параметры элемента по указанному пути и возвращает объект с свойствами и полями с атрибутами разбора, похожими на класс cmdlet или объект System.Management.Automation.RuntimeDefinedParameterDictionary . Runtime Windows PowerShell использует возвращённый объект для добавления параметров в Remove-Item cmdlet.

Этот контейнерный провайдер не реализует этот метод. Однако следующий код является стандартной реализацией System.Management.Automation.Provider.ContainerCmdletProvider.RemoveItemDynamicParameters*.

Запросы для дочерних элементов

Чтобы проверить, существуют ли дочерние элементы на указанном пути, провайдер контейнеров Windows PowerShell должен переопределить метод System.Management.Automation.Provider.ContainerCmdletProvider.HasChildItems* . Этот метод возвращается true , если у предмета есть почерние черти, и false в других случаях. Для нулевого или пустого пути метод считает любые элементы в хранилище данных дочерними и возвращает true.

Вот переопределение для метода System.Management.Automation.Provider.ContainerCmdletProvider.HasChildItems* . Если с помощью вспомогательного метода ChunkPath создаётся более двух частей пути, метод возвращает false, поскольку определены только контейнер базы данных и контейнер таблицы. Для получения дополнительной информации об этом вспомогательном методе см. метод ChunkPath обсуждается в статье «Создание провайдера элементов Windows PowerShell».

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

return results;

Что нужно помнить о внедрении HasChildItems

К вашей реализации System.Management.Automation.Provider.ContainerCmdletProvider.HasChildItems* могут применяться следующие условия:

  • Если провайдер контейнера открывает корень с интересными точками монтирования, реализация метода System.Management.Automation.Provider.ContainerCmdletProvider.HasChildItems* должна возвращаться true при передаче нулевой или пустой строки для пути.

Копирование предметов

Для копирования элементов поставщик контейнера должен реализовать метод System.Management.Automation.Provider.ContainerCmdletProvider.CopyItem для поддержки вызовов из Copy-Item cmdlet. Этот метод копирует элемент данных из места, указанного path параметром cmdlet, в указанное параметром copyPath . Если recurse параметр указан, метод копирует все подконтейнеры. Если параметр не указан, метод копирует только один уровень элементов.

Этот провайдер не реализует этот метод. Однако следующий код является стандартной реализацией System.Management.Automation.Provider.ContainerCmdletProvider.CopyItem.

Что нужно помнить о внедрении CopyItem

Следующие условия могут применяться к вашей реализации System.Management.Automation.Provider.ContainerCmdletProvider.CopyItem:

Прикрепление динамических параметров к командоустройству Copy-Item

Иногда cmdlet Copy-Item требует дополнительных параметров, которые динамически задаются во время выполнения. Для предоставления этих динамических параметров поставщик контейнеров Windows PowerShell должен реализовать метод System.Management.Automation.Provider.ContainerCmdletProvider.CopyItemDynamicParameters* для обработки этих параметров. Этот метод извлекает параметры элемента по указанному пути и возвращает объект с свойствами и полями с атрибутами разбора, похожими на класс cmdlet или объект System.Management.Automation.RuntimeDefinedParameterDictionary . Runtime Windows PowerShell использует возвращённый объект для добавления параметров в Copy-Item cmdlet.

Этот провайдер не реализует этот метод. Однако следующий код является стандартной реализацией System.Management.Automation.Provider.ContainerCmdletProvider.CopyItemDynamicParameters*.

Пример кода

Полный пример кода см. AccessDbProviderSample04 Code Sample.

Создание провайдера Windows PowerShell

Посмотрите, как зарегистрировать cmdlet, провайдеров и хост-приложения.

Тестирование провайдера Windows PowerShell

Когда ваш провайдер Windows PowerShell зарегистрирован в Windows PowerShell, вы можете проверить это, запустив поддерживаемые cmdlets в командной строке. Обратите внимание, что следующий пример вывода использует фиктивную базу данных Access.

  1. Запустите Get-ChildItem cmdlet, чтобы получить список дочерних элементов из таблицы Customers в базе данных Access.

    Get-ChildItem mydb:customers
    

    Ниже приводится результат.

    PSPath        : AccessDB::customers
    PSDrive       : mydb
    PSProvider    : System.Management.Automation.ProviderInfo
    PSIsContainer : True
    Data          : System.Data.DataRow
    Name          : Customers
    RowCount      : 91
    Columns       :
    
  2. Запустите Get-ChildItem cmdlet снова, чтобы получить данные таблицы.

    (Get-ChildItem mydb:customers).Data
    

    Ниже приводится результат.

    TABLE_CAT   : C:\PS\northwind
    TABLE_SCHEM :
    TABLE_NAME  : Customers
    TABLE_TYPE  : TABLE
    REMARKS     :
    
  3. Теперь используйте Get-Item cmdlet, чтобы получить элементы в строке 0 в таблице данных.

    Get-Item mydb:\customers\0
    

    Ниже приводится результат.

    PSPath        : AccessDB::customers\0
    PSDrive       : mydb
    PSProvider    : System.Management.Automation.ProviderInfo
    PSIsContainer : False
    Data          : System.Data.DataRow
    RowNumber     : 0
    
  4. Повторное использование Get-Item для получения данных для элементов в строке 0.

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

    Ниже приводится результат.

    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. Теперь используйте New-Item cmdlet, чтобы добавить строку в существующую таблицу. Path Параметр задаёт полный путь к строке и должен указывать номер строки, который превышает существующее количество строк в таблице. Параметр Type указывает Row на то, какой тип элемента нужно добавить. Наконец, Value параметр задаёт список значений столбцов, разделённый запятой, для строки.

    New-Item -Path mydb:\Customers\3 -ItemType "Row" -Value "3,CustomerFirstName,CustomerLastName,CustomerEmailAddress,CustomerTitle,CustomerCompany,CustomerPhone, CustomerAddress,CustomerCity,CustomerState,CustomerZip,CustomerCountry"
    
  6. Проверьте корректность операции нового элемента следующим образом.

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

    Ниже приводится результат.

    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
    

См. также

Создание провайдеров Windows PowerShell

Проектирование вашего провайдера Windows PowerShell

Реализация поставщика PowerShell для Windows

Реализация навигационного провайдера Windows PowerShell

Как зарегистрировать cmdlet, провайдеров и хост-приложений

Windows PowerShell SDK

Руководство программиста Windows PowerShell