How to create a "Shell IDList Array" to support dragging and dropping virtual files from C # in Windows Explorer?

I started trying to implement drag-and-drop virtual files (from a C # 4 / WPF application) with this coding tutorial . After spending some time trying to figure out the DV_E_FORMATETC error , I realized that I needed to support the Shell IDList Array data format. But it seems next to the null documentation about what this format actually does.

After some searching, I found this page in advanced data transfer , which stated that the IDList array of the shell was a pointer to the CIDA Structure . This CIDA structure then contains the number of PIDLs and a list of offsets. So what the hell is this PIDL? After some searching, this page , this means that it is a pointer to ITEMIDLIST , which itself contains one element, which is a SHITEMID list.

I read a little more, I still can’t say what several PIDLs are for, but there is one SHITEMID for each "level" in the path. At least this riddle is solved.

My next idea was to try and drag a file from another application using virtual files (WinSCP). I just got a MemoryStream for this format. At least I know what class a thing should provide, but that doesn't help at all to explain what to put in it. I tried to learn this MemoryStream based on the formats in the links above, but I was not successful. I just returned the garbage data, and one of the “cb” fields informed me that it was 18000 bytes, when the whole stream was only 539 bytes.

In addition, upon further reading, this page apparently implies that the data contained in the PIDL actually ends up being a path, and looking at the contents of the mentioned MemoryStream in a hex editor gave the path inside my local Temp directory (in any case broken into parts).

It seems that WinSCP just uses a shell extension to handle dropping on explorer, which I really don't want to resort to. However, it has an alternative mode in which it interrupts dragdrop until it moves to a temporary folder - this is acceptable to me, but I have no idea how to do this.

Now my questions are:

  • What is a valid "abID" member for SHITEMID? These virtual files exist only with my program; Will they be dragged to pass the "abID" later when it executes GetData? Should they be unique in the system?
  • How can I control the drag and drop tags that WinCCP does?
  • If I need to implement a shell extension for this, how would I even think about it? I'm sure I can easily find explanations for shell extension theory, but how can I support custom PIDL or something else?

Any help or even links explaining what I should do would be greatly appreciated.

Edit: So, as I actually did at the end:

I canceled most of the code from the CodeProject tutorial above, retaining the functions for creating the FileGroupDescriptor. Then I redefined the .Net IDataObject interface (and in general, I did not have to use the IDataObject COM interface at all). Then I have to synchronously download the file in the background and pass the MemoryStream from GetData (). Conveniently, the actual copy is in the background, but waiting for data is in the foreground. Thanks, researcher. Any reasonably large files are slow, but so far this is "working", which is more than I can say in the last few weeks.

I tried passing the PipeStream class, which I use for internal operations, but the researcher does not like this:

  • It tries to search even though this class has CanSeek as false.
  • It ignores the size that I send to FileGroupDescriptor, and just upload everything in the stream right now.

So, I'm not sure that the perfect case is really possible. However, thanks for your help. I give generosity to JPW because his answers ultimately put me on the right track.

+6
c # wpf drag-and-drop com windows-explorer
source share
3 answers

Disclaimer I am not an expert in Windows Shell programming and in COM programming, and especially not in COM programming using .NET.

Disclaimer 2 . Shell programming is quite complicated, and Windows Explorer is likely to fail. (Be sure to read the MSDN information when debugging shell extensions.)

This is what I can provide to answer your questions:

  • The abID value for SHITEMID is interrupted by the folder containing the corresponding item. Therefore, there is no valid or invalid information, since this data only interferes with the folder. Windows Explorer will transmit this data to identify a specific item. The abID should not be unique on the system, but it will probably be unique in the content folder (although this is not guaranteed). Under certain circumstances, the SHITEMID may persist, so in some cases it must be valid after a reboot (because of these memory references, the abID should be avoided).
  • As I understand it, IDataObject :: GetData will only be called if the actual data is needed (and maybe I'm wrong). So it should be fine if you extract the data to a temporary file in GetData and return the PIDL to this file (see http://support.microsoft.com/kb/132750/en-us , although I remember that it was suggested for this convenient method, but I don’t remember his name). Unfortunately, I don’t see a good way to delete a temporary file (as a last resort, you can do this when IDataObject is destroyed, but this will result in those temporary temp files that are no longer needed).
  • You will probably need custom PIDL support (including a custom PIDL manager) and custom IShellFolder implementation. However, most shell extension documents for C ++ and many functions are not well documented or not documented at all. For more information on PIDL, I would recommend reading http://msdn.microsoft.com/en-us/library/cc144090.aspx . In addition, you should search for “Enlarging the shell namespace” on the Internet, as there may be some information on this topic. Also check out the examples provided in the Windows SDK on this topic.

I hope you find the information helpful.

Change You can also implement QueryGetData and EnumerableFormatEtc accordingly to indicate that your object does not support this format. Windows Explorer may be trying a different format.

Change 2 . Although you’ve already decided on a solution, here’s some more information on how to drag and drop asynchronously (for large files), maybe you (or at least someone who is looking for an answer to a simulation problem, who is reading this) consider useful: http://msdn.microsoft.com/en-us/library/bb776904(VS.85).aspx#async

+2
source share

I think C # File Browser at http://www.codeproject.com/KB/miscctrl/FileBrowser.aspx is what will help you now.

These articles are invaluable.

Edanmo.ShellExtensions is an absolute must. http://www.mvps.org/emorcillo/en/code/shell/shellextensions.shtml

Note that some of these COM interfaces are already defined in .NET 2.0. (I have not tested 4.0, but I doubt that Microsoft has added additional support for Shell / COM interfaces.)

Additional materials

FOUND!

A complete guide for idiots to write namespace extensions - part I at http://www.codeproject.com/kb/shell/namespcextguide1.aspx . Is this what you are looking for?

+3
source share

All Articles