Sdílet prostřednictvím


Vytvoření zprostředkovatele obsahu Windows PowerShellu

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

Poznámka:

Zdrojový soubor C# (AccessDBSampleProvider06.cs) tohoto poskytovatele si můžete stáhnout pomocí sady Microsoft Windows Software Development Kit pro windows Vista a .NET Framework 3.0 Runtime Components. Pokyny ke stažení najdete v tématu Postup instalace prostředí Windows PowerShell a stažení sady Windows PowerShell SDK. Stažené zdrojové soubory jsou k dispozici v <powershellových ukázkách> adresáři. Další informace o dalších implementacích zprostředkovatele Prostředí Windows PowerShell naleznete v tématu Návrh zprostředkovatele Prostředí Windows PowerShell.

Definování třídy zprostředkovatele obsahu Windows PowerShellu

Zprostředkovatel obsahu Prostředí Windows PowerShell musí vytvořit třídu .NET, která podporuje rozhraní System.Management.Automation.Provider.IContentCmdletProvider rozhraní. Tady je definice třídy pro zprostředkovatele položky 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 System.Management.Automation.Provider.CmdletProviderAttribute atribut obsahuje dva parametry. První parametr určuje uživatelsky přívětivý název zprostředkovatele, který používá Prostředí Windows PowerShell. Druhý parametr určuje specifické možnosti prostředí Windows PowerShell, které zprostředkovatel během zpracování příkazů zpřístupňuje modulu runtime Prostředí Windows PowerShell. Pro tohoto poskytovatele nejsou žádné přidané funkce prostředí Windows PowerShell.

Definování funkcí základní třídy

Jak je popsáno v Návrh zprostředkovatele Prostředí Windows PowerShell, System.Management.Automation.Provider.NavigationCmdletProvider třída odvozena z několika dalších tříd, které poskytují různé funkce zprostředkovatele. Zprostředkovatel obsahu Windows PowerShellu, proto obvykle definuje všechny funkce poskytované těmito třídami.

Další informace o tom, jak implementovat funkce pro přidání inicializačních informací specifických pro relaci a uvolnění prostředků používaných poskytovatelem, najdete v tématu Vytvoření základního zprostředkovatele Windows PowerShellu. Většina poskytovatelů, včetně zde popsaného poskytovatele, ale může použít výchozí implementaci této funkce, kterou poskytuje Windows PowerShell.

Aby měl poskytovatel přístup k úložišti dat, musí implementovat metody System.Management.Automation.Provider.DriveCmdletProvider základní třídy. Další informace o implementaci těchto metod naleznete v tématu Vytvoření zprostředkovatele jednotky Prostředí Windows PowerShell.

Aby bylo možno manipulovat s položkami úložiště dat, jako je získání, nastavení a vymazání položek, musí poskytovatel implementovat metody poskytované System.Management.Automation.Provider.ItemCmdletProvider základní třídy. Další informace o implementaci těchto metod naleznete v tématu Vytvoření zprostředkovatele položek prostředí Windows PowerShell.

Pokud chcete pracovat s vícevrstvými úložišti dat, musí poskytovatel implementovat metody poskytované System.Management.Automation.Provider.ContainerCmdletProvider základní třídy. Další informace o implementaci těchto metod naleznete v tématu Vytvoření zprostředkovatele kontejneru prostředí Windows PowerShell.

Aby bylo možné podporovat rekurzivní příkazy, vnořené kontejnery a relativní cesty, musí poskytovatel implementovat System.Management.Automation.Provider.NavigationCmdletProvider základní třídy. Kromě toho může tento zprostředkovatel obsahu Windows PowerShellu připojit System.Management.Automation.Provider.IContentCmdletProvider rozhraní k rozhraní System.Management.Automation.Provider.NavigationCmdletProvider základní třídě, a proto musí implementovat metody poskytované touto třídou. Další informace naleznete v tématu implementace těchto metod naleznete v tématu Implementace zprostředkovatele windows PowerShellu navigace.

Implementace čtečky obsahu

Ke čtení obsahu z položky musí poskytovatel implementovat třídu čtenáře obsahu, která je odvozena z System.Management.Automation.Provider.IContentReader. Čtenář obsahu tohoto poskytovatele umožňuje přístup k obsahu řádku v tabulce dat. Třída čtečky obsahu definuje metodu Read, která načte data z uvedeného řádku a vrátí seznam představující tato data, metodu Seek, která přesune čtenáře obsahu, metodu Zavřít, která čtenáře obsahu zavře, 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

K zápisu obsahu do položky musí poskytovatel implementovat třídu zapisovače obsahu odvozena z System.Management.Automation.Provider.IContentWriter. Třída zapisovače obsahu definuje metodu Write, která zapisuje zadaný obsah řádku, metodu Seek, která přesune zapisovač obsahu, metodu Zavřít, která zapisuje obsah, 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

Pokud chcete získat obsah z položky, musí poskytovatel implementovat System.Management.Automation.Provider.IContentCmdletProvider.GetContentReader* pro podporu rutiny Get-Content. Tato metoda vrátí čtenář obsahu pro položku umístěnou v zadané cestě. Objekt čtenáře je pak možné 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

Co je potřeba pamatovat na 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

Rutina Get-Content může vyžadovat další parametry, které se zadají dynamicky za běhu. Chcete-li poskytnout tyto dynamické parametry, musí poskytovatel obsahu prostředí Windows PowerShell implementovat System.Management.Automation.Provider.IContentCmdletProvider.GetContentReaderdynamicparameters* metoda. Tato metoda načte dynamické parametry položky na určené cestě a vrátí objekt, který má vlastnosti a pole s parsováním atributů podobných třídě rutiny nebo System.Management.Automation.RuntimeDefinedParameterDictionary objektu. Modul runtime Prostředí Windows PowerShell používá vrácený objekt k přidání parametrů do rutiny.

Tento poskytovatel kontejneru Windows PowerShellu 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;
}

Načítání zapisovače obsahu

Pokud chcete napsat obsah do položky, musí poskytovatel implementovat System.Management.Automation.Provider.IContentCmdletProvider.GetContentWriter* pro podporu Set-Content a Add-Content rutin. 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);
}

Co je potřeba pamatovat na implementaci GetContentWriter

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

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

Rutiny Add-Content a Set-Content můžou vyžadovat další dynamické parametry přidané modulem runtime. Chcete-li poskytnout tyto dynamické parametry, musí poskytovatel obsahu prostředí Windows PowerShell implementovat System.Management.Automation.Provider.IContentCmdletProvider.GetContentWriterDynamicParameters* metodu pro zpracování těchto parametrů. Tato metoda načte dynamické parametry položky na určené cestě a vrátí objekt, který má vlastnosti a pole s parsováním atributů podobných třídě rutiny nebo System.Management.Automation.RuntimeDefinedParameterDictionary objektu. Modul runtime Prostředí Windows PowerShell používá vrácený objekt k přidání parametrů do rutin.

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

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

Vymazání obsahu

Váš poskytovatel obsahu implementuje metodu System.Management.Automation.Provider.IContentCmdletProvider.ClearContent* pro podporu rutiny Clear-Content. Tato metoda odebere obsah položky v zadané cestě, ale ponechá položku nedotčenou.

Zde je implementace System.Management.Automation.Provider.IContentCmdletProvider.ClearContent* metoda 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

Co je potřeba pamatovat na 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

Rutina Clear-Content může vyžadovat další dynamické parametry přidané za běhu. Chcete-li poskytnout tyto dynamické parametry, musí poskytovatel obsahu prostředí Windows PowerShell implementovat System.Management.Automation.Provider.IContentCmdletProvider.ClearContentDynamicParameters* metodu pro zpracování těchto parametrů. Tato metoda načte parametry položky na určené cestě. Tato metoda načte dynamické parametry položky na určené cestě a vrátí objekt, který má vlastnosti a pole s parsováním atributů podobných třídě rutiny nebo System.Management.Automation.RuntimeDefinedParameterDictionary objektu. Modul runtime Prostředí Windows PowerShell používá vrácený objekt k přidání parametrů do rutiny.

Tento poskytovatel kontejneru Windows PowerShellu 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

Úplný vzorový kód najdete v ukázky kódu AccessDbProviderSample06.

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

Při psaní zprostředkovatele může být nutné přidat členy do existujících objektů nebo definovat nové objekty. Po dokončení je nutné vytvořit soubor Typy, který windows PowerShell může použít k identifikaci členů objektu a souboru formátu, který definuje, jak se objekt zobrazí. Další informace naleznete v tématu rozšíření typů objektů a formátování.

Vytvoření zprostředkovatele Windows PowerShellu

Viz Postup registrace rutin, poskytovatelů a hostitelských aplikací.

Testování zprostředkovatele Windows PowerShellu

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

Pomocí rutiny Get-Content načtěte obsah zadané položky v tabulce databáze v cestě určené parametrem Path. Parametr ReadCount určuje počet položek, které má definovaný čtenář obsahu číst (výchozí hodnota 1). Pomocí následující položky příkazu rutina načte ze tabulky dva řádky (položky) a zobrazí jejich obsah. Všimněte si, že následující příklad výstupu používá fiktivní accessovou databázi.

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 PowerShellu

navrhnout poskytovatele Windows PowerShellu

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

Implementace zprostředkovatele windows PowerShellu pro navigaci

registrace rutin, poskytovatelů a hostitelských aplikací

windows PowerShell SDK

programátora windows PowerShellu