<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>dimeby8</title><link>http://blogs.msdn.com/dimeby8/default.aspx</link><description /><dc:language>en</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Change ‘Unidentified network’ from Public to Work in Windows 7</title><link>http://blogs.msdn.com/dimeby8/archive/2009/06/10/change-unidentified-network-from-public-to-work-in-windows-7.aspx</link><pubDate>Thu, 11 Jun 2009 01:13:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9725147</guid><dc:creator>dimeby8</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/dimeby8/comments/9725147.aspx</comments><wfw:commentRss>http://blogs.msdn.com/dimeby8/commentrss.aspx?PostID=9725147</wfw:commentRss><description>&lt;P&gt;There isn’t an easy way to set the category of an Unidentified network in Windows 7 RC+ builds. By default, an Unidentified network will be set to Public for security. Often, the Unidentified network is setup intentionally (e.g. two machines connected via a hub; a network TV tuner, etc.). In these cases, Home/Work is a better category to allow common network tasks to succeed.&lt;/P&gt;
&lt;P&gt;Below is a Powershell script to change the category from Public to Work (identical to Home, except Homegroup won’t be started up). You need to be already connected to the ‘Unidentified network’ prior to running this script. &lt;/P&gt;
&lt;P&gt;&lt;TEXTAREA style="WIDTH: 100%; HEIGHT: 329px; FONT-SIZE: 8pt" readOnly&gt;// 
// Name: ChangeCategory.ps1 
// Copyright: Microsoft 2009 
// Revision: 1.0 
// 
// This script can be used to change the network category of 
// an 'Unidentified' network to Private to allow common network 
// activity. This script should only be run when connected to 
// a network that is trusted since it will also affect the 
// firewall profile used. 
// This script is provided as-is and Microsoft does not assume any 
// liability. This script may be redistributed as long as the file 
// contains these terms of use unmodified. 
// 
// Usage: 
// Start an elevated Powershell command window and execute 
// ChangeCategory.ps1 
// 
$NLMType = [Type]::GetTypeFromCLSID(‘DCB00C01-570F-4A9B-8D69-199FDBA5723B’)
$INetworkListManager = [Activator]::CreateInstance($NLMType)

$NLM_ENUM_NETWORK_CONNECTED  = 1
$NLM_NETWORK_CATEGORY_PUBLIC = 0x00
$NLM_NETWORK_CATEGORY_PRIVATE = 0x01
$UNIDENTIFIED = "Unidentified network"

$INetworks = $INetworkListManager.GetNetworks($NLM_ENUM_NETWORK_CONNECTED)

foreach ($INetwork in $INetworks)
{
    $Name = $INetwork.GetName()
    $Category = $INetwork.GetCategory()

    if ($INetwork.IsConnected -and ($Category -eq $NLM_NETWORK_CATEGORY_PUBLIC) -and ($Name -eq $UNIDENTIFIED))
    {
        $INetwork.SetCategory($NLM_NETWORK_CATEGORY_PRIVATE)
    }
}
&lt;/TEXTAREA&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Save the script locally as ChangeCategory.ps1 (say under c:\) &lt;/LI&gt;
&lt;LI&gt;Launch an elevated Powershell command window &lt;/LI&gt;
&lt;LI&gt;Change your execution policy to allow the script to run (if not already changed) &lt;BR&gt;&lt;B&gt;PS&amp;gt; set-executionpolicy remotesigned&lt;/B&gt; &lt;/LI&gt;
&lt;LI&gt;Run the script &lt;BR&gt;&lt;B&gt;PS&amp;gt; c:\ChangeCategory.ps1&lt;/B&gt; &lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;At the end of this, the category for the Unidentified network will show as Work in Network and Sharing Center. This setting is not persisted across re-connects and you will require to run the script again to change the category. Be sure to run the script only for networks that you trust since this affects the firewall profile that will be used.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9725147" width="1" height="1"&gt;</description></item><item><title>Where is wpdmtpextensions.h?</title><link>http://blogs.msdn.com/dimeby8/archive/2007/05/15/where-is-wpdmtpextensions-h.aspx</link><pubDate>Wed, 16 May 2007 02:29:09 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2659434</guid><dc:creator>dimeby8</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/dimeby8/comments/2659434.aspx</comments><wfw:commentRss>http://blogs.msdn.com/dimeby8/commentrss.aspx?PostID=2659434</wfw:commentRss><description>&lt;p&gt;The header file - Wpdmtpextensions.h - has been referenced in several of my posts and is needed to talk MTP to the device through WPD. The header file is not available in the Vista SDK/WDK or the WMP 11 SDK, but is planned for inclusion in the Windows Server code name "Longhorn" SDK.&lt;/p&gt; &lt;p&gt;I've just received a heads-up from the &lt;a href="http://blogs.msdn.com/wpdblog/" target="_blank"&gt;WPD team&lt;/a&gt; that the Server SDK has been published as a Beta (&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=58726ACA-8D84-4683-8959-BE0038DA7084&amp;amp;displaylang=en" target="_blank"&gt;link&lt;/a&gt;). Once you install the Server SDK, you can copy over wpdmtpextensions.h file to your desired SDK (e.g. Vista SDK/Visual Studio SDK) include folder if needed.&amp;nbsp;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2659434" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/dimeby8/archive/tags/WPD/default.aspx">WPD</category><category domain="http://blogs.msdn.com/dimeby8/archive/tags/MTP/default.aspx">MTP</category></item><item><title>Creating a WPD playlist object in C#</title><link>http://blogs.msdn.com/dimeby8/archive/2007/01/08/creating-a-wpd-playlist-object-in-c.aspx</link><pubDate>Tue, 09 Jan 2007 02:44:04 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1436353</guid><dc:creator>dimeby8</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/dimeby8/comments/1436353.aspx</comments><wfw:commentRss>http://blogs.msdn.com/dimeby8/commentrss.aspx?PostID=1436353</wfw:commentRss><description>&lt;p&gt;This is a C# follow-up post on the &lt;a href="http://blogs.msdn.com/dimeby8/archive/2006/11/08/transferring-playlists-through-wpd.aspx"&gt;earlier C++ playlist creation post&lt;/a&gt;. Be sure to read the earlier post for background information on playlists and how it stores references. We will also re-use the &lt;em&gt;StringToPropVariant&lt;/em&gt; helper function that we defined in our &lt;a href="http://blogs.msdn.com/dimeby8/archive/2007/01/08/creating-wpd-propvariants-in-c-without-using-interop.aspx"&gt;previous post&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;To create a playlist object, the objects to be referenced should already have been transferred previously to the device. We'll write a function that will create a brand new playlist and set the references at creation-time. Setting the references is as easy as setting a property value, specifically the WPD_OBJECT_REFERENCES property.&lt;/p&gt;&lt;pre&gt;static void CreatePlaylistObject(
        PortableDeviceApiLib.PortableDeviceClass pPortableDevice,
        string parentID,
        string filename,
        ref string[] refObjectIDs,
        ref string newObjectID)
{
    // Get content interface required to create object
    PortableDeviceApiLib.IPortableDeviceContent pContent;
    pPortableDevice.Content(out pContent);

    // Create properties collection to send while creating object
    PortableDeviceApiLib.IPortableDeviceValues pValues =
        (PortableDeviceApiLib.IPortableDeviceValues)
            new PortableDeviceTypesLib.PortableDeviceValuesClass();

    pValues.SetStringValue(ref PortableDevicePKeys.WPD_OBJECT_PARENT_ID,
                            parentID);
    pValues.SetStringValue(ref PortableDevicePKeys.WPD_OBJECT_ORIGINAL_FILE_NAME,
                            filename);
    pValues.SetStringValue(ref PortableDevicePKeys.WPD_OBJECT_NAME,
                            filename);
    pValues.SetGuidValue(ref PortableDevicePKeys.WPD_OBJECT_FORMAT,
                            ref PortableDeviceGuids.WPD_OBJECT_FORMAT_WPLPLAYLIST);

    // References are stored in a PropVariantCollection object
    PortableDeviceApiLib.IPortableDevicePropVariantCollection pRefIDs =
        (PortableDeviceApiLib.IPortableDevicePropVariantCollection)
            new PortableDeviceTypesLib.PortableDevicePropVariantCollection();

    // Add the string object IDs to the references property
    for (int i = 0; i &amp;lt; refObjectIDs.Length; i++)
    {
        PortableDeviceApiLib.tag_inner_PROPVARIANT propvarValue;
        StringToPropVariant(refObjectIDs[i], out propvarValue);

        pRefIDs.Add(ref propvarValue);
    }

    // Add the references property to the property collection
    pValues.SetIPortableDevicePropVariantCollectionValue(
        ref PortableDevicePKeys.WPD_OBJECT_REFERENCES, pRefIDs);

    // Create the playlist object using the CreateObjectWithPropertiesOnly API
    // The properties to be set have already been defined in pValues
    pContent.CreateObjectWithPropertiesOnly(pValues, ref newObjectID);
}
&lt;/pre&gt;
&lt;p&gt;Since the playlist object does not require any data to be transferred, we will be using the &lt;em&gt;CreateObjectWithPropertiesOnly&lt;/em&gt; API to create it. The function takes in the parent object i.e. the location at which the playlist object should be created and&amp;nbsp;the name to use for the object. The object IDs that the playlist object will reference are passed in as a string array. The function will return the object ID of the new playlist object on success.&lt;/p&gt;
&lt;p&gt;We create an &lt;em&gt;IPortableDeviceValues&lt;/em&gt; instance - pValues -&amp;nbsp;that will hold the properties of the playlist object to be applied. We set the required parent object ID, name and format properties. To add the references, we convert each string into a PROPVARIANT using our &lt;em&gt;StringToPropVariant&lt;/em&gt; converter. We then add the PROPVARIANT into an &lt;em&gt;IPortableDevicePropVariantCollection &lt;/em&gt;object. &lt;/p&gt;
&lt;p&gt;Once we are done converting the input string array of object IDs into a PropVariant collection, we add the WPD_OBJECT_REFERENCES property to the &lt;em&gt;pValues &lt;/em&gt;values collection with the PropVariant collection as the value (which is the list of object IDs to add as a reference).&lt;/p&gt;
&lt;p&gt;Once the properties have been prepared, we call the &lt;em&gt;CreateObjectWithPropertiesOnly&lt;/em&gt; API and create the object. Once the API completes successfully, a new object ID is returned which is the object ID of the newly created playlist object. &lt;/p&gt;
&lt;p&gt;Invoking this function would look something like this:&lt;/p&gt;&lt;pre&gt;string newObjectID = "";

// Set the playlist to reference objects o1 and o2
string[] refObjectIDs = new string[2];
refObjectIDs[0] = "o1";
refObjectIDs[1] = "o2";

CreatePlaylistObject(pPortableDevice, "s10001", "hits2006.pls",
                            ref refObjectIDs, ref newObjectID);
&lt;/pre&gt;
&lt;p&gt;Creating properties-only objects of other formats follows the same style. An example of another properties-only object is a &lt;em&gt;Contact &lt;/em&gt;object - name, email, phone, etc. are just properties of the object itself. The object doesn't have any data. You can modify the function we have just presented to use the appropriate WPD_OBJECT_FORMAT code and create a contact object.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1436353" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/dimeby8/archive/tags/WPD/default.aspx">WPD</category><category domain="http://blogs.msdn.com/dimeby8/archive/tags/C_2300_/default.aspx">C#</category></item><item><title>Creating WPD PROPVARIANTs in C# without using interop</title><link>http://blogs.msdn.com/dimeby8/archive/2007/01/08/creating-wpd-propvariants-in-c-without-using-interop.aspx</link><pubDate>Tue, 09 Jan 2007 02:23:38 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1436283</guid><dc:creator>dimeby8</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/dimeby8/comments/1436283.aspx</comments><wfw:commentRss>http://blogs.msdn.com/dimeby8/commentrss.aspx?PostID=1436283</wfw:commentRss><description>&lt;p&gt;Previous posts have covered how to create, manage and marshal PROPVARIANTs using interop. Here's a way on how to create a PROPVARIANT without interop. &lt;/p&gt; &lt;p&gt;The &lt;em&gt;IPortableDeviceValues&lt;/em&gt; interface exposes a &lt;em&gt;SetStringValue&lt;/em&gt; method that allows a regular C# string to be added into the collection. IPortableDeviceValues also exposes a &lt;em&gt;GetValue&lt;/em&gt; method which lets us retrieve any added property value as a PROPVARIANT. Armed with these two facts, it's pretty obvious how we can manufacture a string PROPVARIANT.&lt;/p&gt;&lt;pre&gt;static void StringToPropVariant(string value,
        out PortableDeviceApiLib.tag_inner_PROPVARIANT propvarValue)
{
    // We'll use an IPortableDeviceValues object to transform the
    // string into a PROPVARIANT
    PortableDeviceApiLib.IPortableDeviceValues pValues =
        (PortableDeviceApiLib.IPortableDeviceValues)
            new PortableDeviceTypesLib.PortableDeviceValuesClass();

    // We insert the string value into the IPortableDeviceValues object
    // using the SetStringValue method
    pValues.SetStringValue(ref PortableDevicePKeys.WPD_OBJECT_ID, value);

    // We then extract the string into a PROPVARIANT by using the 
    // GetValue method
    pValues.GetValue(ref PortableDevicePKeys.WPD_OBJECT_ID, 
                                out propvarValue);
}
&lt;/pre&gt;
&lt;p&gt;We create an instance of an IPortableDeviceValues object named &lt;em&gt;pValues&lt;/em&gt;. We then call SetStringValue with a dummy property key and the string to be converted. pValues now contains exactly one item - a string value which is internally held as a PROPVARIANT. To extract the internally held PROPVARIANT, we call &lt;em&gt;GetValue&lt;/em&gt; which returns us a PROPVARIANT value.&lt;/p&gt;
&lt;p&gt;This example function can be extended for other PROPVARIANT types. Use &lt;em&gt;Object Browser&lt;/em&gt; and take a look at the Set* methods exposed by IPortableDeviceValues. Follow the same paradigm - use Set*Value for your source target type and then use GetValue to extract it as a PROPVARIANT.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1436283" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/dimeby8/archive/tags/WPD/default.aspx">WPD</category><category domain="http://blogs.msdn.com/dimeby8/archive/tags/C_2300_/default.aspx">C#</category></item><item><title>Connecting to a WPD device in C#</title><link>http://blogs.msdn.com/dimeby8/archive/2006/12/21/connecting-to-a-wpd-device-in-c.aspx</link><pubDate>Fri, 22 Dec 2006 02:51:27 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1343844</guid><dc:creator>dimeby8</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/dimeby8/comments/1343844.aspx</comments><wfw:commentRss>http://blogs.msdn.com/dimeby8/commentrss.aspx?PostID=1343844</wfw:commentRss><description>&lt;p&gt;This is the C# equivalent of an &lt;a href="http://blogs.msdn.com/dimeby8/archive/2006/09/27/774259.aspx"&gt;earlier C++ post&lt;/a&gt; on connecting to a WPD device. We'll concentrate on the implementation here - you may refer back to that earlier&amp;nbsp;post for further explanation.&lt;/p&gt;&lt;pre&gt;// Create our client information collection
PortableDeviceApiLib.IPortableDeviceValues pValues = 
        (PortableDeviceApiLib.IPortableDeviceValues)
            new PortableDeviceTypesLib.PortableDeviceValuesClass();

// We have to provide at the least our name, version, revision
pValues.SetStringValue(
        ref PortableDevicePKeys.WPD_CLIENT_NAME, "Sample Client");
pValues.SetUnsignedIntegerValue(
        ref PortableDevicePKeys.WPD_CLIENT_MAJOR_VERSION, 1);
pValues.SetUnsignedIntegerValue(
        ref PortableDevicePKeys.WPD_CLIENT_MINOR_VERSION, 0);
pValues.SetUnsignedIntegerValue(
        ref PortableDevicePKeys.WPD_CLIENT_REVISION, 2);

// Create a new IPortableDevice instance
PortableDeviceApiLib.PortableDeviceClass pPortableDevice = 
        new PortableDeviceApiLib.PortableDeviceClass();

// We are now ready to open a connection to the device
// We'll assume deviceID contains a valid WPD device path and connect to it
pPortableDevice.Open(deviceID, pValues);
&lt;/pre&gt;
&lt;p&gt;As you can see, it's pretty straight-forward to open a connection to a WPD device. We will set up our client information in a PortableDeviceValues collection and then send in the collection to the &lt;em&gt;Open&lt;/em&gt; API call. If the device ID was valid, then a device connection will be opened and we can begin to use &lt;em&gt;pPortableDevice&lt;/em&gt; to communicate with the device.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1343844" width="1" height="1"&gt;</description></item><item><title>Marshalling variant properties in C#</title><link>http://blogs.msdn.com/dimeby8/archive/2006/12/12/marshalling-variant-properties-in-c.aspx</link><pubDate>Wed, 13 Dec 2006 02:43:10 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1269114</guid><dc:creator>dimeby8</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/dimeby8/comments/1269114.aspx</comments><wfw:commentRss>http://blogs.msdn.com/dimeby8/commentrss.aspx?PostID=1269114</wfw:commentRss><description>&lt;p&gt;This post is a continuation of the one&amp;nbsp;covering &lt;a href="http://blogs.msdn.com/dimeby8/archive/2006/12/11/wpd-property-retrieval-in-c.aspx"&gt;WPD property retrieval in C#&lt;/a&gt;. That post explained how to marshal strings and the basic int properties. Handling other types such as VT_DATE and VT_BOOL is trickier so I'll try to cover them here.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;VT_DATE&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;VT_DATE variants hold the date time value in a field of type &lt;em&gt;double&lt;/em&gt;. So we'll need to update our C# PropVariant definition to include a double field. &lt;/p&gt;&lt;pre&gt;[StructLayout(LayoutKind.Explicit, Size = 16)]
public struct PropVariant
{
    [FieldOffset(0)]
    public short variantType;
    [FieldOffset(8)]
    public IntPtr pointerValue;
    [FieldOffset(8)]
    public byte byteValue;
    [FieldOffset(8)]
    public long longValue;
    &lt;strong&gt;&lt;em&gt;[FieldOffset(8)]
    public double dateValue;&lt;/em&gt;&lt;/strong&gt;
} 
&lt;/pre&gt;
&lt;p&gt;Once we have a field that can hold the value, we need to convert it to something C# can understand. PROPVARIANTs are really OLE automation structures, so we can use the &lt;em&gt;DateTime.FromOADate&lt;/em&gt; method to coerce our double into a &lt;em&gt;DateTime&lt;/em&gt; object.&lt;/p&gt;&lt;pre&gt;DateTime date = DateTime.FromOADate(pvValue.dateValue);
&lt;/pre&gt;
&lt;p&gt;To convert from &lt;em&gt;DateTime&lt;/em&gt; to the double value in the PropVariant, use &lt;em&gt;DateTime.ToOADate&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;VT_BOOL&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;VT_BOOL variants hold the bool value in a field of type &lt;em&gt;short&lt;/em&gt;. So we'll need to update the C# PropVariant definition to include the short field.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;pre&gt;[StructLayout(LayoutKind.Explicit, Size = 16)]
public struct PropVariant
{
    [FieldOffset(0)]
    public short variantType;
    [FieldOffset(8)]
    public IntPtr pointerValue;
    [FieldOffset(8)]
    public byte byteValue;
    [FieldOffset(8)]
    public long longValue;
    [FieldOffset(8)]
    public double dateValue;
    &lt;strong&gt;&lt;em&gt;[FieldOffset(8)]
    public short boolValue;&lt;/em&gt;&lt;/strong&gt;
} 
&lt;/pre&gt;
&lt;p&gt;Once we have the short field, we can convert it to a bool using &lt;em&gt;Convert.ToBoolean&lt;/em&gt;.&lt;/p&gt;&lt;pre&gt;bool b = Convert.ToBoolean(pvValue.boolValue);
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;VT_CLSID&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;VT_CLSID variants hold the GUID value in a field of type &lt;em&gt;CLSID*&lt;/em&gt;. The value itself is a pointer to a blob of memory allocated using CoTaskMemAlloc. Since we are dealing with a pointer, we can use the &lt;em&gt;pointerValue&lt;/em&gt; field to access this.&lt;/p&gt;
&lt;p&gt;We then use &lt;em&gt;PtrToStructure&lt;/em&gt; (similar to how we handled LPWSTR) to marshal this pointer into a Guid we can use ourselves.&lt;/p&gt;&lt;pre&gt;Guid guid = (Guid)Marshal.PtrToStructure(pvValue.pointerValue, typeof(Guid));&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;StructureToPtr&lt;/em&gt; can be used to marshal a Guid back into the PropVariant.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I'll update this post if I encounter other types that require special handling. Feel free to leave a comment on any that you come across as well.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1269114" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/dimeby8/archive/tags/WPD/default.aspx">WPD</category><category domain="http://blogs.msdn.com/dimeby8/archive/tags/C_2300_/default.aspx">C#</category></item><item><title>WPD Content Enumeration in C#</title><link>http://blogs.msdn.com/dimeby8/archive/2006/12/12/wpd-content-enumeration-in-c.aspx</link><pubDate>Tue, 12 Dec 2006 22:10:13 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1268035</guid><dc:creator>dimeby8</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/dimeby8/comments/1268035.aspx</comments><wfw:commentRss>http://blogs.msdn.com/dimeby8/commentrss.aspx?PostID=1268035</wfw:commentRss><description>&lt;p&gt;WPD content enumeration in C# is pretty close to the C++ style. Here's a basic example that enumerates the object IDs of the objects present on the device.&lt;/p&gt;&lt;pre&gt;static void Enumerate(
    ref PortableDeviceApiLib.IPortableDeviceContent pContent,
    string parentID,
    string indent)
{
    //
    // Output object ID
    //
    Console.WriteLine(indent + parentID);

    indent += "    ";

    //
    // Enumerate children (if any)
    //
    PortableDeviceApiLib.IEnumPortableDeviceObjectIDs pEnum;
    pContent.EnumObjects(0, parentID, null, out pEnum);

    uint cFetched = 0;
    do
    {
        string objectID;
        pEnum.Next(1, out objectID, ref cFetched);

        if (cFetched &amp;gt; 0)
        {
            //
            // Recurse into children
            //
            Enumerate(ref pContent, objectID, indent);
        }
    } while (cFetched &amp;gt; 0);
}

static void StartEnumerate(
    ref PortableDeviceApiLib.PortableDeviceClass pPortableDevice)
{
    //
    // Get content interface required to enumerate
    //
    PortableDeviceApiLib.IPortableDeviceContent pContent;
    pPortableDevice.Content(out pContent);

    Enumerate(ref pContent, "DEVICE", "");
}
&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;StartEnumerate&lt;/em&gt;&amp;nbsp;is the entry point into the enumeration. This needs to be called with a valid opened device connection. StartEnumerate then defers to the recursive &lt;em&gt;Enumerate&lt;/em&gt; function which requires the parent object ID to enumerate. Using the &lt;em&gt;EnumObjects&lt;/em&gt; API, we get back the &lt;em&gt;IEnumPortableDeviceObjectIDs&lt;/em&gt; enumerator. For each object in the enumeration, we call &lt;em&gt;Enumerate&lt;/em&gt; again.&lt;/p&gt;
&lt;p&gt;Caveats:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;IEnumPortableDeviceObjectIDs::Next&lt;/em&gt; allows more than one object IDs to be returned. We don't take advantage of this optimization since the default interop doesn't handle the array very well. If you need to use this, you will have to edit the interop by hand and fix up the assembly to handle the array correctly.&lt;/li&gt;&lt;/ul&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1268035" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/dimeby8/archive/tags/WPD/default.aspx">WPD</category><category domain="http://blogs.msdn.com/dimeby8/archive/tags/C_2300_/default.aspx">C#</category></item><item><title>Setting WPD properties in C#</title><link>http://blogs.msdn.com/dimeby8/archive/2006/12/11/setting-wpd-properties-in-c.aspx</link><pubDate>Mon, 11 Dec 2006 23:43:18 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1260925</guid><dc:creator>dimeby8</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/dimeby8/comments/1260925.aspx</comments><wfw:commentRss>http://blogs.msdn.com/dimeby8/commentrss.aspx?PostID=1260925</wfw:commentRss><description>&lt;p&gt;Since setting a WPD property requires manipulating a PROPVARIANT structure through interop, we must make use of the marshalling rules we set in our &lt;a href="http://blogs.msdn.com/dimeby8/archive/2006/12/11/wpd-property-retrieval-in-c.aspx"&gt;last post&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;We'll take a look at a function that allows string properties to be set. &lt;/p&gt;&lt;pre&gt;static void SetStringValue(
    PortableDeviceApiLib.PortableDeviceClass pPortableDevice,
    string objectID,
    ref PortableDeviceApiLib._tagpropertykey propKey,
    string newValue)
{
    //
    // Retrieve IPortableDeviceContent interface required to
    // obtain the IPortableDeviceProperties interface
    //
    PortableDeviceApiLib.IPortableDeviceContent pContent;
    pPortableDevice.Content(out pContent);

    //
    // Retrieve IPortableDeviceProperties interface required
    // to get all the properties
    //
    PortableDeviceApiLib.IPortableDeviceProperties pProperties;
    pContent.Properties(out pProperties);

    //
    // Create the Values collection to hold the value to be set
    //
    PortableDeviceApiLib.IPortableDeviceValues pSetValues = 
        (PortableDeviceApiLib.IPortableDeviceValues)
            new PortableDeviceTypesLib.PortableDeviceValuesClass();

    //
    // Use the C# PropVariant definition to set the string value
    //
    PropVariant pvSet = new PropVariant();
    pvSet.variantType = 31; // VT_LPWSTR
    pvSet.pointerValue = Marshal.StringToCoTaskMemUni(newValue);

    //
    // Marshal our definition into a pointer
    //
    IntPtr ptrValue = Marshal.AllocHGlobal(Marshal.SizeOf(pvSet));
    Marshal.StructureToPtr(pvSet, ptrValue, false);

    //
    // Marshal pointer into the interop PROPVARIANT 
    //
    PortableDeviceApiLib.tag_inner_PROPVARIANT ipSet =
      (PortableDeviceApiLib.tag_inner_PROPVARIANT)
        Marshal.PtrToStructure(ptrValue, typeof(PortableDeviceApiLib.tag_inner_PROPVARIANT));

    //
    // Call the SetValues API to set the specified property
    //
    pSetValues.SetValue(ref propKey, ref ipSet);

    PortableDeviceApiLib.IPortableDeviceValues pResults;
    pProperties.SetValues(objectID, pSetValues, out pResults);
}
&lt;/pre&gt;
&lt;p&gt;The example assumes that a device connection has already been opened. For this function to build, the PropVariant definition needs to be present and &lt;a href="http://blogs.msdn.com/dimeby8/archive/2006/12/06/where-are-the-wpd-property-keys-in-c.aspx"&gt;PortableDeviceConstants.cs&lt;/a&gt; needs to be part of the project.&lt;/p&gt;
&lt;p&gt;We first acquire the &lt;em&gt;IPortableDeviceProperties&lt;/em&gt;&amp;nbsp;interface since that exposes the &lt;em&gt;SetValues&lt;/em&gt; API method. Next we prepare the PROPVARIANT of vartype VT_LPWSTR that needs to be sent in. We first create an instance of the C# definition and set the pointer value to a marshalled instance of the value to be set using &lt;em&gt;Marshal.StringToCoTaskMemUni&lt;/em&gt;. We next marshal our definition into a pointer and then re-marshal the pointer into the &lt;em&gt;tag_inner_PROPVARIANT&lt;/em&gt; type expected by the API. This final value is then added to the values collection and this collection is sent down to the driver via the &lt;em&gt;SetValues&lt;/em&gt; API.&lt;/p&gt;
&lt;p&gt;This style of preparing the PROPVARIANT is common across different APIs. e.g. The &lt;em&gt;Delete &lt;/em&gt;API expects a PropVariantCollection. All that needs to be done is prepare the PROPVARIANT using the style above and then add the prepared PROPVARIANT into a PropVariantCollection. This collection can then be sent down with the &lt;em&gt;Delete&lt;/em&gt; API.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1260925" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/dimeby8/archive/tags/WPD/default.aspx">WPD</category><category domain="http://blogs.msdn.com/dimeby8/archive/tags/C_2300_/default.aspx">C#</category></item><item><title>WPD property retrieval in C#</title><link>http://blogs.msdn.com/dimeby8/archive/2006/12/11/wpd-property-retrieval-in-c.aspx</link><pubDate>Mon, 11 Dec 2006 23:17:53 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1260807</guid><dc:creator>dimeby8</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/dimeby8/comments/1260807.aspx</comments><wfw:commentRss>http://blogs.msdn.com/dimeby8/commentrss.aspx?PostID=1260807</wfw:commentRss><description>&lt;p&gt;WPD property values are retrieved as PROPVARIANTs through the WPD API. Unfortunately there is no native support for PROPVARIANTs in C#. To correctly retrieve the property values (or anything that is in a PROPVARIANT) through the WPD API in C#, we must use marshalling.&lt;/p&gt; &lt;p&gt;&lt;em&gt;PortableDeviceApiLib.tag_inner_PROPVARIANT&lt;/em&gt; is the data-type exposed through the WPD Interop layer. This data-type exposes the &lt;em&gt;.vt&lt;/em&gt; member, but it does not expose the anonymous union which is the &lt;em&gt;raison d'être&lt;/em&gt; for the PROPVARIANT structure. &lt;/p&gt; &lt;p&gt;To get to the union, we need to re-define the PROPVARIANT data-type in C#. We can get by with the following definition:&lt;/p&gt;&lt;pre&gt;using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Explicit, Size = 16)]
public struct PropVariant
{
    [FieldOffset(0)]
    public short variantType;
    [FieldOffset(8)]
    public IntPtr pointerValue;
    [FieldOffset(8)]
    public byte byteValue;
    [FieldOffset(8)]
    public long longValue;
} 
&lt;/pre&gt;
&lt;p&gt;This follows exactly the struct layout of a PROPVARIANT. We haven't included all the PROPVARIANT fields, feel free to add them as and when you need them. For our example, we'll manage with the ones above.&lt;/p&gt;
&lt;p&gt;Now that we have a C# specific PROPVARIANT definition, we should be able to convert back and forth to the interop version. This isn't as easy as a simple cast - we'll have to use marshalling to do this.&lt;/p&gt;
&lt;p&gt;To convert from the interop &lt;em&gt;tag_inner_PROPVARIANT&lt;/em&gt; to our C# &lt;em&gt;PropVariant&lt;/em&gt;: &lt;pre&gt;PortableDeviceApiLib.tag_inner_PROPVARIANT ipValue = 
                     new PortableDeviceApiLib.tag_inner_PROPVARIANT();

IntPtr ptrValue = Marshal.AllocHGlobal(Marshal.SizeOf(ipValue));
Marshal.StructureToPtr(ipValue, ptrValue, false);

PropVariant pv = (PropVariant)Marshal.PtrToStructure(p, typeof(PropVariant));
&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;To convert from our C# &lt;em&gt;PropVariant&lt;/em&gt; to the interop &lt;em&gt;tag_inner_PROPVARIANT&lt;/em&gt;: &lt;pre&gt;PropVariant pvValue = new PropVariant();

IntPtr ptrValue = Marshal.AllocHGlobal(Marshal.SizeOf(pvValue));
Marshal.StructureToPtr(pvValue, ptrValue, false);

PortableDeviceApiLib.tag_inner_PROPVARIANT ipValue =
    (PortableDeviceApiLib.tag_inner_PROPVARIANT)
    Marshal.PtrToStructure(ptrValue, typeof(PortableDeviceApiLib.tag_inner_PROPVARIANT));
&lt;/pre&gt;
&lt;p&gt;Essentially what we are doing for both cases is getting a pointer to the original structure and then casting it back (via marshalling) to the second structure.&lt;/p&gt;
&lt;p&gt;Now let's see this in action - we'll attempt to retrieve all the properties for the &lt;em&gt;DEVICE&lt;/em&gt; object and display the value for all string properties.&lt;/p&gt;&lt;pre&gt;static void DisplayProperties(
    PortableDeviceApiLib.PortableDeviceClass pPortableDevice, 
    string objectID)
{
    //
    // Retrieve IPortableDeviceContent interface required to
    // obtain the IPortableDeviceProperties interface
    //
    PortableDeviceApiLib.IPortableDeviceContent pContent;
    pPortableDevice.Content(out pContent);

    //
    // Retrieve IPortableDeviceProperties interface required
    // to get all the properties
    //
    PortableDeviceApiLib.IPortableDeviceProperties pProperties;
    pContent.Properties(out pProperties);

    //
    // Call the GetValues API, we specify null to indicate we
    // want to retrieve all properties
    //
    PortableDeviceApiLib.IPortableDeviceValues pPropValues;
    pProperties.GetValues(objectID, null, out pPropValues);

    //
    // Get count of properties
    //
    uint cPropValues = 0;
    pPropValues.GetCount(ref cPropValues);
    Console.WriteLine("Received " + cPropValues.ToString() + " properties");

    for (uint i = 0; i &amp;lt; cPropValues; i++)
    {
        //
        // Retrieve the property at index 'i'
        //
        PortableDeviceApiLib._tagpropertykey propKey = 
                        new PortableDeviceApiLib._tagpropertykey();
        PortableDeviceApiLib.tag_inner_PROPVARIANT ipValue = 
                        new PortableDeviceApiLib.tag_inner_PROPVARIANT();
        pPropValues.GetAt(i, ref propKey, ref ipValue);

        //
        // Allocate memory for the intermediate marshalled object
        // and marshal it as a pointer
        //
        IntPtr ptrValue = Marshal.AllocHGlobal(Marshal.SizeOf(ipValue));
        Marshal.StructureToPtr(ipValue, ptrValue, false);

        //
        // Marshal the pointer into our C# object
        //
        PropVariant pvValue = 
            (PropVariant)Marshal.PtrToStructure(ptrValue, typeof(PropVariant));

        //
        // Display the property if it a string (VT_LPWSTR is decimal 31)
        //
        if (pvValue.variantType == 31 /*VT_LPWSTR*/)
        {
            Console.WriteLine("{0}: Value is \"{1}\"", 
                (i + 1).ToString(), Marshal.PtrToStringUni(pvValue.pointerValue));
        }
        else
        {
            Console.WriteLine("{0}: Vartype is {1}", 
                (i + 1).ToString(), pvValue.variantType.ToString());
        }
        //PropVariant pv = new PropVariant(ip);
    }
}
&lt;/pre&gt;
&lt;p&gt;The example assumes that a device connection has already been opened. It also assumes that the PropVariant definition (from above) is present somewhere in the class definition. &lt;/p&gt;
&lt;p&gt;We need to start with obtaining the &lt;em&gt;IPortableDeviceProperties &lt;/em&gt;interface. Once we have the interface, we call the &lt;em&gt;GetValues&lt;/em&gt; API to retrieve the properties. This is in a ValuesCollection object, so we use &lt;em&gt;GetAt&lt;/em&gt; to retrieve each property. The retrieved property is of type &lt;em&gt;tag_inner_PROPVARIANT&lt;/em&gt; which we convert to our C# PropVariant definition using marshalling. Once we have the data in our PropVariant structure, we can reference the string by marshalling the pointer value in the PropVariant to a &lt;em&gt;string&lt;/em&gt; object.&lt;/p&gt;
&lt;p&gt;As an exercise, try extending this example to display the value for properties of different vartypes.&amp;nbsp; In our next post, we'll see how we can set property values.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1260807" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/dimeby8/archive/tags/WPD/default.aspx">WPD</category><category domain="http://blogs.msdn.com/dimeby8/archive/tags/C_2300_/default.aspx">C#</category></item><item><title>Where are the WPD property keys in C#?</title><link>http://blogs.msdn.com/dimeby8/archive/2006/12/06/where-are-the-wpd-property-keys-in-c.aspx</link><pubDate>Wed, 06 Dec 2006 22:15:20 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1224815</guid><dc:creator>dimeby8</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/dimeby8/comments/1224815.aspx</comments><wfw:commentRss>http://blogs.msdn.com/dimeby8/commentrss.aspx?PostID=1224815</wfw:commentRss><description>&lt;p&gt;If you followed the exercise from our &lt;a href="http://blogs.msdn.com/dimeby8/archive/2006/12/05/c-and-the-wpd-api.aspx"&gt;first C# post&lt;/a&gt;,&amp;nbsp;you must have noticed that the PortableDeviceApi and PortableDeviceTypes typelibs don't expose the &lt;a href="http://blogs.msdn.com/dimeby8/archive/2006/09/27/774526.aspx"&gt;WPD property keys&lt;/a&gt; such as WPD_OBJECT_ID, WPD_OBJECT_FORMAT, etc. This can be a major blocker since for starters, we need to specify a basic set of client information properties to open a connection to the device.&lt;/p&gt; &lt;p&gt;If you used C++, the WPD property keys&amp;nbsp;definitions could be brought in by linking against PortableDeviceGuids.lib. Linking against a C lib is not an option for a C# application. It's not even possible to generate a typelib for a C lib. The only option is to manually define each of the property keys all over again in your C# application.&lt;/p&gt; &lt;p&gt;The C++ PROPERTYKEY data type maps to the &lt;em&gt;PortableDeviceApiLib._tagpropertykey&lt;/em&gt; interop data type. We can look up the PROPERTYKEY declaration in PortableDevice.h and use that to generate an equivalent C# property key object.&lt;/p&gt; &lt;p&gt;Let's take a look at WPD_OBJECT_ID - the C++ definition (from PortableDevice.h) is:&lt;/p&gt;&lt;pre&gt;// 
// WPD_OBJECT_ID 
//   [ VT_LPWSTR ] Uniquely identifies object on the Portable Device. 
DEFINE_PROPERTYKEY( WPD_OBJECT_ID , 0xEF6B490D, 0x5CD8, 0x437A, 0xAF, 0xFC, 0xDA, 0x8B, 0x60, 0xEE, 0x4A, 0x3C , 2 ); 
&lt;/pre&gt;&lt;br&gt;Mapping this to C# would result in something like: &lt;pre&gt;class PortableDevicePKeys
{
    static PortableDevicePKeys()
    {
        WPD_OBJECT_ID.fmtid = new Guid(0xEF6B490D, 0x5CD8, 0x437A, 0xAF, 0xFC, 0xDA, 0x8B, 0x60, 0xEE, 0x4A, 0x3C);
        WPD_OBJECT_ID.pid = 2;
    }

    public static PortableDeviceApiLib._tagpropertykey WPD_OBJECT_ID;
}
&lt;/pre&gt;
&lt;p&gt;We can then reference the property as PortableDevicePKeys.WPD_OBJECT_ID whenever required.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Making life easier&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Since defining each of these property keys by hand may cause severe &lt;a href="http://en.wikipedia.org/wiki/Repetitive_strain_injury" target="_blank"&gt;RSI&lt;/a&gt;, here's&amp;nbsp;a little script that will generate the definitions for you given PortableDevice.h. In addition to generating the property keys, it will also generate the GUID definitions (such as for WPD_FUNCTIONAL_CATEGORY_STORAGE, WPD_OBJECT_FORMAT_WMA, etc.)&lt;/p&gt;
&lt;p&gt;&lt;textarea style="font-size: 8pt; width: 100%; height: 146px" rows="1" readonly cols="1"&gt;//
// Name: genCSinc.js
// Copyright: Microsoft 2006
// Revision: 1.0
//
// This script can be used to generate a C# .cs file that contains
// the equivalent WPD property-keys and GUIDs as defined in
// portabledevice.h
// This script is provided as-is and Microsoft does not assume any
// liability. This script may be redistributed as long as the file
// contains these terms of use unmodified.
//
// Usage:
// Switch to the folder where portabledevice.h is present and then run
//     cscript //nologo genCSinc.js
// This will generate portabledeviceconstants.cs. This .cs file can
// then be included in a C# project. 
// To use the propertykeys and the GUIDs, add "using PortableDeviceConstants;"
// to the target file.
// Propertykeys can then be referenced as PortableDevicePKeys.desired_prop_name
//     e.g. PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT
// GUIDs can be referenced as PortableDeviceGuids.desired_GUID_name
//     e.g. PortableDeviceGuids.WPD_OBJECT_FORMAT_ALL
//

//
// Use FSO to read/write input/output
//
var fso = new ActiveXObject("Scripting.FileSystemObject");

var f = null;
var fOut = null;
var sIn = "portabledevice.h";
var sOut = "portabledeviceconstants.cs";

//
// Check for input file
//
try
{
    f = fso.OpenTextFile(sIn);
}
catch(e)
{
    WScript.Echo("Expected portabledevice.h to be in the current folder!");
}

//
// Check for output file
//
try
{
    fOut = fso.OpenTextFile(sOut, 2, true);
}
catch(e)
{
    WScript.Echo("Cannot open " + sOut + " for writing!");
}

//
// Write out header
//
fOut.Write("\
using System;\r\n\
\r\n\
namespace PortableDeviceConstants\r\n\
{\r\n\
    class PortableDevicePKeys\r\n\
    {\r\n\
        static PortableDevicePKeys()\r\n\
        {\r\n\
");    

//
// RegEx declarations for PKEYs and GUIDs
//
//e.g. DEFINE_PROPERTYKEY( WPD_CLIENT_MINOR_VERSION , 0x204D9F0C, 0x2292, 0x4080, 0x9F, 0x42, 0x40, 0x66, 0x4E, 0x70, 0xF8, 0x59 , 4 ); 
var rePKEY = /\s*DEFINE_PROPERTYKEY\(\s*(\w+)\s*,\s*(.+)\s*,\s*(\d+)\s*\);/;
var arrPKEY = new Array();

//e.g. DEFINE_GUID(WPD_EVENT_DEVICE_RESET, 0x7755CF53, 0xC1ED, 0x44F3, 0xB5, 0xA2, 0x45, 0x1E, 0x2C, 0x37, 0x6B, 0x27 ); 
var reGUID = /\s*DEFINE_GUID\((\w+),\s(.+)\s\);/;
var arrGUID = new Array();

//
// Parse the file
//
while (!f.AtEndOfStream)
{
    var l = f.ReadLine();

    //
    // Check for PKEYs
    //
    if (l.match(rePKEY))
    {
        //
        // Write out initializations for the PKEYs
        //
        var sName = l.replace(rePKEY, "$1");
        var sGUID = l.replace(rePKEY, "$2");
        var sPID = l.replace(rePKEY, "$3");

        //WPD_CLIENT_NAME.fmtid = new Guid(0x204D9F0C, 0x2292, 0x4080, 0x9F, 0x42, 0x40, 0x66, 0x4E, 0x70, 0xF8, 0x59);
        //WPD_CLIENT_NAME.pid = 2; 
        
        fOut.Write("            " + sName + ".fmtid = new Guid( " + sGUID + ");\r\n");
        fOut.Write("            " + sName + ".pid = " + sPID + ";\r\n");
        fOut.Write("\r\n");

        //
        // Save the PKEY name for declaration at class level
        //
        arrPKEY.push(sName);
    }
    else if (l.match(reGUID))
    {
        //
        // Save the GUIDs since they go into a second class
        //
        var sName = l.replace(reGUID, "$1");
        var sGUID = l.replace(reGUID, "$2");

        arrGUID.push("public static Guid " + sName + " = new Guid( " + sGUID + " );");
    }
}

//
// Write out declarations for PKEYs
//
fOut.Write("        }\r\n\r\n");

for (var i = 0; i &amp;lt; arrPKEY.length; i++)
{
    fOut.Write("        " + "public static PortableDeviceApiLib._tagpropertykey " + arrPKEY[i] + ";\r\n");
}

fOut.Write("\
    } // class PortableDevicePKeys\r\n\
");

//
// Write out GUIDs
//
fOut.Write("\r\n\r\n");
fOut.Write("\
    class PortableDeviceGuids\r\n\
    {\r\n\
");

for (var i = 0; i &amp;lt; arrGUID.length; i++)
{
    fOut.Write("        " + arrGUID[i] + "\r\n");
}

//
// Write out footer
//
fOut.Write("\
    } // class PortableDeviceGuids\r\n\
} // namespace PortableDeviceConstants\r\n\
");

WScript.Echo("Done: " + sOut + " now contains C# WPD constants");
&lt;/textarea&gt; &lt;/p&gt;
&lt;p&gt;Copy the script from the text-box above, paste it into Notepad and save it as &lt;em&gt;gencsinc.js&lt;/em&gt;. Copy PortableDevice.h to the same folder as gencsinc.js and then run gencsinc.js using "&lt;em&gt;cscript gencsinc.js&lt;/em&gt;". This will generate a PortableDeviceConstants.cs file which you may add to your C# project.&lt;/p&gt;
&lt;p&gt;Once the generated file is added to your project, add "&lt;em&gt;using PortableDeviceConstants;&lt;/em&gt;" to your target C# source. To reference property keys, you can simply use &lt;em&gt;PortableDevicePKeys.propertyname&lt;/em&gt; (e.g. PortableDevicePKeys.WPD_OBJECT_ID) and to reference GUIDs, you can simply use &lt;em&gt;PortableDeviceGuids.guidname&lt;/em&gt; (e.g. PortableDeviceGuids.WPD_OBJECT_FORMAT_WMA).&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1224815" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/dimeby8/archive/tags/WPD/default.aspx">WPD</category><category domain="http://blogs.msdn.com/dimeby8/archive/tags/C_2300_/default.aspx">C#</category></item><item><title>Flying Wiimotes</title><link>http://blogs.msdn.com/dimeby8/archive/2006/12/06/flying-wiimotes.aspx</link><pubDate>Wed, 06 Dec 2006 21:23:48 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1224699</guid><dc:creator>dimeby8</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/dimeby8/comments/1224699.aspx</comments><wfw:commentRss>http://blogs.msdn.com/dimeby8/commentrss.aspx?PostID=1224699</wfw:commentRss><description>&lt;p&gt;I just bought a Wii and it has totally changed my gamer attitude, and I wasn't even a gamer to start with. No more button mashing anymore -&amp;nbsp;arm-swinging and flailing with some actual hand-eye coordination is what it's all about.&lt;/p&gt; &lt;p&gt;Of course with all the arm-thrashing, the controllers are bound to gain critical velocity and &lt;a href="http://www.wiihaveaproblem.com/" target="_blank"&gt;boldly go where no controller has gone before&lt;/a&gt;. &lt;/p&gt; &lt;p&gt;I guess I now need to bullet-proof my entertainment center,&amp;nbsp;shatter-proof my windows&amp;nbsp;and put padding on my walls.... Or maybe not - here's how &lt;a href="http://www.flickr.com/photos/98046567@N00/sets/72157594405700187/" target="_blank"&gt;a short fishing line can go a long way&lt;/a&gt; towards protecting you from yourself :).&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1224699" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/dimeby8/archive/tags/Misc/default.aspx">Misc</category></item><item><title>Enumerating WPD devices in C#</title><link>http://blogs.msdn.com/dimeby8/archive/2006/12/05/enumerating-wpd-devices-in-c.aspx</link><pubDate>Wed, 06 Dec 2006 04:06:32 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1214381</guid><dc:creator>dimeby8</dc:creator><slash:comments>14</slash:comments><comments>http://blogs.msdn.com/dimeby8/comments/1214381.aspx</comments><wfw:commentRss>http://blogs.msdn.com/dimeby8/commentrss.aspx?PostID=1214381</wfw:commentRss><description>&lt;p&gt;Let's take a look at how we can enumerate WPD devices in C#. This post assumes that you already have a project set up using &lt;a href="http://blogs.msdn.com/dimeby8/archive/2006/12/05/c-and-the-wpd-api.aspx"&gt;these instructions&lt;/a&gt;. (Update: You will also need to follow the disassembly/reassembly instructions below for this to work correctly.)&lt;/p&gt;&lt;pre&gt;static void Main(string[] args)
{
    //
    // Get an instance of the device manager
    //
    PortableDeviceApiLib.PortableDeviceManagerClass devMgr 
        = new PortableDeviceApiLib.PortableDeviceManagerClass();

    //
    // Probe for number of devices
    //
    uint cDevices = 1;
    devMgr.GetDevices(null, ref cDevices);

    //
    // Re-allocate if needed
    //
    if (cDevices &amp;gt; 0)
    {
        string[] deviceIDs = new string[cDevices];
        devMgr.GetDevices(deviceIDs, ref cDevices);

        for (int ndxDevices = 0; ndxDevices &amp;lt; cDevices; ndxDevices++)
        {
            Console.WriteLine("Device[{0}]: {1}", 
                    ndxDevices + 1, deviceIDs[ndxDevices]);
        }
    }
    else
    {
        Console.WriteLine("No WPD devices are present!");
    }
}
&lt;/pre&gt;
&lt;p&gt;This code maps almost line-by-line to the &lt;a href="http://blogs.msdn.com/dimeby8/archive/2006/08/15/701442.aspx"&gt;C++ enumeration example&lt;/a&gt;. We manufacture an instance of the device manager using PortableDeviceApiLib.PortableDeviceManagerClass. We then use the instance to probe how many devices are there. If you remember, the &lt;em&gt;GetDevices &lt;/em&gt;API will return back in cDevices the number of devices (actually the size of the string array that should be specified to retrieve all the device IDs). &lt;/p&gt;
&lt;p&gt;Once we know the number of devices, we allocate an appropriately sized array and then call &lt;em&gt;GetDevices&lt;/em&gt; again. This time, the array will contain all the device IDs. To display them, we simply iterate over the array and print them out.&lt;/p&gt;
&lt;p&gt;Gotchas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We could use the &lt;em&gt;string[]&lt;/em&gt;&amp;nbsp; notation since the GetDevices API returned an array of CoTaskMemAlloc'd LPWSTR strings 
&lt;li&gt;We can't use the &lt;em&gt;string&lt;/em&gt; datatype for&amp;nbsp;API calls that require a buffer allocated by the caller. &lt;em&gt;GetDeviceFriendlyName&lt;/em&gt;&amp;nbsp;is an example of this - such API calls require prior allocation of &lt;em&gt;ushort[]&lt;/em&gt; and then on success, character-by-character conversion to a C# &lt;em&gt;string&lt;/em&gt;.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;&lt;u&gt;Update&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Mike R. brought to my notice that the above sample only enumerates one device even if more than one are connected. This is a marshalling restriction - we can work around it by manually fixing up the generated Interop assembly. Follow the steps below to edit the assembly:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Disassemble the PortableDeviceApi interop using the command -&lt;br&gt;ildasm Interop.PortableDeviceApiLib.dll /out:pdapi.il 
&lt;li&gt;Open the IL in Notepad and search for the following string&lt;br&gt;&lt;em&gt;instance void&amp;nbsp; GetDevices([in][out] string&amp;amp;&amp;nbsp; marshal( lpwstr) pPnPDeviceIDs,&lt;/em&gt; 
&lt;li&gt;Replace all instances of the string above with the following string&lt;br&gt;&lt;em&gt;instance void&amp;nbsp; GetDevices([in][out] string[]&amp;nbsp; marshal([]) pPnPDeviceIDs,&lt;/em&gt; 
&lt;li&gt;Save the IL and reassemble the interop using the command -&lt;br&gt;ilasm pdapi.il /dll /output=Interop.PortableDeviceApiLib.dll&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;You can now rebuild your project. You can now first call GetDevices with a NULL parameter to get the count of devices and then call it again with an array to get the device IDs.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1214381" width="1" height="1"&gt;</description></item><item><title>C# and the WPD API</title><link>http://blogs.msdn.com/dimeby8/archive/2006/12/05/c-and-the-wpd-api.aspx</link><pubDate>Wed, 06 Dec 2006 00:45:15 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1214210</guid><dc:creator>dimeby8</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/dimeby8/comments/1214210.aspx</comments><wfw:commentRss>http://blogs.msdn.com/dimeby8/commentrss.aspx?PostID=1214210</wfw:commentRss><description>&lt;p&gt;There currently is no managed/C# flavor of the WPD API. This, of course, doesn't mean that you are locked out from using the WPD API if you want to use C#. Since the API is a set of COM interfaces, we simply have to interop across from C#. Granted it isn't as easy as a native C# implementation, but it gets the job done.&lt;/p&gt; &lt;p&gt;This and future posts assume that you are using Visual Studio. I used 2005, but other versions should work fine.&lt;/p&gt; &lt;p&gt;To start, create a new C# Console Application project. Next select the "Project&amp;gt;Add Reference ..." menu option. Click the "COM" tab in the "Add Reference" dialog and make sure the following items are selected and then click OK:&lt;br&gt;&lt;em&gt;PortableDeviceApi 1.0 Type Library&lt;/em&gt;&lt;br&gt;&lt;em&gt;PortableDeviceTypes 1.0 Type Library&lt;/em&gt;  &lt;p&gt;Once the references have been added, you can use the Object Browser (Ctrl+Alt+J) to check out the interesting stuff the interop brought in. You'll see two new nodes - &lt;em&gt;Interop.PortableDeviceApiLib &lt;/em&gt;and &lt;em&gt;Interop.PortableDeviceTypesLib&lt;/em&gt;. Under these nodes, you will find &lt;em&gt;PortableDeviceApiLib&lt;/em&gt; and &lt;em&gt;PortableDeviceTypesLib&lt;/em&gt;. We will need to use the latter names to reference other objects. As an exercise, spend some time comparing the objects and methods exposed through interop versus those available in WPD API through C++.&lt;/p&gt; &lt;p&gt;In our next post, we'll re-visit the &lt;a href="http://blogs.msdn.com/dimeby8/archive/2006/08/15/701442.aspx"&gt;C++ device enumeration example&lt;/a&gt; but with a C# twist.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1214210" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/dimeby8/archive/tags/WPD/default.aspx">WPD</category><category domain="http://blogs.msdn.com/dimeby8/archive/tags/C_2300_/default.aspx">C#</category></item><item><title>Help! WPD API calls randomly fail with 0x800700AA (ERROR_BUSY)</title><link>http://blogs.msdn.com/dimeby8/archive/2006/11/08/help-wpd-api-calls-randomly-fail-with-0x800700aa-error-busy.aspx</link><pubDate>Thu, 09 Nov 2006 07:20:08 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1042704</guid><dc:creator>dimeby8</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/dimeby8/comments/1042704.aspx</comments><wfw:commentRss>http://blogs.msdn.com/dimeby8/commentrss.aspx?PostID=1042704</wfw:commentRss><description>&lt;p&gt;If you notice your API calls are randomly failing with HRESULT_FROM_WIN32(ERROR_BUSY) / 0x800700AA / -2147024726, then it's likely that the device&amp;nbsp;driver is indeed busy doing something else. It could be that WMP is syncing content to the device, or maybe Explorer needs to refresh its view and is enumerating content on the device.&lt;/p&gt; &lt;p&gt;So what do you do? Simply deal with it. &lt;/p&gt; &lt;p&gt;The fact is that the driver has a choice when an operation is requested while it is busy doing something else. It can either block the contending request or it can return right away with a special error code (in this case ERROR_BUSY). &lt;/p&gt; &lt;p&gt;The current driver model does not advocate a particular choice; so to play it safe, you (as a WPD client app developer) should check if the error was HRESULT_FROM_WIN32(ERROR_BUSY). In that special case, you can randomly try the operation again in a while. Alternatively, you can put up a dialog telling the user that the device is busy doing something else and the user should try again later. Or maybe you can write an asynchronous wrapper around the API which frees you from worrying about all this. Whichever choice you make, just &lt;em&gt;don't treat it as a hard error&lt;/em&gt; and present the user with an error dialog since the user won't understand why it broke.&lt;/p&gt; &lt;p&gt;While special-handling ERROR_BUSY may seem to be a hack and inelegant, unfortunately the behavior is here to stay. Later iterations of the driver model may enforce/advocate an alternative behavior, but the backward-compatibility cross will still have to be carried.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1042704" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/dimeby8/archive/tags/WPD/default.aspx">WPD</category></item><item><title>Transferring playlists through WPD</title><link>http://blogs.msdn.com/dimeby8/archive/2006/11/08/transferring-playlists-through-wpd.aspx</link><pubDate>Thu, 09 Nov 2006 06:45:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1042606</guid><dc:creator>dimeby8</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/dimeby8/comments/1042606.aspx</comments><wfw:commentRss>http://blogs.msdn.com/dimeby8/commentrss.aspx?PostID=1042606</wfw:commentRss><description>&lt;P&gt;A playlist (.WPL, .M3U, etc.) is a text file which contains a list of filenames. This list is the "playlist". So transferring the playlist should be easy right? Well, yes it is - if you just want to transfer it as a text file...&lt;/P&gt;
&lt;P&gt;However if you want the playlist semantics to be sent to the device as well, you need to go an extra step (well, several extra steps :). Let's take a look.&lt;/P&gt;
&lt;P&gt;A .WPL playlist in WPD is an object of format WPD_OBJECT_FORMAT_WPLPLAYLIST. Similar WPD formats exist for .M3U, .MPL, .ASX, etc. To associate tracks with the playlist, you must make use of the WPD_OBJECT_REFERENCES parameter. The WPD_OBJECT_REFERENCES parameter is available for most container-style formats. It is of type IPortableDevicePropVariantCollection. &lt;/P&gt;
&lt;P&gt;Now even though WPD_OBJECT_REFERENCES is of type IPortableDevicePropVariantCollection, it can only legally hold PROPVARIANTs of a specific vartype i.e. VT_LPWSTR. Each string must correspond to a valid WPD object ID - these will be the object IDs that you want to associate with the playlist.&lt;/P&gt;Assume we have the following objects already on the device. &lt;PRE&gt;Store
 |
 |-- o1 (Happy.wma) [WPD_OBJECT_FORMAT_WMA]
 |-- o2 (Sad.wma)   [WPD_OBJECT_FORMAT_WMA]
&lt;/PRE&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;Next we want to add a playlist to the device. So we send the playlist first as a regular object of format WPLPLAYLIST. &lt;PRE&gt;Store
 |
 |-- o1 (Happy.wma) 
 |-- o2 (Sad.wma)
 |-- o3 (Emotions.wpl) [WPD_OBJECT_FORMAT_WPLPLAYLIST]
&lt;/PRE&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;Now that we have a WPLPLAYLIST object (given by handle &lt;EM&gt;o3&lt;/EM&gt;), we can set the WPD_OBJECT_REFERENCES property on it. Let's say we want to include &lt;EM&gt;o1&lt;/EM&gt; and &lt;EM&gt;o2&lt;/EM&gt; in the playlist. &lt;PRE&gt;LPWSTR pwszPlaylistObject = NULL;
if (hr == S_OK)
{
    // IMP: Add your code to transfer an object to the device and get back
    // a WPD object handle. We are assigning o3 just for this example
    pwszPlaylistObject = L"o3";
}

CComPtr&amp;lt;IPortableDeviceProperties&amp;gt; spProperties;
if (hr == S_OK)
{
    // IMP: Add your code to obtain the Properties interface from the
    // Device interface
}

CComPtr&amp;lt;IPortableDeviceValues&amp;gt; spValues;
CComPtr&amp;lt;IPortableDevicePropVariantCollection&amp;gt; spReferences;

if (hr == S_OK)
{
    // IMP: Add your code to CoCreate spValues and spReferences here
}

// Add o1 and o2 for the references 0 - your code will probably have
// a list of object IDs that you obtained prior by enumeration
PROPVARIANT pv = {0};
if (hr == S_OK)    
{
    pv.vt = VT_LPWSTR;
    pv.pwszVal = L"o1";
    
    hr = spReferences-&amp;gt;Add(&amp;amp;pv);
}

if (hr == S_OK)    
{
    pv.vt = VT_LPWSTR;
    pv.pwszVal = L"o2";
    
    hr = spReferences-&amp;gt;Add(&amp;amp;pv);
}

// Add the references to the values collection to send to the device
if (hr == S_OK)
{
    hr = spValues-&amp;gt;SetIPortableDevicePropVariantCollectionValue(
                        WPD_OBJECT_REFERENCES, spReferences);
}

// Set the references property on the Playlist object
CComPtr&amp;lt;IPortableDeviceValues&amp;gt; spResults;
if (hr == S_OK)
{
    hr = spProperties-&amp;gt;SetValues(pwszPlaylistObject, spValues, &amp;amp;spResults);
}
&lt;/PRE&gt;
&lt;P&gt;Briefly - you need to create an instance of a PropVariantCollection and add the object IDs that need to be part of the playlist to that collection. Next add that PropVariantCollection to the Values bag that we need to send down to the device. Be sure to specify the REFERENCES propertykey. Finally, use the SetValues API call to send the new value to the device.&lt;/P&gt;
&lt;P&gt;Note that:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Your objects need to already exist on the device before they can be added to the playlist. So if you are syncing a playlist, sync the referenced content first, get&amp;nbsp;the content object IDs&amp;nbsp;and then sync the playlist object and set the REFERENCES property. 
&lt;LI&gt;Modifying the REFERENCES property will &lt;EM&gt;clobber&lt;/EM&gt; any previous value. If you need to add a new object ID, read the property first, add to the collection and then set the property back. 
&lt;LI&gt;You can also set the references at the same time as playlist object creation. The CreateObject* APIs allow property values to be specified in the same call.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;As a curiosity, when you transfer the playlist object to the device, you can transfer just a 0-sized object using CreateObjectWithPropertiesOnly and skip the data since it isn't going to be processed by the device anyway.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1042606" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/dimeby8/archive/tags/WPD/default.aspx">WPD</category></item></channel></rss>