3

How can I read xml content of xml file that is not saved anywhere on the disk?

I want to be able to drag an attachment from Outlook (file extension is custom) and drop it in my application. Based on the content of the xml file I will do some Action accordingly.

I tried to iterate through e.Data.GetFormats() and GetData(format) but no avail. I tried e.Data.GetData("FileContents") didn't work. I tried e.Data.GetData(DataFormat.Text) also with DataFormats.UnicodeText, DataFormats.FileDrop and nothing works.

It is important to read the content of the file from DataObject since I don't want to force user to save the file before dragging it.

Any help will be greatly appreciated!

ANSWER

Well formatted answer for those who have same question:

So any file saved on disk being dropped will have full path that can be loaded and read.

Any file dropped from Outlook will have "FileGroupDesciptor" to get fileName along with its extension. "FileContents" will contain data stream of contents.

Example:

To process dragged dropped files to see if we can do some actions

public void DragEnter(DragEventArgs e)
{
    var obj = e.Data as DataObject;

    //get fileName of file saved on disk
    var fileNames = obj.GetFileDropList();
    
    if(fileNames.Count > 0)
        fileName = fileNames[0]; //I want only one at a time

    //Get fileName not save on disk
    if (string.IsNullOrEmpty(fileName) && obj.GetDataPresent("FileGroupDescriptor"))
    {
        var ms = (MemoryStream)obj.GetData("FileGroupDescriptor");
        ms.Position = 76;
        char a;
        while ((a = (char)ms.ReadByte()) != 0)
            fileName += a;
    }

    if (fileName.Length != 0)
    {
        var extension = fileName.Substring(fileName.LastIndexOf('.') + 1);
        switch (extension.ToUpper())
        {
            case "WTV":
                itemType = DropItemType.WTVFile;
                break;
          
            default:
                itemType = DropItemType.None;
                break;

        }
        canHandleDropData = (itemType != DropItemType.None);
    }
    
    if (canHandleDropData)
        e.Effect = DragDropEffects.Copy;
}

To Get content of dragged dropped file

 public XmlDocument GetXmlDocument(DragEventArgs dragEventArgs)
    {
        var doc = new XmlDocument();

        //Get content of outlook file not saved on disk
        var rawContent = dragEventArgs.Data.GetData("FileContents");

        if (rawContent == null)
        {
           //if null then it is a saved file and I can read its content by loading file name
            var xmlString = File.ReadAllText(fileName);
            doc.LoadXml(xmlString);
        }
        else
        {
            //outlook file content
            var xmlString = rawContent as MemoryStream;
            doc.Load(xmlString);    
        }

        return doc;
    }
Community
  • 1
  • 1
Rmazay
  • 65
  • 1
  • 7

1 Answers1

1

This is code that I use that handles converting either files from windows explorer or attachments from outlook to a memory stream. (ms is a public memorystream variable on the form). I'm sure you can use the same logic to convert it to a string reader.

      Private Sub ubFilepath_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles ubFilepath.DragDrop
    Try
        If e.Data.GetDataPresent(DataFormats.Text) Then
            Me.ubFilepath.Text = e.Data.GetData("Text")
        ElseIf e.Data.GetDataPresent(DataFormats.FileDrop) Then
            Dim fileNames() As String
            Dim MyFilename As String
            fileNames = DirectCast(e.Data.GetData(DataFormats.FileDrop), String())
            MyFilename = fileNames(0)
            Me.ubFilepath.Text = MyFilename

        //RenPrivateItem is from outlook

        ElseIf e.Data.GetDataPresent("RenPrivateItem") Then
            Dim thestream As System.IO.MemoryStream = e.Data.GetData("FileGroupDescriptor")
            Dim filename As New System.Text.StringBuilder("")
            Dim fileGroupDescriptor(700) As Byte
            Try
                thestream.Read(fileGroupDescriptor, 0, 700)
                Dim i As Integer = 76
                While fileGroupDescriptor(i) <> 0
                    filename.Append(Convert.ToChar(fileGroupDescriptor(i)))
                    i += 1
                End While
                Me.ubFilepath.Text = "Outlook attachment_" + filename.ToString
                ms = e.Data.GetData("FileContents", True)
            Finally
                If thestream IsNot Nothing Then thestream.Close()
            End Try
        End If
    Catch ex As Exception
        MessageBox.Show(ex.ToString, "Only files can be dragged into this box")
    End Try
Artiom
  • 7,694
  • 3
  • 38
  • 45
Haim Katz
  • 455
  • 3
  • 15