Sdílet prostřednictvím


Vytvoření poskytovatele obsahu ve Windows PowerShell

Toto téma popisuje, jak vytvořit poskytovatele Windows PowerShell, který umožňuje uživateli manipulovat s obsahem položek v datovém úložišti. V důsledku toho se poskytovatel, který dokáže manipulovat s obsahem položek, nazývá poskytovatel obsahu Windows PowerShell.

Poznámka:

Zdrojový soubor C# (AccessDBSampleProvider06.cs) tohoto poskytovatele si můžete stáhnout pomocí Microsoft Windows Software Development Kit pro Windows Vista a .NET Framework 3.0 Runtime Components. Pro návod ke stažení viz Jak nainstalovat Windows PowerShell a Stáhněte si Windows PowerShell SDK. Stažené zdrojové soubory jsou dostupné v adresáři <PowerShell Samples> . Pro více informací o dalších implementacích poskytovatelů Windows PowerShell viz Návrh vašeho poskytovatele Windows PowerShell.

Definujte třídu poskytovatele obsahu Windows PowerShell

Poskytovatel obsahu ve Windows PowerShell musí vytvořit .NET třídu, která podporuje rozhraní System.Management.Automation.Provider.IContentCmdletProvider . Zde je definice třídy poskytovatele položek popsaná v této sekci.

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

Všimněte si, že v této definici třídy atribut System.Management.Automation.Provider.CmdletProviderAttribute obsahuje dva parametry. První parametr určuje uživatelsky přívětivé jméno poskytovatele, které používá Windows PowerShell. Druhý parametr specifikuje specifické schopnosti Windows PowerShell, které poskytovatel zpřístupňuje běhu Windows PowerShell během zpracování příkazů. Pro tohoto poskytovatele nejsou přidané specifické funkce Windows PowerShell.

Definujte funkčnost základní třídy

Jak je popsáno v knize Design Your Windows PowerShell Provider, třída System.Management.Automation.Provider.NavigationCmdletProvider pochází z několika dalších tříd, které nabízely různé funkce poskytovatelů. Poskytovatel obsahu ve Windows PowerShell tedy obvykle definuje veškerou funkcionalitu poskytovanou těmito třídami.

Pro více informací o tom, jak implementovat funkce pro přidání specifických inicializačních informací pro relaci a pro uvolnění zdrojů používaných poskytovatelem, viz Vytvoření základního poskytovatele Windows PowerShell. Většina poskytovatelů, včetně zde popsaného poskytovatele, však může použít výchozí implementaci této funkce, kterou poskytuje Windows PowerShell.

Pro přístup k datovému úložišti musí poskytovatel implementovat metody základní třídy System.Management.Automation.Provider.DriveCmdletProvider . Pro více informací o implementaci těchto metod viz Vytvoření poskytovatele disku Windows PowerShell.

Pro manipulaci s položkami datového úložiště, jako je získávání, nastavování a vyřizování položek, musí poskytovatel implementovat metody poskytované základní třídou System.Management.Automation.Provider.ItemCmdletProvider . Pro více informací o implementaci těchto metod viz Vytvoření poskytovatele položek Windows PowerShell.

Pro práci s vícevrstvými datovými úložišti musí poskytovatel implementovat metody poskytované základní třídou System.Management.Automation.Provider.ContainerCmdletProvider . Pro více informací o implementaci těchto metod viz Vytvoření Windows PowerShell Container Provider.

Pro podporu rekurzivních příkazů, vnořených kontejnerů a relativních cest musí poskytovatel implementovat základní třídu System.Management.Automation.Provider.NavigationCmdletProvider . Kromě toho může tento poskytovatel obsahu Windows PowerShell připojit rozhraní System.Management.Automation.Provider.IContentCmdletProvider k základní třídě System.Management.Automation.Provider.NavigationCmdletProvider , a proto musí implementovat metody poskytované touto třídou. Pro více informací viz implementace těchto metod viz Implementace navigace Windows PowerShell Provider.

Implementace čtečky obsahu

Pro čtení obsahu z položky musí poskytovatel implementovat třídu čtečky obsahu, která vychází ze System.Management.Automation.Provider.IContentReader. Čtečka obsahu tohoto poskytovatele umožňuje přístup k obsahu řádku v datové tabulce. Třída Content reader definuje metodu čtení , která získává data z uvedeného řádku a vrací seznam reprezentující tato data, metodu Seek , která přesouvá čtečku obsahu, metodu Close , která čtečku obsahu uzavírá, a metodu 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

Implementace Content Writera

Pro napsání obsahu na položku musí poskytovatel implementovat třídu content writer odvozenou ze System.Management.Automation.Provider.IContentWriter. Třída content writer definuje metodu Write , která zapisuje zadaný obsah řádku, metodu Sekeen , která přesouvá content writera, metodu Close , která uzavírá content writera, a metodu 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

Získání čtečky obsahu

Pro získání obsahu z položky musí poskytovatel implementovat System.Management.Automation.Provider.IContentCmdletProvider.GetContentReader* pro podporu Get-Content cmdletu. Tato metoda vrací čtečku obsahu pro položku umístěnou na určené cestě. Objekt čtečky lze pak otevřít pro čtení obsahu.

Zde je implementace System.Management.Automation.Provider.IContentCmdletProvider.GetContentReader* pro tuto metodu pro tohoto poskytovatele.

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

Věci, na které je třeba pamatovat při implementaci GetContentReader

Následující podmínky se mohou vztahovat na implementaci System.Management.Automation.Provider.IContentCmdletProvider.GetContentReader*:

Připojení dynamických parametrů k Get-Content Cmdletu

Cmdlet Get-Content může vyžadovat další parametry, které jsou dynamicky specifikovány za běhu. Pro poskytnutí těchto dynamických parametrů musí poskytovatel obsahu Windows PowerShell implementovat metodu System.Management.Automation.Provider.IContentCmdletProvider.GetContentReaderdynamicparameters* . Tato metoda získává dynamické parametry pro položku na indikované cestě a vrací objekt, který má vlastnosti a pole s atributy pro parsování podobnými třídě cmdlet nebo objektu System.Management.Automation.RuntimeDefinedParameterDictionary . Runtime Windows PowerShell používá vrácený objekt k přidání parametrů do cmdletu.

Tento poskytovatel kontejnerů Windows PowerShell tuto metodu neimplementuje. Následující kód je však výchozí implementací této metody.

public object GetContentReaderDynamicParameters(string path)
{
    return null;
}
public object GetContentReaderDynamicParameters(string path)
{
    return null;
}

Získání autora obsahu

Pro napsání obsahu na položku musí poskytovatel implementovat System.Management.Automation.Provider.IContentCmdletProvider.GetContentWriter* pro podporu Set-Content a Add-Content cmdletů. Tato metoda vrací autora obsahu pro položku umístěnou na určené cestě.

Zde je implementace System.Management.Automation.Provider.IContentCmdletProvider.GetContentWriter* pro tuto metodu.

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);
}

Na co si pamatovat při implementaci GetContentWriter

Následující podmínky se mohou vztahovat na vaši implementaci System.Management.Automation.Provider.IContentCmdletProvider.GetContentWriter*:

Připojování dynamických parametrů k Add-Content a Set-Content cmdletům

Cmdlets Add-Content and Set-Content mohou vyžadovat další dynamické parametry, které se přidávají za běhu. Aby poskytovatel obsahu ve Windows PowerShell mohl tyto dynamické parametry zajistit, musí implementovat metodu System.Management.Automation.Provider.IContentCmdletProvider.GetContentWriterDynamicParameters* pro zpracování těchto parametrů. Tato metoda získává dynamické parametry pro položku na indikované cestě a vrací objekt, který má vlastnosti a pole s atributy pro parsování podobnými třídě cmdlet nebo objektu System.Management.Automation.RuntimeDefinedParameterDictionary . Runtime Windows PowerShell používá vrácený objekt k přidání parametrů do cmdletů.

Tento poskytovatel kontejnerů Windows PowerShell tuto metodu neimplementuje. Následující kód je však výchozí implementací této metody.

public object GetContentWriterDynamicParameters(string path)
{
    return null;
}

Clearingový obsah

Váš poskytovatel obsahu implementuje metodu System.Management.Automation.Provider.IContentCmdletProvider.ClearContent* na podporu Clear-Content tohoto cmdletu. Tato metoda odstraní obsah položky na určené cestě, ale položku ponechá nedotčenou.

Zde je implementace metody System.Management.Automation.Provider.IContentCmdletProvider.ClearContent* pro tohoto poskytovatele.

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

Na co si pamatovat při implementaci ClearContent

Následující podmínky se mohou vztahovat na implementaci System.Management.Automation.Provider.IContentCmdletProvider.ClearContent*:

Připojení dynamických parametrů k Clear-Content Cmdletu

Cmdlet Clear-Content může vyžadovat další dynamické parametry, které se přidávají za běhu. Pro poskytnutí těchto dynamických parametrů musí poskytovatel obsahu Windows PowerShell implementovat metodu System.Management.Automation.Provider.IContentCmdletProvider.ClearContentDynamicParameters* pro zpracování těchto parametrů. Tato metoda získá parametry položky na uvedené cestě. Tato metoda získává dynamické parametry pro položku na indikované cestě a vrací objekt, který má vlastnosti a pole s atributy pro parsování podobnými třídě cmdlet nebo objektu System.Management.Automation.RuntimeDefinedParameterDictionary . Runtime Windows PowerShell používá vrácený objekt k přidání parametrů do cmdletu.

Tento poskytovatel kontejnerů Windows PowerShell tuto metodu neimplementuje. Následující kód je však výchozí implementací této metody.

public object ClearContentDynamicParameters(string path)
{
    return null;
}
public object ClearContentDynamicParameters(string path)
{
    return null;
}

Ukázka kódu

Pro kompletní ukázkový kód viz AccessDbProviderSample06 Code Sample.

Definování typů objektů a formátování

Při psaní poskytovatele může být nutné přidávat členy k existujícím objektům nebo definovat nové objekty. Když je to hotové, musíte vytvořit soubor Types, který Windows PowerShell použije k identifikaci členů objektu, a formátový soubor, který definuje, jak je objekt zobrazen. Pro více informací viz Rozšíření typů objektů a formátování.

Vytvoření Windows PowerShell Provider

Podívejte se, jak registrovat cmdlety, poskytovatele a hostitelské aplikace.

Testování Windows PowerShell Provider

Když je váš poskytovatel Windows PowerShell registrován ve Windows PowerShell, můžete to otestovat spuštěním podporovaných cmdletů na příkazovém řádku. Například otestujte poskytovatele vzorkového obsahu.

Použijte Get-Content cmdlet k získání obsahu zadané položky v databázové tabulce na cestě určené parametrem Path . Parametr ReadCount určuje počet položek, které má definovaná čtečka obsahu číst (výchozí 1). S následujícím příkazem cmdlet načte dva řádky (položky) z tabulky a zobrazí jejich obsah. Všimněte si, že následující příklad výstupu používá fiktivní databázi 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

Viz také

Vytváření poskytovatelů Windows PowerShell

Navrhněte svého poskytovatele Windows PowerShell

Rozšíření typů objektů a formátování

Implementace navigačního poskytovatele Windows PowerShell

Jak registrovat cmdlety, poskytovatele a hostitelské aplikace

Windows PowerShell SDK

Průvodce programátora Windows PowerShell