Заметка
Доступ к этой странице требует авторизации. Вы можете попробовать войти в систему или изменить каталог.
Доступ к этой странице требует авторизации. Вы можете попробовать сменить директорию.
В этой теме описывается, как создать провайдера Windows PowerShell, который позволяет пользователю управлять содержимым элементов в хранилище данных. В результате провайдер, способный управлять содержимым элементов, называется поставщиком контента Windows PowerShell.
Замечание
Вы можете скачать исходный файл C# (AccessDBSampleProvider06.cs) для этого провайдера с помощью Microsoft Windows Software Development Kit for Windows Vista и .NET Framework 3.0 Runtime Components. Инструкции по скачиванию смотрите в разделе «Как установить Windows PowerShell» и «Скачать Windows PowerShell SDK». Загруженные исходные файлы доступны в каталоге <PowerShell Samples> . Для получения дополнительной информации о других реализациях провайдеров 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.CmdletProviderAttribute включает два параметра. Первый параметр задаёт удобное для пользователя имя провайдера, используемое Windows PowerShell. Второй параметр определяет специфические для Windows PowerShell возможности, которые провайдер открывает в процессе выполнения Windows PowerShell во время обработки команд. Для этого провайдера нет дополнительных возможностей, специфичных для Windows PowerShell.
Определить функциональность базового класса
Как описано в статье «Проектируйте ваш Windows PowerShell Provider», класс 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 Provider».
Реализация считывателя контента
Чтобы читать контент из элемента, провайдер должен реализовать класс читателя контента, производный из System.Management.Automation.Provider.IContentReader. Считыватель контента этого провайдера позволяет получать доступ к содержимому строки в таблице данных. Класс читателя контента определяет метод чтения , который извлекает данные из указанной строки и возвращает список, представляющий эти данные, метод See , перемещающий читатель контента, метод Close , закрывающий читатель контента, и метод Disposed .
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. Класс контент-райтера определяет метод Write , который записывает указанный контент строки, метод Search , который перемещает автора контента, метод Close , который закрывает автора контента, и метод Disposed .
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
Получение Content Reader
Чтобы получить контент из элемента, провайдер должен реализовать System.Management.Automation.Provider.IContentCmdletProvider.GetContentReader* для поддержки cmdlet 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 может объявить возможности провайдера ExpandWildcards, Filter, Include или Exclude из перечисления System.Management.Automation.Provider.ProviderCapabilities . В таких случаях реализация метода System.Management.Automation.Provider.IContentCmdletProvider.GetContentReader* должна гарантировать, что путь, переданный методу, соответствует требованиям указанных возможностей. Для этого метод должен получить доступ к соответствующим свойствам, например, к свойствам System.Management.Automation.Provider.CmdletProvider.Exclude* и свойствам System.Management.Automation.Provider.CmdletProvider.Include* .
По умолчанию переопределители этого метода не должны получать считыватель для объектов, скрытых от пользователя, если только свойство System.Management.Automation.Provider.CmdletProvider.Force* не установлено на
true. Ошибка должна быть написана, если путь представляет элемент, скрытый от пользователя, и System.Management.Automation.Provider.Provider.CmdletProvider.Force* установлен вfalse.
Прикрепление динамических параметров к командоустройству Get-Content
Cmdlet Get-Content может потребовать дополнительных параметров, которые динамически задаются во время выполнения. Для предоставления этих динамических параметров поставщик контента Windows PowerShell должен реализовать метод System.Management.Automation.Provider.IContentCmdletProvider.GetContentReaderdynamicparameters* . Этот метод извлекает динамические параметры для элемента по указанному пути и возвращает объект с свойствами и полями с атрибутами разбора, похожими на класс cmdlet или объект System.Management.Automation.RuntimeDefinedParameterDictionary . Runtime Windows PowerShell использует возвращённый объект для добавления параметров в cmdlet.
Этот провайдер контейнеров Windows PowerShell не реализует этот метод. Однако следующий код является стандартной реализацией этого метода.
public object GetContentReaderDynamicParameters(string path)
{
return null;
}
public object GetContentReaderDynamicParameters(string path)
{
return null;
}
Получение автора контента
Чтобы записать контент в элемент, провайдер должен реализовать System.Management.Automation.Provider.IContentCmdletProvider.GetContentWriter* для поддержки Set-Content cmdlet 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 может объявить возможности провайдера ExpandWildcards, Filter, Include или Exclude из перечисления System.Management.Automation.Provider.ProviderCapabilities . В таких случаях реализация метода System.Management.Automation.Provider.IContentCmdletProvider.GetContentWriter* должна гарантировать, что путь, переданный методу, соответствует требованиям указанных возможностей. Для этого метод должен получить доступ к соответствующим свойствам, например, к свойствам System.Management.Automation.Provider.CmdletProvider.Exclude* и свойствам System.Management.Automation.Provider.CmdletProvider.Include* .
По умолчанию переопределения этого метода не должны получать запись для объектов, скрытых от пользователя, если только свойство System.Management.Automation.Provider.CmdletProvider.Force* не установлено на
true. Ошибка должна быть написана, если путь представляет элемент, скрытый от пользователя, и System.Management.Automation.Provider.Provider.CmdletProvider.Force* установлен вfalse.
Прикрепление динамических параметров к командорам Add-Content и Set-Content
Cmdlets Add-Content и Set-Content могут требовать дополнительных динамических параметров, которые добавляются в время выполнения. Для предоставления этих динамических параметров поставщик контента Windows PowerShell должен реализовать метод System.Management.Automation.Provider.IContentCmdletProvider.GetContentWriterDynamicParameters* для обработки этих параметров. Этот метод извлекает динамические параметры для элемента по указанному пути и возвращает объект с свойствами и полями с атрибутами разбора, похожими на класс cmdlet или объект System.Management.Automation.RuntimeDefinedParameterDictionary . В процессе выполнения Windows PowerShell используется возвращённый объект для добавления параметров в cmdlet.
Этот провайдер контейнеров Windows PowerShell не реализует этот метод. Однако следующий код является стандартной реализацией этого метода.
public object GetContentWriterDynamicParameters(string path)
{
return null;
}
Очистка контента
Ваш поставщик контента реализует метод System.Management.Automation.Provider.IContentCmdletProvider.ClearContent* в поддержку Clear-Content cmdlet. Этот метод удаляет содержимое элемента по указанному пути, но оставляет элемент нетронутым.
Вот реализация метода 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 может объявить возможности провайдера ExpandWildcards, Filter, Include или Exclude из перечисления System.Management.Automation.Provider.ProviderCapabilities . В таких случаях реализация метода System.Management.Automation.Provider.IContentCmdletProvider.ClearContent* должна гарантировать, что путь, переданный к методу, соответствует требованиям указанных возможностей. Для этого метод должен получить доступ к соответствующим свойствам, например, к свойствам System.Management.Automation.Provider.CmdletProvider.Exclude* и свойствам System.Management.Automation.Provider.CmdletProvider.Include* .
По умолчанию перенастройки этого метода не должны очищать содержимое объектов, скрытых от пользователя, если только свойство System.Management.Automation.Provider.Provider.CmdletProvider.Force* не установлено на
true. Ошибка должна быть написана, если путь представляет элемент, скрытый от пользователя, и System.Management.Automation.Provider.Provider.CmdletProvider.Force* установлен вfalse.Ваша реализация метода System.Management.Automation.Provider.IContentCmdletProvider.ClearContent* должна вызывать System.Management.Automation.Provider.CmdletProvider.ShouldProcess и проверять его возвращаемое значение перед внесением изменений в хранилище данных. Этот метод используется для подтверждения выполнения операции при внесении изменения в хранилище данных, например, очистки содержимого. Метод System.Management.Automation.Provider.CmdletProvider.ShouldProcess отправляет пользователю имя ресурса для изменения, а среда выполнения Windows PowerShell обрабатывает любые командные настройки или переменные предпочтений при определении того, что должно отображаться.
После вызова System.Management.Automation.Provider.CmdletProvider.ShouldProcess возвращается
true, метод System.Management.Automation.Provider.IContentCmdletProvider.ClearContent* должен вызывать метод System.Management.Automation.Provider.CmdletProvider.ShouldContinue . Этот метод отправляет пользователю сообщение, чтобы получить обратную связь и проверить, следует ли продолжать операцию. Вызов System.Management.Automation.Provider.CmdletProvider.ShouldContinue позволяет дополнительно проверить потенциально опасные модификации системы.
Прикрепление динамических параметров к командоустройству Clear-Content
Cmdlet Clear-Content может требовать дополнительных динамических параметров, которые добавляются во время выполнения. Для предоставления этих динамических параметров поставщик контента Windows PowerShell должен реализовать метод System.Management.Automation.Provider.IContentCmdletProvider.ClearContentDynamicParameters* для обработки этих параметров. Этот метод извлекает параметры элемента по указанному пути. Этот метод извлекает динамические параметры для элемента по указанному пути и возвращает объект с свойствами и полями с атрибутами разбора, похожими на класс cmdlet или объект System.Management.Automation.RuntimeDefinedParameterDictionary . Runtime Windows PowerShell использует возвращённый объект для добавления параметров в cmdlet.
Этот провайдер контейнеров Windows PowerShell не реализует этот метод. Однако следующий код является стандартной реализацией этого метода.
public object ClearContentDynamicParameters(string path)
{
return null;
}
public object ClearContentDynamicParameters(string path)
{
return null;
}
Пример кода
Полный пример кода смотрите в AccessDbProviderSample06 Code Sample06.
Определение типов объектов и форматирования
При написании провайдера может потребоваться добавить элементы к существующим объектам или определить новые. После этого необходимо создать файл Types, который Windows PowerShell сможет использовать для идентификации членов объекта, а также файл Format, определяющий, как объект отображается. Для получения дополнительной информации см. раздел «Расширение типов объектов и форматирования».
Создание провайдера Windows PowerShell
Посмотрите, как зарегистрировать cmdlet, провайдеров и хост-приложения.
Тестирование провайдера Windows PowerShell
Когда ваш провайдер Windows PowerShell зарегистрирован в Windows PowerShell, вы можете проверить это, запустив поддерживаемые cmdlets в командной строке. Например, протестируйте поставщика образцового контента.
Используйте Get-Content cmdlet для извлечения содержимого указанного элемента в таблице базы данных по пути, указанному параметром Path . Параметр ReadCount указывает количество элементов, которые должен читать определённый ридер контента (по умолчанию 1). С помощью следующей команды cmdlet извлекает из таблицы две строки (элементы) и отображает их содержимое. Обратите внимание, что следующий пример вывода использует фиктивную базу данных Access.
Get-Content -Path mydb:\Customers -ReadCount 2
ID : 1
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
ID : 2
FirstName : Eva
LastName : Corets
Email : evacorets@cohowinery.com
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