Megosztás a következőn keresztül:


Windows PowerShell tartalomszolgáltató létrehozása

Ez a téma leírja, hogyan hozhatunk létre Windows PowerShell szolgáltatót, amely lehetővé teszi a felhasználó számára, hogy kezelje az adattároló elemei tartalmát. Ennek következtében egy olyan szolgáltatót, amely képes manipulálni az elemek tartalmát, Windows PowerShell tartalomszolgáltatónak nevezik.

Megjegyzés:

Letöltheti a C# forrásfájlt (AccessDBSampleProvider06.cs) ehhez a szolgáltatóhoz a Microsoft Windows Software Development Kit for Windows Vista és .NET Framework 3.0 Runtime Components segítségével. A letöltési utasításokért lásd: Hogyan telepítsük a Windows PowerShell és a Windows PowerShell SDK letöltése. A letöltött forrásfájlok elérhetők a <PowerShell Samples> könyvtárban. További információért más Windows PowerShell szolgáltató megvalósításokról lásd: Designing Your Windows PowerShell Provider.

Definiáld a Windows PowerShell tartalomszolgáltató osztályt

Egy Windows PowerShell tartalomszolgáltatónak olyan .NET osztályt kell létrehoznia, amely támogatja a System.Management.Automation.Provider.IContentCmdletProvider interfészt. Íme a részben leírt tárgyszolgáltató osztálydefiníciója.

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

Fontos megjegyezni, hogy ebben az osztálydefinícióban a System.Management.Automation.Provider.CmdletProviderAttribute attribútum két paramétert tartalmaz. Az első paraméter egy felhasználóbarát nevet ad a szolgáltatónak, amelyet a Windows PowerShell használ. A második paraméter meghatározza azokat a Windows PowerShell-specifikus képességeket, amelyeket a szolgáltató a Windows PowerShell futási idejének a parancsfeldolgozás során kiterjeszt. Ennél a szolgáltatónál nincs további Windows PowerShell-specifikus képesség.

Az alaposztály funkcionalitásának meghatározása

Ahogy a Design Your Windows PowerShell Provider című művében leírta, a System.Management.Automation.Provider.NavigationCmdletProvider osztály több más osztályból származik, amelyek eltérő szolgáltatói funkciókat biztosítottak. Ezért egy Windows PowerShell tartalomszolgáltató általában meghatározza az összes ilyen osztály által biztosított funkciókat.

További információért a munka-specifikus inicializációs információk hozzáadására és a szolgáltató által használt erőforrások felszabadítására szolgáló funkciók megvalósításáról lásd : Alap Windows PowerShell szolgáltató létrehozása. Azonban a legtöbb szolgáltató, beleértve az itt leírt szolgáltatót is, használhatja ennek a funkciónak a Windows PowerShell által biztosított alapértelmezett megvalósítását.

Az adattárolóhoz való hozzáféréshez a szolgáltatónak a System.Management.Automation.Provider.DriveCmdletProvider alaposztály módszereit kell végrehajtania. További információért ezeknek a módszereknek a megvalósításáról lásd: Windows PowerShell meghajtó szolgáltató létrehozása.

Az adattároló elemeinek, például az elemek megszerzése, beállítása és törlése kezelésére a szolgáltatónak a System.Management.Automation.Provider.ItemCmdletProvider alaposztály által biztosított módszereket kell alkalmaznia. További információért ezeknek a módszereknek a megvalósításáról lásd : Windows PowerShell Item Provider létrehozása.

A többrétegű adattárolók működtetéséhez a szolgáltatónak meg kell valósítania a System.Management.Automation.Provider.ContainerCmdletProvider alaposztály által biztosított módszereket. További információért ezeknek a módszereknek a megvalósításáról lásd : Windows PowerShell konténer szolgáltató létrehozása.

A rekurzív parancsok, beágyazott konténerek és relatív utak támogatásához a szolgáltatónak meg kell valósítania a System.Management.Automation.Provider.NavigationCmdletProvider alaposztályt. Ezen felül ez a Windows PowerShell tartalomszolgáltató csatolhatja a System.Management.Automation.Provider.IContentCmdletProvider interfészt a System.Management.Automation.Provider.NavigationCmdletProvider alaposztályhoz, ezért meg kell valósítania az adott osztály által biztosított módszereket. További információért lásd: Implementál ezeket a módszereket, lásd: Implementáld a Navigáció Windows PowerShell szolgáltatót.

Tartalomolvasó megvalósítása

Ahhoz, hogy egy tárgyból származó tartalmat olvasson, a szolgáltatónak egy tartalomolvasó osztályt kell megvalósítania, amely a System.Management.Automation.Provider.IContentReader kódból származik. Ennek a szolgáltatónak a tartalomolvasója lehetővé teszi a hozzáférést egy adattábla sor tartalmához. A tartalomolvasó osztály egy Read metódust definiál, amely lekéri az adatokat a megadott sorból, és visszaadja az adott adatokat megjelenítő listát, egy Seek metódust, amely mozgatja a tartalomolvasót, egy Close metódust, amely lezárja a tartalomolvasót, valamint egy Dispose metódust.

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

Tartalomíró megvalósítása

Ahhoz, hogy tartalmat írjon egy tárgyba, a szolgáltatónak olyan tartalomíró osztályt kell implementálnia, amely a System.Management.Automation.Provider.IContentWriter programból származik. A tartalomíró osztály meghatároz egy Write metódust, amely a megadott sortartalmat írja meg, egy Seek metódust, amely mozgatja a tartalomírót, egy Close metódust, amely lezárja a tartalomírót, és egy Dispose metódust.

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

A tartalomolvasó visszakeresése

Ahhoz, hogy tartalmat kapjon egy termékből, a szolgáltatónak be kell valósítania a System.Management.Automation.Provider.IContentCmdletProvider.GetContentReader* funkciót, hogy támogassa a Get-Content cmdletet. Ez a módszer visszaadja a tartalomolvasót a megadott útvonalon található elemre. Az olvasóobjektum ezután megnyitható a tartalom elolvasására.

Íme a System.Management.Automation.Provider.IContentCmdletProvider.GetContentReader* megvalósítása ehhez a módszerhez ehhez a szolgáltatóhoz.

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

Fontos dolgok, amiket érdemes megjegyezni a GetContentReader bevezetésével kapcsolatban

A következő feltételek alkalmazhatók a System.Management.Automation.Provider.IContentCmdletProvider.GetContentReader* implementációjára:

Dinamikus paraméterek hozzácsatolása a Get-Content cmdlethez

A Get-Content cmdlet további paramétereket igényelhet, amelyeket dinamikusan meghatározott futás közben. Ezeknek a dinamikus paramétereknek a biztosításához a Windows PowerShell tartalomszolgáltatónak meg kell valósítania a System.Management.Automation.Provider.IContentCmdletProvider.GetContentReaderdynamicparameters* metódust. Ez a módszer a megadott úton lévő elem dinamikus paramétereit keresi, és olyan objektumot ad vissza, amelynek tulajdonságai és mezői olyan elemző attribútumokkal rendelkeznek, amelyek hasonlóak egy cmdlet osztályhoz vagy a System.Management.Automation.RuntimeDefinedParameterDictionary objektumhoz. A Windows PowerShell futási ideje a visszaküldött objektumot használja a paraméterek hozzáadására a cmdlethez.

Ez a Windows PowerShell konténer szolgáltató nem valósítja meg ezt a módszert. Azonban a következő kód a módszer alapértelmezett implementációja.

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

A tartalomíró visszakeresése

Ahhoz, hogy tartalmat írjon egy elemre, a szolgáltatónak be kell valósítania a System.Management.Automation.Provider.IContentCmdletProvider.GetContentWriter* funkciót, hogy támogassa az Set-Content és Add-Content cmdleteket. Ez a módszer visszaadja a tartalomírót a megadott úton található elemre.

Íme a System.Management.Automation.Provider.IContentCmdletProvider.GetContentWriter* implementációja ehhez a módszerhez.

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

Fontos dolgok, amiket érdemes megjegyezni a GetContentWriter bevezetésével kapcsolatban

Az alábbi feltételek alkalmazhatók a System.Management.Automation.Provider.IContentCmdletProvider.GetContentWriter* implementációjára:

Dinamikus paraméterek csatolása a Add-Content és Set-Content parancsnokakhoz

Az és Set-Content cmdlet-ek Add-Content további dinamikus paramétereket igényelhetnek, amelyeket futás közben hozzáadnak. A dinamikus paraméterek biztosításához a Windows PowerShell tartalomszolgáltatónak be kell valósítania a System.Management.Automation.Provider.IContentCmdletProvider.GetContentWriterDynamicParameters* metóduszt a paraméterek kezelésére. Ez a módszer a megadott úton lévő elem dinamikus paramétereit keresi, és olyan objektumot ad vissza, amelynek tulajdonságai és mezői olyan elemző attribútumokkal rendelkeznek, amelyek hasonlóak egy cmdlet osztályhoz vagy a System.Management.Automation.RuntimeDefinedParameterDictionary objektumhoz. A Windows PowerShell futóideje a visszaküldött objektumot használja a paraméterek hozzáadására a cmdletekhez.

Ez a Windows PowerShell konténer szolgáltató nem valósítja meg ezt a módszert. Azonban a következő kód a módszer alapértelmezett implementációja.

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

Tartalom tisztítása

A tartalomszolgáltatód a System.Management.Automation.Provider.IContentCmdletProvider.ClearContent* módszert alkalmazza a cmdlet támogatására Clear-Content . Ez a módszer eltávolítja az elem tartalmát a megadott úton, de érintetlenül hagyja az elemet.

Íme a System.Management.Automation.Provider.IContentCmdletProvider.ClearContent* módszer megvalósítása ehhez a szolgáltatóhoz.

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

Fontos dolgok, amiket érdemes megjegyezni a ClearContent bevezetéséről

A következő feltételek alkalmazhatók a System.Management.Automation.Provider.IContentCmdletProvider.ClearContent* implementációjára:

Dinamikus paraméterek hozzácsatolása a Clear-Content cmdlethez

A Clear-Content cmdlet további dinamikus paramétereket igényelhet, amelyeket futás közben adnak hozzá. Ezeknek a dinamikus paramétereknek a biztosításához a Windows PowerShell tartalomszolgáltatónak be kell valósítania a System.Management.Automation.Provider.IContentCmdletProvider.ClearContentDynamicParameters* metódunut a paraméterek kezelésére. Ez a módszer visszanyeri az elem paramétereit a megadott úton. Ez a módszer a megadott úton lévő elem dinamikus paramétereit keresi, és olyan objektumot ad vissza, amelynek tulajdonságai és mezői olyan elemző attribútumokkal rendelkeznek, amelyek hasonlóak egy cmdlet osztályhoz vagy a System.Management.Automation.RuntimeDefinedParameterDictionary objektumhoz. A Windows PowerShell futási ideje a visszaküldött objektumot használja a paraméterek hozzáadására a cmdlethez.

Ez a Windows PowerShell konténer szolgáltató nem valósítja meg ezt a módszert. Azonban a következő kód a módszer alapértelmezett implementációja.

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

Kódminta

A teljes mintakódért lásd: AccessDbProviderSample06 Code Sample.

Objektumtípusok meghatározása és formázása

Szolgáltató írásakor szükség lehet tagok hozzáadására meglévő objektumokhoz vagy új objektumok definiálására. Amikor ez megtörténik, létre kell hoznod egy Types fájlt, amelyet a Windows PowerShell használhat az objektum tagjainak azonosítására, valamint egy Format fájlt, amely meghatározza, hogyan jeleníti meg az objektumot. További információért lásd: Objektumtípusok és formázás bővítése.

Windows PowerShell szolgáltató építése

Lásd : Hogyan regisztráljuk a cmdleteket, szolgáltatókat és hásztealkalmazásokat.

A Windows PowerShell szolgáltató tesztelése

Amikor a Windows PowerShell szolgáltatód regisztrálva van Windows PowerShell-re, tesztelheted a támogatott cmdlet-eket a parancssoron futtatva. Például teszteljük a mintatartalomszolgáltatót.

A Get-Content cmdletet használjuk a megadott elem tartalmának visszakeresésére az adatbázis táblájában, a paraméter által megadott Path úton. A ReadCount paraméter megadja, hogy a definiált tartalomolvasó hány elemet olvas (alapértelmezett 1). A következő parancsbejegyzéssel a cmdlet két sort (elemet) visszanyer a táblából, és megjeleníti azok tartalmát. Fontos megjegyezni, hogy a következő példakimenet egy fiktív Access adatbázist használ.

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

Lásd még:

Windows PowerShell szolgáltatók létrehozása

Tervezd meg a Windows PowerShell szolgáltatódat

Objektumtípusok és formázás bővítése

Implementál egy Navigation Windows PowerShell szolgáltatót

Hogyan regisztráljuk a cmdleteket, szolgáltatókat és hoszt alkalmazásokat

Windows PowerShell SDK

Windows PowerShell programozói útmutató