Creating something from nothing – and knowing it [Developer-friendly virtual file implementation for .NET refined!]


This blog has moved to a new location and comments have been disabled.

All old posts, new posts, and comments can be found on The blog of dlaa.me.

See you there!

Comments (19)
  1. iop111 says:

    Hi! Thanks for this interested article!

    I have a question. How could I drop an empty folder with your code?

  2. Delay says:

    iop111,

    That’s a great question – I honestly had no idea at first! But I’ve got good news. :)

    Firstly, if you just want to put the virtual file(s) in a subdirectory, you can use the code I’ve posted just like it is. To see this in action, just change the string "Alphabet.txt" to "Dir\Alphabet.txt" in the sample and you’ll see a "Dir" directory get created in the folder you drop to with an "Alphabet.txt" file inside it. You can even specify different directories for different virtual files in the same drag-drop operation!

    So that probably covers what you want 99% of the time. The remaining 1% is if you want the drop to create an *empty* directory. If that’s your goal, I don’t think the virtual file technique shown here will help because the documentation doesn’t seem to say anything about creating a directory (everything deals with files). But creating a directory is (pretty much always) a synchronous operation, so if that’s your goal, you should be able to create the directory somewhere temporary and then use the standard DROPFILES/SetFileDropList technique to let Windows do the work of creating it in the right place for you.

    Thanks for the question – hope this helps you out!

  3. Ken Parker says:

    Great implimentation but there are still a few bugs in the class. In windows 7 when explorer calls the GetData method it gives a value for dwAspect of DVASPECT_TUMBNAIL | DVASPECT_CONTENT. Need to change any comparison statements with FORMATETC.dwAspect to allow for multiple values like the FORMATETC.tymed statements do. Also I am trying to use an ISTREAM to transfer virtual files to windows explorer. However, the implimentation uses a wrapper that writes all of the data to the ISTREAM object when SetData(…) is called. My application has a large amount of files to copy and some that are 1gb+ in size. Using this implimentation I can not copy files larger then my physical memory. I need to somehow impliment the IStream COM interface but allocate it in unmanaged space so that other programs can gain access to it. Also need to solve the memory problem.

  4. Ken Parker says:

    You can drag and drop empty folder by adding them to the FileDescriptor setting the Contents to an empty stream and settings FileDescriptor.Attributes = FILE_ATTRIBUTE_DIRECTORY; Make sure to set the size to zero. Some external applications when dropped onto will call FILE_CONTENTS if they do you return an empty STREAM. Sorry I dont have the code anymore because it is proprietary and I no longer have access to it.

  5. Delay says:

    Ken Parker,

    That's great information, thanks so much for sharing!

    Regarding the dwAspect issue, what you say makes total sense. However, because I developed this code on Windows 7 and ran it successfully, I think it's not ALWAYS the case that THUMBNAIL is OR-ed in or I would have seen this myself. Of course, that's no excuse – I'm just explaining why I didn't do so in the first place. :)

    I get your point about the IStream memory limitation. If you come up with any suggestions for things I might do differently that wouldn't overly complicate the common "small file" case, I'd love to hear them.

    The folder handling information is cool – that scenario wasn't on my radar when I wrote this code.

    Thanks again! I've added some notes to my TODO list to follow up on your comments when I get a chance.

  6. Ken Parker says:

    I dont know why it is OR-ed with THUMBNAIL maybe depends on the current view of the folder. I do believe it was working at one point with out that correction but not sure what caused the mistake. So you may not be getting it now but it my creep up on you later

  7. Ken Parker says:

    The current implimentation converts a .NET Stream to a COM IStream. It uses an unmanaged call to allocate the memory. I think the solution is to impliment the COM IStream interface in managed code so that the file does not have to remain in memory to be transferred. The problem I run into is I dont know enough about COM interop to marshal this into the correct Memory so that external apps like Windows Explorer or MS Outlook can read the address when it calls GetData expecting a pointer to the IStream interface.

  8. Pro says:

    Hi!

    Thanks for your work! Great!

    When I drop a file from my App to the explorer it always has a length of 0 bytes. When I copy the same file via the clipboard it works!  Any idea?

    What does Ken mean with changing FORMATETC.dwAspect? Can you update the sample?

    Thanks a lot!!!!!!

  9. Pro says:

    After some tests I found out that asynchron modus is the problem!

    I changed this:

    void IAsyncOperation.GetAsyncMode(out int pfIsOpAsync)

    {

    //pfIsOpAsync = IsAsynchronous ? NativeMethods.VARIANT_TRUE : NativeMethods.VARIANT_FALSE;

    pfIsOpAsync = NativeMethods.VARIANT_FALSE;

    }

    Then it works!

    Any idea why asynchron modus does not work?

  10. Delay says:

    Pro,

    As I recall, the sample works for your scenario, so I'm wondering if maybe the problem you're seeing has to do with something you're doing a little differently. Offhand, I'm not sure what that would be, but I recall things being very picky about exactly how they were configured. If you agree the sample seems to work okay, you might start by trying to identify the differences vs. your implementation. Alternatively, gradually turn the sample into your implementation and see when it breaks. :)

  11. Pro says:

    Hi!

    Thanks for your answer!

    I found the problem! It was the start action! The start action called a method to show the wait screen. But invoking the UI thread caused a very weird deadlock. I don't know why this happen but it definitly causes the problem :-(

  12. Delay says:

    Pro,

    That *is* weird – but I'm glad to hear you found the problem! Thanks for letting me know!

  13. Tim Dellas says:

    If I understand it right, I need to do additional implementation for the asynchronous work that needs to be done after the dragging has been done in the demo program. Sadly I came looking for this from a .NET background and have little experience with the C structures or the programming paradigms needed to implement this. Therefore I want to humbly suggest to show an example in the demo, like downloading a file and putting it to the dragged location – which would make this basically the copy-paste solution I (and I guess a lot of others) came looking for. I know this sounds a bit lame, but I fail to see the usefullness of a demo app that crashes the Windows Explorer when used.

  14. Delay says:

    Tim Dellas,

    It sounds like maybe something's not working well with your system – Windows Explorer shouldn't crash no matter what my sample tries to do. (And it doesn't crash for other folks who have successfully used this code.) FYI that the sample application already does what you ask for – please have a look at the method TextUrlVirtualFile_MouseButtonDown to see how it asynchronously downloads a file to the drop location (with a busy indicator).

  15. Basile Cornet says:

    Hi David!

    Thank you very much for this piece of code ! I'm still trying to figure out how everything work (inside), but it work well :)

    Do you now how I can retrieve the dropped file path ? I really like the way you handle download of file, but my case is a bit more complicated. So what I'm tring to do is, drag and drop a file with only its FileDescriptor information, and retrieve its location once windows created an empty file, and then handle myself the download in my application.

    For now I managed to drop a file, it is created by windows, but no way to retrieve its path, and more than that each time I try another drag and drop, windows keeps dropping the first one. It's like the first d&d operation never ended.

  16. Delay says:

    Basile Cornet,

    Based on my understanding of your question, the following two links may be helpful:

    social.msdn.microsoft.com/…/454470ac-a9ea-4e1b-a341-b32672d56495

    stackoverflow.com/…/drag-drop-from-form-to-windows-get-drop-destination

    However, the complete answer may be that it's not possible to do this in general which is what Raymond Chen seems to suggest here:

    blogs.msdn.com/…/2453927.aspx

    Hope this helps!

  17. Basile Cornet says:

    Hi David,

    Thank you for your answer.

    We may have to change how we handle drag and drop, if I rely on the post by Raymond Chen.

    Thank you.

  18. Alex Nossov says:

    Great explanation and example of Drag source! Would highly appreciate to see C# code working as Drop Target with your demo application for Virtual File. Thanks again.

  19. Delay says:

    Alex Nossov,

    Thanks – I'll keep that in mind if I ever update this sample in the future!

Comments are closed.