Opening the default e-email app

e.gromero@alumnos.upm.es 21 Reputation points
2023-01-20T17:11:33.46+00:00

Hello everyone and happy new year. As you can see, I have a list of files in a listview and a share button. The problem is that I want to open the e-mail client you have by default.

User's image

I tried this code, but it gives me an error

string mailAppPath;
using (var key = Registry.ClassesRoot.OpenSubKey("mailto")) {
    mailAppPath = key?.GetValue("").ToString();
}
if (!string.IsNullOrEmpty(mailAppPath)) {
    // Use the mailAppPath variable to start the process
    Process p = new();
    p.StartInfo.FileName = mailAppPath;
    p.Start();
}

System.ComponentModel.Win32Exception: 'An error occurred trying to start process 'URL:MailTo Protocol' with working directory 'the directory that I am working on'. The system cannot find the file specified.'

I guess that for some reason is trying to look in my project directory, specifically the BIN/Windows10 bla bla

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,686 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,389 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Castorix31 82,116 Reputation points
    2023-01-20T18:55:05.84+00:00

    I want to open the e-mail client you have by default

    Usually, it could be done with mailto: protocol in FileName, like "mailto:test@test.com?subject=Subject&body=Body",

    but it does not work anymore on my PC (Windows 10)

    Other methods are with MAPI

    This test works for me with a "E:\test.docx" file as attachment (add a Button for the test on the Click) :

        public partial class Form1 : Form
        {
            public enum HRESULT : int
            {
                S_OK = 0,
                S_FALSE = 1,
                E_NOINTERFACE = unchecked((int)0x80004002),
                E_NOTIMPL = unchecked((int)0x80004001),
                E_FAIL = unchecked((int)0x80004005),
            }
    
            [ComImport]
            [Guid("00000122-0000-0000-C000-000000000046")]
            [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
            public interface IDropTarget
            {
                HRESULT DragEnter(
                    [In] System.Runtime.InteropServices.ComTypes.IDataObject pDataObj,
                    [In] int grfKeyState,
                    [In] Point pt,
                    [In, Out] ref int pdwEffect);
    
                HRESULT DragOver(
                    [In] int grfKeyState,
                    [In] Point pt,
                    [In, Out] ref int pdwEffect);
    
                HRESULT DragLeave();
    
                HRESULT Drop(
                    [In] System.Runtime.InteropServices.ComTypes.IDataObject pDataObj,
                    [In] int grfKeyState,
                    [In] Point pt,
                    [In, Out] ref int pdwEffect);
            }
    
            public const int DROPEFFECT_NONE = (0);
    
            [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "#740")]
            public static extern HRESULT SHCreateFileDataObject(IntPtr pidlFolder, uint cidl, IntPtr[] apidl, System.Runtime.InteropServices.ComTypes.IDataObject pdtInner, out System.Runtime.InteropServices.ComTypes.IDataObject ppdtobj);
    
            [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
            public static extern HRESULT SHILCreateFromPath([MarshalAs(UnmanagedType.LPWStr)] string pszPath, out IntPtr ppIdl, ref uint rgflnOut);
      
            [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
            public static extern IntPtr ILFindLastID(IntPtr pidl);
    
            [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
            public static extern IntPtr ILClone(IntPtr pidl);
    
            [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
            public static extern Boolean ILRemoveLastID(IntPtr pidl);
    
            [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
            public static extern void ILFree(IntPtr pidl);
      
            Guid CLSID_MapiMail = new Guid("9E56BE60-C50F-11CF-9A2C-00A0C90A90CE");
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                HRESULT hr = HRESULT.E_FAIL;
                uint rgflnOut = 0;
                System.Runtime.InteropServices.ComTypes.IDataObject pDataObject;
                IntPtr pidlParent = IntPtr.Zero, pidlFull = IntPtr.Zero, pidlItem = IntPtr.Zero;
                var aPidl = new IntPtr[255];
    
                hr = SHILCreateFromPath("E:\\test.docx", out pidlFull, ref rgflnOut);
                if (hr == HRESULT.S_OK)
                {
                    pidlItem = ILFindLastID(pidlFull);
                    aPidl[0] = ILClone(pidlItem);
                    ILRemoveLastID(pidlFull);
                    pidlParent = ILClone(pidlFull);
                    ILFree(pidlFull);
    
                    hr = SHCreateFileDataObject(pidlParent, 1, aPidl, null, out pDataObject);
                    if (hr == HRESULT.S_OK)
                    { 
                        Type DropTargetType = Type.GetTypeFromCLSID(CLSID_MapiMail, true);
                        object DropTarget = Activator.CreateInstance(DropTargetType);
                        IDropTarget pDropTarget = (IDropTarget)DropTarget;
                        int pdwEffect = DROPEFFECT_NONE;
                        Point pt = new Point();
                        pt.X = 0;
                        pt.Y = 0;
                        hr = pDropTarget.Drop(pDataObject, 0, pt, pdwEffect);
                    }
    
                    if (pidlParent != IntPtr.Zero)
                        ILFree(pidlParent);
                    if (aPidl[0] != IntPtr.Zero)
                        ILFree(aPidl[0]);
                }
            }
        }