Vytvoření zprostředkovatele obsahu Windows PowerShellu

toto téma popisuje, jak vytvořit poskytovatele Windows PowerShell, který umožňuje uživateli manipulovat s obsahem položek v úložišti dat. v důsledku toho poskytovatel, který může manipulovat s obsahem položek, se označuje jako poskytovatel obsahu Windows PowerShell.

Poznámka

zdrojový soubor C# (AccessDBSampleProvider06. cs) pro tohoto zprostředkovatele si můžete stáhnout pomocí sady Microsoft Windows Software Development Kit pro Windows Vista a .NET Framework 3,0 běhových komponent. pokyny ke stažení najdete v tématu jak nainstalovat Windows PowerShell a stáhnout sadu Windows PowerShell SDK. Stažené zdrojové soubory jsou k dispozici v <PowerShell Samples> adresáři. další informace o dalších implementacích poskytovatele Windows PowerShell najdete v tématu navrhování poskytovatele Windows PowerShell.

definice třídy poskytovatele Windows PowerShell obsahu

poskytovatel obsahu Windows PowerShell musí vytvořit třídu .net, která podporuje rozhraní System. Management. Automation. provider. Icontentcmdletprovider . Tady je definice třídy pro poskytovatele položek popsané v této části.

[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ý název pro poskytovatele, který je používán Windows PowerShell. druhý parametr určuje Windows PowerShell specifické možnosti, které poskytovatel zpřístupňuje modulu Windows PowerShell runtime během zpracování příkazu. pro tohoto zprostředkovatele nejsou k dispozici žádné Windows PowerShell specifické možnosti.

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

jak je popsáno v tématu návrh poskytovatele Windows PowerShell, třída System. Management. Automation. Provider. Navigationcmdletprovider je odvozena z několika dalších tříd, které poskytují jiné funkce poskytovatele. poskytovatel obsahu Windows PowerShell proto obvykle definuje všechny funkce poskytované těmito třídami.

další informace o implementaci funkcí pro přidání inicializačních informací specifických pro relaci a uvolnění prostředků používaných zprostředkovatelem najdete v tématu vytvoření základního poskytovatele Windows PowerShell. Většina poskytovatelů, včetně poskytovatele popsaných tady, ale může používat výchozí implementaci této funkce, která je k dispozici v Windows PowerShell.

Pro přístup k úložišti dat musí poskytovatel implementovat metody základní třídy System. Management. Automation. Provider. Drivecmdletprovider . další informace o implementaci těchto metod najdete v tématu vytvoření poskytovatele Windows PowerShell jednotky.

Aby bylo možné manipulovat s položkami úložiště dat, jako je například získání, nastavení a mazání položek, poskytovatel musí implementovat metody poskytované základní třídou System. Management. Automation. Provider. Itemcmdletprovider . další informace o implementaci těchto metod naleznete v tématu vytvoření poskytovatele Windows PowerShellch položek.

Aby bylo možné pracovat s více úložišti dat, poskytovatel musí implementovat metody poskytované základní třídou System. Management. Automation. Provider. Containercmdletprovider . další informace o implementaci těchto metod naleznete v tématu vytvoření poskytovatele kontejneru Windows PowerShell.

Aby bylo možné podporovat rekurzivní příkazy, vnořené kontejnery a relativní cesty, musí zprostředkovatel implementovat základní třídu System. Management. Automation. Provider. Navigationcmdletprovider . kromě toho může tento Windows PowerShell poskytovatel obsahu připojit rozhraní system. management. automation. provider. Icontentcmdletprovider k základní třídě system. management. automation. provider. Navigationcmdletprovider a musí proto implementovat metody poskytované touto třídou. další informace naleznete v tématu implementace těchto metod v tématu implementace poskytovatele Windows PowerShell navigace.

Implementace čtečky obsahu

Pro čtení obsahu z položky musí zprostředkovatel implementovat třídu čtečky obsahu, která je odvozena od třídy System. Management. Automation. Provider. Icontentreader. Čtenář obsahu pro tohoto zprostředkovatele umožňuje přístup k obsahu řádku v tabulce dat. Třída čtečky obsahu definuje metodu čtení , která načte data z označeného řádku a vrátí seznam reprezentující tato data, vyhledávací metodu, která přesune čtečku obsahu, metodu Close , která zavírá čtečku obsahu 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 zapisovače obsahu

Aby bylo možné zapisovat obsah do položky, zprostředkovatel musí implementovat třídu zapisovače obsahu odvozenou od třídy System. Management. Automation. Provider. Icontentwriter. Třída zapisovač obsahu definuje metodu zápisu , která zapisuje zadaný obsah řádku, vyhledávací metodu, která přesouvá zapisovač obsahu, metodu Close , která zavírá zapisovač obsahu, 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

Načítání čtečky obsahu

Chcete-li získat obsah z položky, zprostředkovatel musí implementovat rozhraní System. Management. Automation. Provider. Icontentcmdletprovider. Getcontentreader * pro podporu Get-Content rutiny. Tato metoda vrátí čtecí modul obsahu pro položku umístěnou v zadané cestě. Objekt čtečky lze následně 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, které si zapamatujete o implementaci GetContentReader

Následující podmínky mohou platit pro implementaci System. Management. Automation. Provider. Icontentcmdletprovider. Getcontentreader *:

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

Get-ContentRutina může vyžadovat další parametry, které jsou zadány dynamicky za běhu. aby bylo možné poskytnout tyto dynamické parametry, poskytovatel obsahu Windows PowerShell musí implementovat metodu System. Management. Automation. provider. Icontentcmdletprovider. Getcontentreaderdynamicparameters * . Tato metoda načte dynamické parametry pro položku na zadané cestě a vrátí objekt, který má vlastnosti a pole s atributy analýzy, podobně jako třída rutin nebo objekt System. Management. Automation. Runtimedefinedparameterdictionary . modul runtime Windows PowerShell používá vrácený objekt k přidání parametrů do rutiny.

tento zprostředkovatel kontejneru Windows PowerShell neimplementuje tuto metodu. 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;
}

Načítání zapisovače obsahu

Chcete-li zapisovat obsah do položky, zprostředkovatel musí implementovat rozhraní System. Management. Automation. Provider. Icontentcmdletprovider. Getcontentwriter * , aby podporoval Set-Content Add-Content rutiny a. Tato metoda vrátí zapisovač obsahu pro položku umístěnou v zadané 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);
}

Věci, které si zapamatujete o implementaci GetContentWriter

Následující podmínky mohou platit pro implementaci System. Management. Automation. Provider. Icontentcmdletprovider. Getcontentwriter *:

Připojení dynamických parametrů k rutinám Add-Content a Set-Content

Add-Content Set-Content Rutiny a můžou vyžadovat další dynamické parametry, které přidávají modul runtime. aby bylo možné tyto dynamické parametry poskytnout, poskytovatel obsahu Windows PowerShell musí implementovat metodu System. Management. Automation. provider. Icontentcmdletprovider. Getcontentwriterdynamicparameters * pro zpracování těchto parametrů. Tato metoda načte dynamické parametry pro položku na zadané cestě a vrátí objekt, který má vlastnosti a pole s atributy analýzy, podobně jako třída rutin nebo objekt System. Management. Automation. Runtimedefinedparameterdictionary . modul runtime Windows PowerShell používá vrácený objekt k přidání parametrů do rutin.

tento zprostředkovatel kontejneru Windows PowerShell neimplementuje tuto metodu. Následující kód je však výchozí implementací této metody.

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

Mazání obsahu

Poskytovatel obsahu implementuje metodu System. Management. Automation. Provider. Icontentcmdletprovider. ClearContent * v podpoře Clear-Content rutiny. Tato metoda odebere obsah položky v zadané cestě, ale ponechá položku beze změny.

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

Věci, které si zapamatujete o implementaci ClearContent

Následující podmínky mohou platit pro implementaci System. Management. Automation. Provider. Icontentcmdletprovider. ClearContent *:

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

Clear-ContentRutina může vyžadovat další dynamické parametry, které se přidají za běhu. aby bylo možné tyto dynamické parametry poskytnout, poskytovatel obsahu Windows PowerShell musí implementovat metodu System. Management. Automation. provider. Icontentcmdletprovider. Clearcontentdynamicparameters * pro zpracování těchto parametrů. Tato metoda načte parametry položky na zadané cestě. Tato metoda načte dynamické parametry pro položku na zadané cestě a vrátí objekt, který má vlastnosti a pole s atributy analýzy, podobně jako třída rutin nebo objekt System. Management. Automation. Runtimedefinedparameterdictionary . modul runtime Windows PowerShell používá vrácený objekt k přidání parametrů do rutiny.

tento zprostředkovatel kontejneru Windows PowerShell neimplementuje tuto metodu. 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;
}

Vzorek kódu

Úplný vzorový kód naleznete v tématu AccessDbProviderSample06 Code Sample.

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

Při psaní poskytovatele může být nutné přidat členy do existujících objektů nebo definovat nové objekty. až to uděláte, musíte vytvořit soubor typů, který Windows PowerShell použít k identifikaci členů objektu a formátového souboru, který definuje způsob zobrazení objektu. Další informace najdete v tématu rozšíření typů objektů a formátování.

sestavování poskytovatele Windows PowerShell

Podívejte se , jak registrovat rutiny, zprostředkovatele a hostitelské aplikace.

testování poskytovatele Windows PowerShell

když je poskytovatel Windows PowerShell zaregistrovaný v Windows PowerShell, můžete ho otestovat spuštěním podporovaných rutin na příkazovém řádku. Otestujte například ukázkového poskytovatele obsahu.

Pomocí Get-Content rutiny načtěte obsah zadané položky v tabulce databáze na cestě určené Path parametrem. ReadCountParametr určuje počet položek pro čtení definovaného čtecího modulu obsahu (výchozí hodnota 1). V následující položce příkazu načte rutina 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 Accessu.

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í zprostředkovatelů Windows PowerShell

návrh poskytovatele Windows PowerShell

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

implementace poskytovatele Windows PowerShell navigace

Jak registrovat rutiny, zprostředkovatele a hostitelské aplikace

Sada SDK Windows PowerShellu

Příručka programátora Windows PowerShellu