Создание поставщика содержимого Windows PowerShell
в этом разделе описывается создание поставщика Windows PowerShell, который позволяет пользователю управлять содержимым элементов в хранилище данных. как следствие, поставщик, который может манипулировать содержимым элементов, называется Windows PowerShell поставщиком содержимого.
Примечание
исходный файл C# (AccessDBSampleProvider06. cs) для этого поставщика можно скачать с помощью пакета средств разработки Microsoft Windows Software Development Kit для компонентов среды выполнения Windows Vista и платформа .NET Framework 3,0. инструкции по загрузке см. в статье установка Windows PowerShell и загрузка пакета SDK для Windows PowerShell. Скачанные исходные файлы доступны в <PowerShell Samples> каталоге. дополнительные сведения о других реализациях поставщиков Windows PowerShell см. в разделе разработка поставщика Windows PowerShell.
определение класса поставщика содержимого Windows PowerShell
поставщик содержимого Windows PowerShell должен создать класс .net, который поддерживает интерфейс System. Management. Automation. provider. иконтенткмдлетпровидер . Ниже приведено определение класса для поставщика элементов, описанного в этом разделе.
[CmdletProvider("AccessDB", ProviderCapabilities.None)]
public class AccessDBProvider : NavigationCmdletProvider, IContentCmdletProvider
Обратите внимание, что в этом определении класса атрибут System. Management. Automation. Provider. кмдлетпровидераттрибуте включает два параметра. Первый параметр задает понятное имя для поставщика, используемого 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. дривекмдлетпровидер . дополнительные сведения о реализации этих методов см. в разделе создание поставщика Windows PowerShell диска.
Чтобы управлять элементами хранилища данных, такими как получение, установка и очистка элементов, поставщик должен реализовать методы, предоставляемые базовым классом System. Management. Automation. Provider. итемкмдлетпровидер . дополнительные сведения о реализации этих методов см. в разделе создание поставщика Windows PowerShell элемента.
Для работы с хранилищами данных с несколькими уровнями поставщик должен реализовать методы, предоставляемые базовым классом System. Management. Automation. Provider. контаинеркмдлетпровидер . дополнительные сведения о реализации этих методов см. в разделе создание поставщика контейнера Windows PowerShell.
Для поддержки рекурсивных команд, вложенных контейнеров и относительных путей поставщик должен реализовать базовый класс System. Management. Automation. Provider. Navigationcmdletprovider . кроме того, этот Windows PowerShell поставщик содержимого может подключить интерфейс system. management. automation. provider. иконтенткмдлетпровидер к базовому классу system. management. automation. provider. Navigationcmdletprovider и, следовательно, должен реализовать методы, предоставляемые этим классом. дополнительные сведения см. в разделе реализация поставщика Windows PowerShell навигации.
Реализация средства чтения содержимого
Для чтения содержимого из элемента поставщик должен реализовывать класс чтения содержимого, производный от класса System. Management. Automation. Provider. иконтентреадер. Читатель содержимого для этого поставщика предоставляет доступ к содержимому строки в таблице данных. Класс чтения содержимого определяет метод 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. иконтентвритер. Класс записи содержимого определяет метод Write , записывающий указанное содержимое строки, метод 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. иконтенткмдлетпровидер. жетконтентреадер * для поддержки Get-Content
командлета. Этот метод возвращает средство чтения содержимого для элемента, расположенного по указанному пути. Затем объект модуля чтения можно открыть для чтения содержимого.
Ниже приведена реализация класса System. Management. Automation. Provider. иконтенткмдлетпровидер. жетконтентреадер * для этого метода для данного поставщика.
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
Вопросы, связанные с реализацией Жетконтентреадер
Следующие условия могут применяться к реализации System. Management. Automation. Provider. иконтенткмдлетпровидер. жетконтентреадер *:
при определении класса поставщика Windows PowerShell поставщик содержимого может объявлять возможности поставщика експандвилдкардс, Filter, Include или Exclude из перечисления System. Management. Automation. provider. провидеркапабилитиес . В таких случаях реализация метода System. Management. Automation. Provider. иконтенткмдлетпровидер. жетконтентреадер * должна гарантировать, что путь, передаваемый в метод, соответствует требованиям указанных возможностей. Для этого метод должен получить доступ к соответствующему свойству, например к свойствам System. Management. Automation. Provider. кмдлетпровидер. Exclude * и System. Management. Automation. Provider. кмдлетпровидер. include * .
По умолчанию переопределения этого метода не должны извлекать модуль чтения для объектов, которые скрыты от пользователя, если свойство System. Management. Automation. Provider. кмдлетпровидер. Force * не имеет значение
true
. Если путь представляет элемент, который скрыт от User, а параметр System. Management. Automation. Provider. кмдлетпровидер. Force * имеет значение, то ошибка должна быть записанаfalse
.
Присоединение динамических параметров к командлету Get-Content
Get-Content
Командлету могут потребоваться дополнительные параметры, заданные динамически во время выполнения. чтобы предоставить эти динамические параметры, поставщик содержимого Windows PowerShell должен реализовать метод System. Management. Automation. provider. иконтенткмдлетпровидер. жетконтентреадердинамикпараметерс * . Этот метод получает динамические параметры для элемента по указанному пути и возвращает объект со свойствами и полями с атрибутами синтаксического анализа, похожими на класс командлета или объект System. Management. Automation. рунтимедефинедпараметердиктионари . среда выполнения Windows PowerShell использует возвращаемый объект для добавления параметров в командлет.
поставщик контейнеров Windows PowerShell не реализует этот метод. Однако приведенный ниже код является реализацией этого метода по умолчанию.
public object GetContentReaderDynamicParameters(string path)
{
return null;
}
public object GetContentReaderDynamicParameters(string path)
{
return null;
}
Получение модуля записи содержимого
Для записи содержимого в элемент поставщик должен реализовать System. Management. Automation. Provider. иконтенткмдлетпровидер. жетконтентвритер * для поддержки Set-Content
Add-Content
командлетов и. Этот метод возвращает модуль записи содержимого для элемента, расположенного по указанному пути.
Ниже приведена реализация класса System. Management. Automation. Provider. иконтенткмдлетпровидер. жетконтентвритер * для этого метода.
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);
}
Вопросы, связанные с реализацией Жетконтентвритер
Следующие условия могут применяться к реализации System. Management. Automation. Provider. иконтенткмдлетпровидер. жетконтентвритер *:
при определении класса поставщика Windows PowerShell поставщик содержимого может объявлять возможности поставщика експандвилдкардс, Filter, Include или Exclude из перечисления System. Management. Automation. provider. провидеркапабилитиес . В таких случаях реализация метода System. Management. Automation. Provider. иконтенткмдлетпровидер. жетконтентвритер * должна гарантировать, что путь, передаваемый в метод, соответствует требованиям указанных возможностей. Для этого метод должен получить доступ к соответствующему свойству, например к свойствам System. Management. Automation. Provider. кмдлетпровидер. Exclude * и System. Management. Automation. Provider. кмдлетпровидер. include * .
По умолчанию переопределения этого метода не должны извлекать модуль записи для объектов, которые скрыты от пользователя, если свойство System. Management. Automation. Provider. кмдлетпровидер. Force * не имеет значение
true
. Если путь представляет элемент, который скрыт от User, а параметр System. Management. Automation. Provider. кмдлетпровидер. Force * имеет значение, то ошибка должна быть записанаfalse
.
Присоединение динамических параметров к командлетам Add-Content и Set-Content
Add-Content
Set-Content
Командлеты и могут потребовать дополнительных динамических параметров, которые добавляют среду выполнения. чтобы предоставить эти динамические параметры, поставщик содержимого Windows PowerShell должен реализовать метод System. Management. Automation. provider. иконтенткмдлетпровидер. жетконтентвритердинамикпараметерс * , чтобы обрабатывал эти параметры. Этот метод получает динамические параметры для элемента по указанному пути и возвращает объект со свойствами и полями с атрибутами синтаксического анализа, похожими на класс командлета или объект System. Management. Automation. рунтимедефинедпараметердиктионари . среда выполнения Windows PowerShell использует возвращаемый объект для добавления параметров в командлеты.
поставщик контейнеров Windows PowerShell не реализует этот метод. Однако приведенный ниже код является реализацией этого метода по умолчанию.
public object GetContentWriterDynamicParameters(string path)
{
return null;
}
Очистка содержимого
Поставщик содержимого реализует метод System. Management. Automation. Provider. иконтенткмдлетпровидер. ClearContent * для поддержки Clear-Content
командлета. Этот метод удаляет содержимое элемента по указанному пути, но оставляет элемент неизменным.
Ниже приведена реализация метода System. Management. Automation. Provider. иконтенткмдлетпровидер. 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. иконтенткмдлетпровидер. ClearContent *:
при определении класса поставщика Windows PowerShell поставщик содержимого может объявлять возможности поставщика експандвилдкардс, Filter, Include или Exclude из перечисления System. Management. Automation. provider. провидеркапабилитиес . В таких случаях реализация метода System. Management. Automation. Provider. иконтенткмдлетпровидер. ClearContent * должна гарантировать, что путь, передаваемый в метод, соответствует требованиям указанных возможностей. Для этого метод должен получить доступ к соответствующему свойству, например к свойствам System. Management. Automation. Provider. кмдлетпровидер. Exclude * и System. Management. Automation. Provider. кмдлетпровидер. include * .
По умолчанию переопределения этого метода не должны очищать содержимое объектов, которые скрыты от пользователя, если свойство System. Management. Automation. Provider. кмдлетпровидер. Force * не имеет значение
true
. Если путь представляет элемент, который скрыт от User, а параметр System. Management. Automation. Provider. кмдлетпровидер. Force * имеет значение, то ошибка должна быть записанаfalse
.Реализация метода System. Management. Automation. Provider. иконтенткмдлетпровидер. ClearContent * должна вызывать System. Management. Automation. Provider. кмдлетпровидер. ShouldProcess и проверять его возвращаемое значение перед внесением любых изменений в хранилище данных. Этот метод используется для подтверждения выполнения операции при внесении изменений в хранилище данных, таких как очистка содержимого. метод System. Management. Automation. Provider. кмдлетпровидер. ShouldProcess отправляет имя ресурса, который будет изменен пользователю, при этом среда выполнения Windows PowerShell обрабатывает все параметры командной строки или привилегированные переменные в определении того, что следует отображать.
После того как вызов метода System. Management. Automation. Provider. кмдлетпровидер. ShouldProcess возвращает
true
, метод System. Management. Automation. Provider. иконтенткмдлетпровидер. ClearContent * должен вызвать метод System. Management. Automation. Provider. кмдлетпровидер. ShouldContinue . Этот метод отправляет пользователю сообщение, чтобы разрешить отзыв, чтобы убедиться, что операция должна быть продолжена. Вызов System. Management. Automation. Provider. кмдлетпровидер. ShouldContinue обеспечивает дополнительную проверку потенциально опасного изменения системы.
Присоединение динамических параметров к командлету Clear-Content
Для Clear-Content
командлета могут потребоваться дополнительные динамические параметры, добавляемые во время выполнения. чтобы предоставить эти динамические параметры, поставщик содержимого Windows PowerShell должен реализовать метод System. Management. Automation. provider. иконтенткмдлетпровидер. клеарконтентдинамикпараметерс * , чтобы обрабатывал эти параметры. Этот метод получает параметры для элемента по указанному пути. Этот метод получает динамические параметры для элемента по указанному пути и возвращает объект со свойствами и полями с атрибутами синтаксического анализа, похожими на класс командлета или объект System. Management. Automation. рунтимедефинедпараметердиктионари . среда выполнения 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 : 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 навигации
Регистрация командлетов, поставщиков и ведущих приложений