Item identification (PIDLs)

A PIDL (or an IDL) is a fundamental Windows Shell concept. At a high level, it’s pretty simple, as it’s just a “value” that represent a Shell item in the Shell namespace. It’s a bit like a full file system path for a physical file or folder, except it’s a binary object, it’s not a string.

Note: the names “PIDL” and “IDL” can be used interchangeably. The leading P stands for Pointer, but, for convenience, PIDL generally refers to the IDL itself rather than the pointer to it, especially in .NET where we rarely use pointers. To go further on that subject, Microsoft gives more gory details here Identifying Namespace Objects.

So, just like a full file system path is a list of string separated by the \ (slash) character,  a PIDL is a list (L is for List) of ID separated by a special PIDL separator (which if you really want to know is two consecutive zeros).

That seems complicated!

As a ShellBoost developer, you generally don’t need to know how PIDLs or IDs are made, allocated or destroyed, since ShellBoost provides two .NET classes that mask that complexity:

ShellItemId : represents an ID, a segment in the list

ShellItemIdList : represents a PIDL or IDL, which is a list of ShellItemId instance.

With ShellBoost, all Shell Items (including folders) are represented by an instance the ShellItem class. To match Windows Shell namespace organization, every ShellItem instance has an ID, which is an instance of the ShellItemId class. In fact, this identifier instance must be specified in the ShellItem class constructor. Here is the most basic constructor of the ShellItem class:

public ShellItem(ShellFolder parent, ShellItemId id)

As we can see, the constructor needs the parent folder, the folder that contains the new Shell Item, and an Id, uniquely representing the item in the folder.

How to create a ShellItemId?

The ShellItemId class has only one constructor:

protected ShellItemId(byte[] data)

As you see, it’s protected, and it takes whatever data you want, represented as a byte array. Fortunately, you probably will never need to create a new class from ShellItemId because ShellBoost provides a list of ready-made classes for most well-known data types:

KeyShellItemId: supports a Guid, sbyte, byte, short, ushort, int, uint, long, ulong, string, IntPtr, and byte[] types for the ID data, but you can use the specialized classes:

GuidKeyShellItemId: uses a Guid value as the ID

SByteKeyShellItemId: uses an sbyte value as the ID

ByteKeyShellItemId: uses a byte value as the ID

Int16KeyShellItemId: uses a short value as the ID

UInt16KeyShellItemId: uses an ushort value as the ID

Int32KeyShellItemId: uses an int value as the ID

UInt32KeyShellItemId: uses an uint value as the ID

Int64KeyShellItemId: uses a long value as the ID

UInt64KeyShellItemId: uses an ulong value as the ID

StringKeyShellItemId: uses a non-null string value as the ID

IntPtrKeyShellItemId: uses an IntPtr value as the ID

UInt64KeyShellItemId: uses an ulong value as the ID

So, for example, if the shell items in a ShellBoost folder come from rows of a table in a relational database, and the primary key of that table is a Guid value, you could use the GuidKeyShellItemId class to represent IDs of shell items.