Drag Gmail attachment to c# winform

2

i'm trying to have may application accept attachments dragged in from the Gmail web page.

But when i drag in a attachment , directly from the site e.Data does nor seem to contain the data in any way.

    private void Form1_DragDrop(object sender, DragEventArgs e)
    {
        string[] dataFormats = e.Data.GetFormats();
        Type type = e.Data.GetType();
    }

e.Data is of type DataObject. FileDrop, FileNameW, FileName are null DragContext, DragImageBits, chromium/x-renderer-taint are System.IO.MemoryStream

Non of the Memorystream objects hold any file data of the attachment dragged in. Nor any download url.

edit. Apparently when dragging in a picture attachment, the data is holding the URL. but other attachments, does not carry a URL but some way windows explorer knows where to download it when i drag it to desktop, so there must be a way to retrieve this URL.

edit2 added data viewed with Immediate Window for DataObject

    (e.Data as System.Windows.DataObject).GetFormats(false);
{string[4]}
    [0]: "DragContext"
    [1]: "DragImageBits"
    [2]: "chromium/x-renderer-taint"
    [3]: "FileDrop"
(e.Data as System.Windows.DataObject).GetData("DragContext");
'(e.Data as System.Windows.DataObject).GetData("DragContext")' threw an exception of type 'System.Runtime.InteropServices.COMException'
    Data: {System.Collections.ListDictionaryInternal}
    ErrorCode: -2147221404
    HResult: -2147221404
    HelpLink: null
    InnerException: null
    Message: "Invalid FORMATETC structure (Exception from HRESULT: 0x80040064 (DV_E_FORMATETC))"
    Source: "System"
    StackTrace: "   at System.Runtime.InteropServices.ComTypes.IDataObject.GetData(FORMATETC& format, STGMEDIUM& medium)\r\n   at System.Windows.DataObject.OleConverter.GetDataInner(FORMATETC& formatetc, STGMEDIUM& medium)\r\n   at System.Windows.DataObject.OleConverter.GetDataFromOleHGLOBAL(String format, DVASPECT aspect, Int32 index)\r\n   at System.Windows.DataObject.OleConverter.GetDataFromBoundOleDataObject(String format, DVASPECT aspect, Int32 index)\r\n   at System.Windows.DataObject.OleConverter.GetData(String format, Boolean autoConvert, DVASPECT aspect, Int32 index)\r\n   at System.Windows.DataObject.OleConverter.GetData(String format, Boolean autoConvert)\r\n   at System.Windows.DataObject.GetData(String format, Boolean autoConvert)\r\n   at System.Windows.DataObject.GetData(String format)"
    TargetSite: {Void GetData(System.Runtime.InteropServices.ComTypes.FORMATETC ByRef, System.Runtime.InteropServices.ComTypes.STGMEDIUM ByRef)}
(e.Data as System.Windows.DataObject).GetData("DragImageBits");
{System.IO.MemoryStream}
    CanRead: true
    CanSeek: true
    CanTimeout: false
    CanWrite: true
    Capacity: 87144
    Length: 87144
    Position: 0
    ReadTimeout: '((System.IO.Stream)(e.Data as System.Windows.DataObject).GetData("DragImageBits")).ReadTimeout' threw an exception of type 'System.InvalidOperationException'
    WriteTimeout: '((System.IO.Stream)(e.Data as System.Windows.DataObject).GetData("DragImageBits")).WriteTimeout' threw an exception of type 'System.InvalidOperationException'
(e.Data as System.Windows.DataObject).GetData("chromium/x-renderer-taint");
{System.IO.MemoryStream}
    CanRead: true
    CanSeek: true
    CanTimeout: false
    CanWrite: true
    Capacity: 1
    Length: 1
    Position: 0
    ReadTimeout: '((System.IO.Stream)(e.Data as System.Windows.DataObject).GetData("chromium/x-renderer-taint")).ReadTimeout' threw an exception of type 'System.InvalidOperationException'
    WriteTimeout: '((System.IO.Stream)(e.Data as System.Windows.DataObject).GetData("chromium/x-renderer-taint")).WriteTimeout' threw an exception of type 'System.InvalidOperationException'
(e.Data as System.Windows.DataObject).GetData("FileDrop");
'(e.Data as System.Windows.DataObject).GetData("FileDrop")' threw an exception of type 'System.Runtime.InteropServices.COMException'
    Data: {System.Collections.ListDictionaryInternal}
    ErrorCode: -2147221404
    HResult: -2147221404
    HelpLink: null
    InnerException: null
    Message: "Invalid FORMATETC structure (Exception from HRESULT: 0x80040064 (DV_E_FORMATETC))"
    Source: "System"
    StackTrace: "   at System.Runtime.InteropServices.ComTypes.IDataObject.GetData(FORMATETC& format, STGMEDIUM& medium)\r\n   at System.Windows.DataObject.OleConverter.GetDataInner(FORMATETC& formatetc, STGMEDIUM& medium)\r\n   at System.Windows.DataObject.OleConverter.GetDataFromOleHGLOBAL(String format, DVASPECT aspect, Int32 index)\r\n   at System.Windows.DataObject.OleConverter.GetDataFromBoundOleDataObject(String format, DVASPECT aspect, Int32 index)\r\n   at System.Windows.DataObject.OleConverter.GetData(String format, Boolean autoConvert, DVASPECT aspect, Int32 index)\r\n   at System.Windows.DataObject.OleConverter.GetData(String format, Boolean autoConvert)\r\n   at System.Windows.DataObject.GetData(String format, Boolean autoConvert)\r\n   at System.Windows.DataObject.GetData(String format)"
    TargetSite: {Void GetData(System.Runtime.InteropServices.ComTypes.FORMATETC ByRef, System.Runtime.InteropServices.ComTypes.STGMEDIUM ByRef)}
c#
drag-and-drop
asked on Stack Overflow Feb 18, 2018 by arnold • edited Mar 1, 2018 by arnold

2 Answers

0

The attachment is detected as a FileDrop, the data contains the URL to the attachment, which can be retrieved by doing GetData(DataFormats.Text).

Here is some sample code for you to try:

private void Form1_DragDrop(object sender, DragEventArgs e) {
    string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
    if (files == null) {
        string url = (string)e.Data.GetData(DataFormats.Text);
        MessageBox.Show(url);
   }
}

private void Form1_DragEnter(object sender, DragEventArgs e) {
    if (e.Data.GetDataPresent(DataFormats.FileDrop)) {
        e.Effect = DragDropEffects.Copy;
    }
}

Note that it is important to handle the DragEnter event and set the e.Effect to DragDropEffects.Copy, otherwise the DragDrop event either won't fire, or won't have the data you need.

answered on Stack Overflow Feb 24, 2018 by Simon • edited Feb 24, 2018 by Simon
0

The latest Gmail web app has implemented security and now it will not allow you to get direct file url like image. My purpose is to provide you with some explanation on what I did.

I researched some more deep into it and tried some code during debugging in an Immediate window and found that..

There are many Formats available when get the DataObject

(e.Data as System.Windows.DataObject).GetFormats(false);

{string[13]}
        [0]: "DragContext"
        [1]: "DragImageBits"
        [2]: "chromium/x-renderer-taint"
        [3]: "FileDrop"
        [4]: "UnicodeText"
        [5]: "Text"
        [6]: "text/x-moz-url"
        [7]: "FileGroupDescriptorW"
        [8]: "FileContents"
        [9]: "UniformResourceLocatorW"
        [10]: "UniformResourceLocator"
        [11]: "HTML Format"
        [12]: "text/html"

Then I tried getting Text format data from it

(e.Data as System.Windows.DataObject).GetDataPresent("Text");
true

(e.Data as System.Windows.DataObject).GetData("Text");
    "https://mail.google.com/mail/u/0/?ui=X&ik=XXXXXXXXXXX&view=att&th=XXXXXXXXXX&attid=0.1&disp=inline&safe=1&zw"

So this is nothing but the url to your attachment. When I tried to hit this url on browser directly, I redirected to the attach file. (You must login in browser with google account)

Last I tried the following option

(e.Data as System.Windows.DataObject).GetData("HTML Format");

I got the string with some querystring and html. In the HTML, you can easily find the file name (temporary) and the extension of the file.

The point I want to prove here OR the approach I suggest you is that once you get the URL to the attachment file. You can put a simple web service call / Google API call to the URL and download the file in response.

NOTE: All above mention code is from Visual Studio Immediate window so its a combination of code i executed and output which was returned.

answered on Stack Overflow Mar 1, 2018 by Gaurang Dave

User contributions licensed under CC BY-SA 3.0