Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этом разделе описывается создание поставщика Windows PowerShell, позволяющего пользователю управлять содержимым элементов в хранилище данных. В результате поставщик, который может управлять содержимым элементов, называется поставщиком содержимого Windows PowerShell.
Примечание.
Исходный файл C# (AccessDBSampleProvider06.cs) для этого поставщика можно скачать с помощью пакета средств разработки программного обеспечения Microsoft Windows для Windows Vista и компонентов среды выполнения .NET Framework 3.0. Инструкции по скачиванию см. в статье Установка Windows PowerShell и скачивание пакета SDK для Windows PowerShell. Скачанные исходные файлы доступны в каталоге>примеров PowerShell<. Дополнительные сведения о других реализациях поставщика Windows PowerShell см. в статье Проектированиепоставщика Windows PowerShell.
Определение класса поставщика содержимого Windows PowerShell
Поставщик содержимого Windows PowerShell должен создать класс .NET, поддерживающий интерфейс System.Management.Automation.Provider.IContentCmdletProvider. Ниже приведено определение класса для поставщика элементов, описанного в этом разделе.
[CmdletProvider("AccessDB", ProviderCapabilities.None)]
public class AccessDBProvider : NavigationCmdletProvider, IContentCmdletProvider
Обратите внимание, что в этом определении класса атрибут System.Management.Automation.Provider.КомандлетProviderAttribute включает два параметра. Первый параметр задает понятное имя поставщика, используемого Windows PowerShell. Второй параметр указывает определенные возможности Windows PowerShell, предоставляемые поставщику во время выполнения Windows PowerShell во время обработки команд. Для этого поставщика нет дополнительных возможностей Windows PowerShell.
Определение функциональных возможностей базового класса
Как описано в конструкторепоставщика Windows PowerShell, класс System.Management.Automation.Provider.NavigationCmdletProvider является производным от нескольких других классов, которые предоставили различные функциональные возможности поставщика. Поэтому поставщик содержимого Windows PowerShell обычно определяет все функциональные возможности, предоставляемые этими классами.
Дополнительные сведения о том, как реализовать функциональные возможности для добавления сведений об инициализации для конкретного сеанса и освобождения ресурсов, используемых поставщиком, см. в статье Создание базового поставщика Windows PowerShell. Однако большинство поставщиков, включая описанный здесь поставщик, может использовать реализацию этой функции по умолчанию, предоставляемую Windows PowerShell.
Чтобы получить доступ к хранилищу данных, поставщик должен реализовать методы базового класса System.Management.Automation.Provider.DriveCmdletProvider. Дополнительные сведения о реализации этих методов см. в создании поставщика дисков Windows PowerShell.
Чтобы управлять элементами хранилища данных, такими как получение, настройка и очистка элементов, поставщик должен реализовать методы, предоставляемые базовым классом System.Management.Automation.Provider.ItemCmdletProvider. Дополнительные сведения о реализации этих методов см. в созданиипоставщика элементов Windows PowerShell.
Чтобы работать с хранилищами данных с несколькими уровнями, поставщик должен реализовать методы, предоставляемые базовым классом System.Management.Automation.Provider.ContainerCmdletProvider. Дополнительные сведения о реализации этих методов см. в создании поставщика контейнеров Windows PowerShell.
Чтобы поддерживать рекурсивные команды, вложенные контейнеры и относительные пути, поставщик должен реализовать базовый класс System.Management.Automation.Provider.NavigationCmdletProvider. Кроме того, этот поставщик содержимого Windows PowerShell может подключать интерфейс System.Management.Automation.Provider.IContentCmdletProvider интерфейсом System.Management.Automation.Provider.NavigationCmdletProvider базовым классом и поэтому должен реализовывать методы, предоставляемые этим классом. Дополнительные сведения см. в статье Реализацияпоставщика Windows PowerShell для навигации.
Реализация средства чтения содержимого
Для чтения содержимого из элемента поставщик должен реализовать класс чтения содержимого, производный от System.Management.Automation.Provider.IContentReader. Средство чтения содержимого для этого поставщика позволяет получить доступ к содержимому строки в таблице данных. Класс чтения содержимого определяет метод Read, который извлекает данные из указанной строки и возвращает список, представляющий эти данные, метод Seek, который перемещает читателя содержимого, метод Close, который закрывает средство чтения содержимого и метод Dispose.
public class AccessDBContentReader : IContentReader
{
// A provider instance is required so as to get "content"
private AccessDBProvider provider;
private string path;
private long currentOffset;
internal AccessDBContentReader(string path, AccessDBProvider provider)
{
this.path = path;
this.provider = provider;
}
/// <summary>
/// Read the specified number of rows from the source.
/// </summary>
/// <param name="readCount">The number of items to
/// return.</param>
/// <returns>An array of elements read.</returns>
public IList Read(long readCount)
{
// Read the number of rows specified by readCount and increment
// offset
string tableName;
int rowNumber;
PathType type = provider.GetNamesFromPath(path, out tableName, out rowNumber);
Collection<DatabaseRowInfo> rows =
provider.GetRows(tableName);
Collection<DataRow> results = new Collection<DataRow>();
if (currentOffset < 0 || currentOffset >= rows.Count)
{
return null;
}
int rowsRead = 0;
while (rowsRead < readCount && currentOffset < rows.Count)
{
results.Add(rows[(int)currentOffset].Data);
rowsRead++;
currentOffset++;
}
return results;
} // Read
/// <summary>
/// Moves the content reader specified number of rows from the
/// origin
/// </summary>
/// <param name="offset">Number of rows to offset</param>
/// <param name="origin">Starting row from which to offset</param>
public void Seek(long offset, System.IO.SeekOrigin origin)
{
// get the number of rows in the table which will help in
// calculating current position
string tableName;
int rowNumber;
PathType type = provider.GetNamesFromPath(path, out tableName, out rowNumber);
if (type == PathType.Invalid)
{
throw new ArgumentException("Path specified must represent a table or a row :" + path);
}
if (type == PathType.Table)
{
Collection<DatabaseRowInfo> rows = provider.GetRows(tableName);
int numRows = rows.Count;
if (offset > rows.Count)
{
throw new
ArgumentException(
"Offset cannot be greater than the number of rows available"
);
}
if (origin == System.IO.SeekOrigin.Begin)
{
// starting from Beginning with an index 0, the current offset
// has to be advanced to offset - 1
currentOffset = offset - 1;
}
else if (origin == System.IO.SeekOrigin.End)
{
// starting from the end which is numRows - 1, the current
// offset is so much less than numRows - 1
currentOffset = numRows - 1 - offset;
}
else
{
// calculate from the previous value of current offset
// advancing forward always
currentOffset += offset;
}
} // if (type...
else
{
// for row, the offset will always be set to 0
currentOffset = 0;
}
} // Seek
/// <summary>
/// Closes the content reader, so all members are reset
/// </summary>
public void Close()
{
Dispose();
} // Close
/// <summary>
/// Dispose any resources being used
/// </summary>
public void Dispose()
{
Seek(0, System.IO.SeekOrigin.Begin);
GC.SuppressFinalize(this);
} // Dispose
} // AccessDBContentReader
Реализация модуля записи содержимого
Чтобы записать содержимое в элемент, поставщик должен реализовать класс записи содержимого, производный от System.Management.Automation.Provider.IContentWriter. Класс записи содержимого определяет метод записи, который записывает указанное содержимое строки, метод Seek, который перемещает модуль записи содержимого, метод Close, который закрывает модуль записи содержимого и метод Dispose.
public class AccessDBContentWriter : IContentWriter
{
// A provider instance is required so as to get "content"
private AccessDBProvider provider;
private string path;
private long currentOffset;
internal AccessDBContentWriter(string path, AccessDBProvider provider)
{
this.path = path;
this.provider = provider;
}
/// <summary>
/// Write the specified row contents in the source
/// </summary>
/// <param name="content"> The contents to be written to the source.
/// </param>
/// <returns>An array of elements which were successfully written to
/// the source</returns>
///
public IList Write(IList content)
{
if (content == null)
{
return null;
}
// Get the total number of rows currently available it will
// determine how much to overwrite and how much to append at
// the end
string tableName;
int rowNumber;
PathType type = provider.GetNamesFromPath(path, out tableName, out rowNumber);
if (type == PathType.Table)
{
OdbcDataAdapter da = provider.GetAdapterForTable(tableName);
if (da == null)
{
return null;
}
DataSet ds = provider.GetDataSetForTable(da, tableName);
DataTable table = provider.GetDataTable(ds, tableName);
string[] colValues = (content[0] as string).Split(',');
// set the specified row
DataRow row = table.NewRow();
for (int i = 0; i < colValues.Length; i++)
{
if (!String.IsNullOrEmpty(colValues[i]))
{
row[i] = colValues[i];
}
}
//table.Rows.InsertAt(row, rowNumber);
// Update the table
table.Rows.Add(row);
da.Update(ds, tableName);
}
else
{
throw new InvalidOperationException("Operation not supported. Content can be added only for tables");
}
return null;
} // Write
/// <summary>
/// Moves the content reader specified number of rows from the
/// origin
/// </summary>
/// <param name="offset">Number of rows to offset</param>
/// <param name="origin">Starting row from which to offset</param>
public void Seek(long offset, System.IO.SeekOrigin origin)
{
// get the number of rows in the table which will help in
// calculating current position
string tableName;
int rowNumber;
PathType type = provider.GetNamesFromPath(path, out tableName, out rowNumber);
if (type == PathType.Invalid)
{
throw new ArgumentException("Path specified should represent either a table or a row : " + path);
}
Collection<DatabaseRowInfo> rows =
provider.GetRows(tableName);
int numRows = rows.Count;
if (offset > rows.Count)
{
throw new
ArgumentException(
"Offset cannot be greater than the number of rows available"
);
}
if (origin == System.IO.SeekOrigin.Begin)
{
// starting from Beginning with an index 0, the current offset
// has to be advanced to offset - 1
currentOffset = offset - 1;
}
else if (origin == System.IO.SeekOrigin.End)
{
// starting from the end which is numRows - 1, the current
// offset is so much less than numRows - 1
currentOffset = numRows - 1 - offset;
}
else
{
// calculate from the previous value of current offset
// advancing forward always
currentOffset += offset;
}
} // Seek
/// <summary>
/// Closes the content reader, so all members are reset
/// </summary>
public void Close()
{
Dispose();
} // Close
/// <summary>
/// Dispose any resources being used
/// </summary>
public void Dispose()
{
Seek(0, System.IO.SeekOrigin.Begin);
GC.SuppressFinalize(this);
} // Dispose
} // AccessDBContentWriter
Получение средства чтения содержимого
Чтобы получить содержимое из элемента, поставщик должен реализовать System.Management.Automation.Provider.IContentCmdletProvider.GetContentReader* для поддержки командлета Get-Content
. Этот метод возвращает средство чтения содержимого для элемента, расположенного по указанному пути. Затем объект чтения можно открыть для чтения содержимого.
Ниже приведена реализация System.Management.Automation.Provider.IContentCmdletProvider.GetContentReader* для этого метода для этого поставщика.
public IContentReader GetContentReader(string path)
{
string tableName;
int rowNumber;
PathType type = GetNamesFromPath(path, out tableName, out rowNumber);
if (type == PathType.Invalid)
{
ThrowTerminatingInvalidPathException(path);
}
else if (type == PathType.Row)
{
throw new InvalidOperationException("contents can be obtained only for tables");
}
return new AccessDBContentReader(path, this);
} // GetContentReader
public IContentReader GetContentReader(string path)
{
string tableName;
int rowNumber;
PathType type = GetNamesFromPath(path, out tableName, out rowNumber);
if (type == PathType.Invalid)
{
ThrowTerminatingInvalidPathException(path);
}
else if (type == PathType.Row)
{
throw new InvalidOperationException("contents can be obtained only for tables");
}
return new AccessDBContentReader(path, this);
} // GetContentReader
Сведения о реализации GetContentReader
Следующие условия могут применяться к реализации System.Management.Automation.Provider.IContentCmdletProvider.GetContentReader*:
При определении класса поставщика содержимого Windows PowerShell может объявлять возможности поставщика расширений, фильтров, включения или исключения из перечисления System.Management.Automation.Provider.ProviderCapabilities. В этих случаях реализация метода System.Management.Automation.Provider.IContentCmdletProvider.GetContentReader* должна гарантировать, что путь, переданный методу, соответствует требованиям указанных возможностей. Для этого метод должен получить доступ к соответствующему свойству, например к свойствам System.Management.Automation.Provider.КомандлетProvider.Exclude* и System.Management.Automation.Provider.КомандлетProvider.Include*.
По умолчанию переопределения этого метода не должны извлекать средство чтения для объектов, скрытых от пользователя, если свойство System.Management.Automation.Provider.CmdletProvider.Force* имеет значение
true
. Ошибка должна быть записана, если путь представляет элемент, скрытый от пользователя, и System.Management.Automation.Provider.КомандлетProvider.Force* имеет значениеfalse
.
Присоединение динамических параметров к командлету Get-Content
Командлет Get-Content
может потребовать дополнительных параметров, которые задаются динамически во время выполнения. Чтобы предоставить эти динамические параметры, поставщик содержимого Windows PowerShell должен реализовать метод System.Management.Automation.Provider.IContentCmdletProvider.GetContentReaderdynamicparameters*. Этот метод извлекает динамические параметры для элемента по указанному пути и возвращает объект, имеющий свойства и поля с атрибутами синтаксического анализа, аналогичные классу командлета или объекту System.Management.Automation.RuntimeDefinedParameterDictionary. Среда выполнения Windows PowerShell использует возвращенный объект для добавления параметров в командлет.
Этот поставщик контейнеров Windows PowerShell не реализует этот метод. Однако следующий код является реализацией этого метода по умолчанию.
public object GetContentReaderDynamicParameters(string path)
{
return null;
}
public object GetContentReaderDynamicParameters(string path)
{
return null;
}
Получение записи содержимого
Чтобы записать содержимое в элемент, поставщик должен реализовать System.Management.Automation.Provider.IContentCmdletProvider.GetContentWriter* для поддержки командлетов Set-Content
и Add-Content
. Этот метод возвращает средство записи содержимого для элемента, расположенного по указанному пути.
Ниже приведена реализация System.Management.Automation.Provider.IContentCmdletProvider.GetContentWriter* для этого метода.
public IContentWriter GetContentWriter(string path)
{
string tableName;
int rowNumber;
PathType type = GetNamesFromPath(path, out tableName, out rowNumber);
if (type == PathType.Invalid)
{
ThrowTerminatingInvalidPathException(path);
}
else if (type == PathType.Row)
{
throw new InvalidOperationException("contents can be added only to tables");
}
return new AccessDBContentWriter(path, this);
}
public IContentWriter GetContentWriter(string path)
{
string tableName;
int rowNumber;
PathType type = GetNamesFromPath(path, out tableName, out rowNumber);
if (type == PathType.Invalid)
{
ThrowTerminatingInvalidPathException(path);
}
else if (type == PathType.Row)
{
throw new InvalidOperationException("contents can be added only to tables");
}
return new AccessDBContentWriter(path, this);
}
Сведения о реализации GetContentWriter
Следующие условия могут применяться к реализации System.Management.Automation.Provider.IContentCmdletProvider.GetContentWriter*:
При определении класса поставщика содержимого Windows PowerShell может объявлять возможности поставщика расширений, фильтров, включения или исключения из перечисления System.Management.Automation.Provider.ProviderCapabilities. В этих случаях реализация метода System.Management.Automation.Provider.IContentCmdletProvider.GetContentWriter* должна гарантировать, что путь, переданный методу, соответствует требованиям указанных возможностей. Для этого метод должен получить доступ к соответствующему свойству, например к свойствам System.Management.Automation.Provider.КомандлетProvider.Exclude* и System.Management.Automation.Provider.КомандлетProvider.Include*.
По умолчанию переопределения этого метода не должны извлекать запись для объектов, скрытых от пользователя, если для свойства System.Management.Automation.Provider.CmdletProvider.Force* задано значение
true
. Ошибка должна быть записана, если путь представляет элемент, скрытый от пользователя, и System.Management.Automation.Provider.КомандлетProvider.Force* имеет значениеfalse
.
Присоединение динамических параметров к командлетам Add-Content и Set-Content
Для командлетов Add-Content
и Set-Content
могут потребоваться дополнительные динамические параметры, добавленные в среду выполнения. Чтобы предоставить эти динамические параметры, поставщик содержимого Windows PowerShell должен реализовать метод System.Management.Automation.Provider.IContentCmdletProvider.GetContentWriterDynamicParameters* для обработки этих параметров. Этот метод извлекает динамические параметры для элемента по указанному пути и возвращает объект, имеющий свойства и поля с атрибутами синтаксического анализа, аналогичные классу командлета или объекту System.Management.Automation.RuntimeDefinedParameterDictionary. Среда выполнения Windows PowerShell использует возвращенный объект для добавления параметров в командлеты.
Этот поставщик контейнеров Windows PowerShell не реализует этот метод. Однако следующий код является реализацией этого метода по умолчанию.
public object GetContentWriterDynamicParameters(string path)
{
return null;
}
Очистка содержимого
Поставщик содержимого реализует метод System.Management.Automation.Provider.IContentCmdletProvider.ClearContent* в поддержку командлета Clear-Content
. Этот метод удаляет содержимое элемента по указанному пути, но оставляет элемент нетронутым.
Ниже приведена реализация метода System.Management.Automation.Provider.IContentCmdletProvider.ClearContent* для этого поставщика.
public void ClearContent(string path)
{
string tableName;
int rowNumber;
PathType type = GetNamesFromPath(path, out tableName, out rowNumber);
if (type != PathType.Table)
{
WriteError(new ErrorRecord(
new InvalidOperationException("Operation not supported. Content can be cleared only for table"),
"NotValidRow", ErrorCategory.InvalidArgument,
path));
return;
}
OdbcDataAdapter da = GetAdapterForTable(tableName);
if (da == null)
{
return;
}
DataSet ds = GetDataSetForTable(da, tableName);
DataTable table = GetDataTable(ds, tableName);
// Clear contents at the specified location
for (int i = 0; i < table.Rows.Count; i++)
{
table.Rows[i].Delete();
}
if (ShouldProcess(path, "ClearContent"))
{
da.Update(ds, tableName);
}
} // ClearContent
Сведения о реализации ClearContent
Следующие условия могут применяться к реализации System.Management.Automation.Provider.IContentCmdletProvider.ClearContent*:
При определении класса поставщика содержимого Windows PowerShell может объявлять возможности поставщика расширений, фильтров, включения или исключения из перечисления System.Management.Automation.Provider.ProviderCapabilities. В таких случаях реализация метода System.Management.Automation.Provider.IContentCmdletProvider.ClearContent* должна гарантировать, что путь, передаваемый методу, соответствует требованиям указанных возможностей. Для этого метод должен получить доступ к соответствующему свойству, например к свойствам System.Management.Automation.Provider.КомандлетProvider.Exclude* и System.Management.Automation.Provider.КомандлетProvider.Include*.
По умолчанию переопределения этого метода не должны очищать содержимое объектов, скрытых от пользователя, если свойство System.Management.Automation.Provider.КомандлетProvider.Force* имеет значение
true
. Ошибка должна быть записана, если путь представляет элемент, скрытый от пользователя, и System.Management.Automation.Provider.КомандлетProvider.Force* имеет значениеfalse
.Реализация метода System.Management.Automation.Provider.IContentCmdletProvider.ClearContent* должна вызывать System.Management.Automation.Provider.КомандлетProvider.ShouldProcess перед внесением изменений в хранилище данных. Этот метод используется для подтверждения выполнения операции при изменении хранилища данных, например очистки содержимого. Метод System.Management.Automation.Provider.КомандлетProvider.ShouldProcess отправляет имя ресурса, который нужно изменить пользователю, при этом среда выполнения Windows PowerShell обрабатывает все параметры командной строки или переменные предпочтения при определении того, что нужно отобразить.
После вызова System.Management.Automation.Provider.КомандлетProvider.ShouldProcess возвращает
true
, метод System.Management.Automation.Provider.IContentCmdletProvider.ClearContent* должен вызывать метод System.Management.Automation.Provider.КомандлетProvider.ShouldContinue. Этот метод отправляет пользователю сообщение, чтобы разрешить обратную связь, чтобы проверить, следует ли продолжить операцию. Вызов System.Management.Automation.Provider.КомандлетProvider.ShouldContinue позволяет дополнительно проверить потенциально опасные изменения системы.
Присоединение динамических параметров к командлету Clear-Content
Командлет Clear-Content
может потребовать дополнительных динамических параметров, добавленных во время выполнения. Чтобы предоставить эти динамические параметры, поставщик содержимого Windows PowerShell должен реализовать метод System.Management.Automation.Provider.IContentCmdletProvider.ClearContentDynamicParameters* для обработки этих параметров. Этот метод извлекает параметры элемента по указанному пути. Этот метод извлекает динамические параметры для элемента по указанному пути и возвращает объект, имеющий свойства и поля с атрибутами синтаксического анализа, аналогичные классу командлета или объекту System.Management.Automation.RuntimeDefinedParameterDictionary. Среда выполнения Windows PowerShell использует возвращенный объект для добавления параметров в командлет.
Этот поставщик контейнеров Windows PowerShell не реализует этот метод. Однако следующий код является реализацией этого метода по умолчанию.
public object ClearContentDynamicParameters(string path)
{
return null;
}
public object ClearContentDynamicParameters(string path)
{
return null;
}
Пример кода
Полный пример кода см. в примере кода AccessDbProviderSample06.
Определение типов объектов и форматирования
При написании поставщика может потребоваться добавить элементы в существующие объекты или определить новые объекты. После этого необходимо создать файл типов, который Windows PowerShell может использовать для идентификации членов объекта и файла форматирования, определяющего способ отображения объекта. Дополнительные сведения см. в разделе Расширения типов объектов и форматирования.
Создание поставщика Windows PowerShell
См. , как зарегистрировать командлеты, поставщики и хост-приложения.
Тестирование поставщика Windows PowerShell
Если поставщик Windows PowerShell зарегистрирован в Windows PowerShell, его можно протестировать, выполнив поддерживаемые командлеты в командной строке. Например, проверьте пример поставщика контента.
Используйте командлет Get-Content
, чтобы получить содержимое указанного элемента в таблице базы данных по пути, указанному параметром Path
. Параметр ReadCount
указывает количество элементов для чтения определенного средства чтения содержимого (по умолчанию 1). С помощью следующей записи команды командлет извлекает две строки (элементы) из таблицы и отображает их содержимое. Обратите внимание, что в следующем примере выходных данных используется фиктивная база данных Access.
Get-Content -Path mydb:\Customers -ReadCount 2
ID : 1
FirstName : Eric
LastName : Gruber
Email : [email protected]
Title : President
Company : Fabrikam
WorkPhone : (425) 555-0100
Address : 4567 Main Street
City : Buffalo
State : NY
Zip : 98052
Country : USA
ID : 2
FirstName : Eva
LastName : Corets
Email : [email protected]
Title : Sales Representative
Company : Coho Winery
WorkPhone : (360) 555-0100
Address : 8910 Main Street
City : Cabmerlot
State : WA
Zip : 98089
Country : USA
См. также
создание поставщиков Windows PowerShell
проектирование поставщика Windows PowerShell
расширения типов объектов и форматирования
Реализация поставщика навигации Windows PowerShell
Регистрация командлетов, поставщиков и ведущих приложений
пакета SDK для Windows PowerShell
руководство программиста Windows PowerShell
PowerShell