Drag and drop large virtual files from C# to Windows Explorer

后端 未结 2 1087
甜味超标
甜味超标 2020-12-11 19:23

I have a C# WPF application with a section that serves as an FTP client, listing files on a remote server and allowing the user to download them. I want the user to be able

2条回答
  •  既然无缘
    2020-12-11 20:18

    I got the same issue, easy to fix though ;)

    The problem is that we are creating a new memory stream whereas it is not needed since we already have ours. You can create in c# an Stream wrapper that implements IStream:

        /// 
    /// Simple class that exposes a read-only Stream as a IStream.
    /// 
    private class StreamWrapper : IStream
    {
    
       private Stream _stream;
    
       public StreamWrapper(Stream stream)
    
       {
           _stream = stream;
       }
    
       public void Read(byte[] pv, int cb, System.IntPtr pcbRead)
    
       {
           Marshal.WriteInt32(pcbRead, _stream.Read(pv, 0, cb));
       }
    
       public void Seek(long dlibMove, int dwOrigin, System.IntPtr plibNewPosition)
    
       {
           Marshal.WriteInt32(plibNewPosition, (int)_stream.Seek(dlibMove, (SeekOrigin)dwOrigin));
       }
    
       public void Clone(out IStream ppstm)
    
       {
           throw new NotImplementedException();
       }
    
       public void Commit(int grfCommitFlags)
    
       {
           throw new NotImplementedException();
       }
    
       public void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten)
    
       {
           throw new NotImplementedException();
       }
    
       public void LockRegion(long libOffset, long cb, int dwLockType)
    
       {
           throw new NotImplementedException();
       }
    
       public void Revert()
    
       {
           throw new NotImplementedException();
       }
    
       public void SetSize(long libNewSize)
    
       {
           throw new NotImplementedException();
       }
    
       public void Stat(out System.Runtime.InteropServices.ComTypes.STATSTG pstatstg, int grfStatFlag)
    
       {
           throw new NotImplementedException();
       }
    
       public void UnlockRegion(long libOffset, long cb, int dwLockType)
    
       {
           throw new NotImplementedException();
       }
    
       public void Write(byte[] pv, int cb, IntPtr pcbWritten)
    
       {
           throw new NotImplementedException();
       }
    }
    

    And then in the VirtualFileDataObject class, change the signature of the SetData method so that you pass now a Stream:

    public void SetData(short dataFormat, int index, Stream stream)
    {
      ...
      var iStream = new StreamWrapper(stream);
      ...
      // Ensure the following line is commented out:
      //Marshal.ReleaseComObject(iStream);
      return new Tuple(ptr, NativeMethods.S_OK);
     ...
    }
    

    Now, no new memory stream will be created.

    For further info, go to http://blogs.msdn.com/b/delay/archive/2009/11/04/creating-something-from-nothing-asynchronously-developer-friendly-virtual-file-implementation-for-net-improved.aspx#10496772 and read my comments

提交回复
热议问题