Click here to Skip to main content
Licence 
First Posted 24 Sep 2002
Views 68,925
Bookmarked 18 times

Detect and run the default mail client

By | 24 Sep 2002 | Article
Programatically get the default mail client using registry

Helpers

Actually these are more suitable for interfaces, but hopefully good for other objects too needing auto-deletion on getting out-of-scope.
template<typename T>
class AutoDeleteHlp
{
    typedef T _Item;

    public:
        AutoDeleteHlp(T t)
        {
            m_T = t;
        }
        ~AutoDeleteHlp()
        {}
        operator T ()
        {
            return m_T;
        }
        operator T *()
        {
            return (T *)&m_T;
        }
        virtual operator bool()
        {
            return (m_T != NULL) ? true : false;
        }
        T **operator &()
        {
            return &m_T;
        }
        T *Get()
        {
            return m_T;
        }
        void Set(T t)
        {
            m_T = t;
        }

    private:
        virtual void Delete() = 0;

    protected:
        T m_T;
};

The (incomplete) registry key helper

class RegKey_ : public AutoDeleteHlp<HKEY>
{
    public:
        RegKey_(HKEY hk = 0)
            : AutoDeleteHlp<HKEY>(hk)
        {}
        ~RegKey_()
        {
            Delete();
        }
        LONG Open(HKEY hKey, LPCTSTR lpSubkeyName, REGSAM regSam = KEY_READ)
        {
            return ::RegOpenKeyEx(hKey, lpSubkeyName, 0, regSam, &m_T);
        }
        LONG ReadString(LPTSTR lpString, DWORD cbData, 
          LPCTSTR lpValName = _T(""))
        {
            DWORD dwType;
            return ::RegQueryValueEx(m_T, lpValName, NULL, 
              &dwType, (LPBYTE)lpString, &cbData);
        }
        LONG Read(LPBYTE lpData, DWORD cbData, LPCTSTR lpValName = _T(""))
        {
            DWORD dwType;
            return ::RegQueryValueEx(m_T, lpValName, NULL, 
              &dwType, (LPBYTE)lpData, &cbData);
        }
    private:
        virtual void Delete()
        {
            if(m_T)
            {
                _Item hk = m_T;
                m_T = 0;

                if(::RegCloseKey(hk))
                {
                    hk = NULL;
                }
            }
        }
};

...the CreateProcess wrapper (for executing a command line):

class CmdLineExec_
{
    private:
        STARTUPINFO            m_si;
        PROCESS_INFORMATION m_pi;

        TCHAR                m_lpCmdLine[_MAX_PATH + 1];

    public:
        CmdLineExec_(LPCTSTR lpCmdLine)
        {
            ZeroMemory(&m_si, sizeof(STARTUPINFO));
            ZeroMemory(&m_pi, sizeof(PROCESS_INFORMATION));

            if(lpCmdLine != NULL)
            {
                lstrcpyn(m_lpCmdLine, lpCmdLine, _MAX_PATH + 1);
            }
            else
            {
                lstrcpyn(m_lpCmdLine, _T(""), _MAX_PATH + 1);
            }
        }
        ~CmdLineExec_()
        {
            if(m_pi.hProcess)
            {
                CloseHandle(m_pi.hProcess);
            }
            if(m_pi.hThread)
            {
                CloseHandle(m_pi.hThread);
            }
        }
    public:
        BOOL Execute(DWORD *pdwLastError = NULL)
        {
            BOOL fRet = CreateProcess(NULL, (LPTSTR)m_lpCmdLine, NULL, 
                NULL, FALSE, 0, NULL, NULL, &m_si, &m_pi);
            if(pdwLastError != NULL)
            {
                *pdwLastError = GetLastError();
            }

            return fRet;
        }
};

... and finally the default mail client wrapper:

class DefaultMailClient_ : public RegKey_
{
    private:
        TCHAR    m_szDefMailClient[_MAX_PATH + 1];
        BOOL    m_fValid;

    public:
        TCHAR    m_szDefMailCmd[_MAX_PATH + 1];

    public:
        DefaultMailClient_(HKEY hk = 0)
            : RegKey_(hk)
        {
            lstrcpyn(m_szDefMailClient, _T("SOFTWARE\\Clients\\Mail"),
                _MAX_PATH);
            lstrcpyn(m_szDefMailCmd, _T(""), _MAX_PATH);

            m_fValid = GetCmdLine();
        }
        ~DefaultMailClient_()
        {
            Delete();
        }

    public:
        BOOL IsValid()
        {
            return m_fValid;
        }
        BOOL Execute()
        {
            CmdLineExec_ cmdl(m_szDefMailCmd);
            return cmdl.Execute();
        }
    protected:
        BOOL GetCmdLine()
        {
            LONG retval;
            
            retval = Open(HKEY_LOCAL_MACHINE, m_szDefMailClient);
            if(retval == NO_ERROR)
            {
                DWORD cbData = _MAX_PATH;
                retval = ReadString(m_szDefMailClient, cbData);
                if(retval == NO_ERROR)
                {
                    TCHAR szCmdLine[_MAX_PATH + 1];

                    lstrcpyn(szCmdLine, _T("SOFTWARE\\Clients\\Mail\\"), 
                       _MAX_PATH + 1);
                    _tcsncat(szCmdLine, m_szDefMailClient, _MAX_PATH + 1);
                    _tcsncat(szCmdLine, _T(\\shell\\open\\command),
                       _MAX_PATH + 1);

                    RegKey_ rk;
                    if(rk.Open(HKEY_LOCAL_MACHINE, szCmdLine) == NO_ERROR)
                    {
                        retval = rk.ReadString(m_szDefMailCmd, _MAX_PATH);
                        if(retval == NO_ERROR)
                        {
                            return TRUE;
                        }
                    }
                }
            }

            return FALSE;
        }

    private:
        virtual void Delete()
        {
            if(m_T)
            {
                _Item hk = m_T;
                m_T = 0;

                if(::RegCloseKey(hk))
                {
                    hk = NULL;
                }
            }
        }
};

Calling routine

void OpenDefaultMailClient()
{
    DefaultMailClient_ dmcl;
    if(dmcl.IsValid())
    {
        if(!dmcl.Execute())
        {
            MessageBox(NULL,
                _T("Could not launch the default mail client."), 
                NULL, MB_OK);
        }
    }
}
main simply calls this function:
void main()
{
    OpenDefaultMailClient();
}

For convenience, the dsw and dsp files are included, and also the makefile. For a single-file project, open a console and execute :-

...> nmake /f dmcl.mak 

Conclusion

That's it. Keep it simple. Use the function instead of digging registry yourself (like I did). Tested on Windows 2000 SP3. Let me know if you have problems on other platforms.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Sardaukar

Web Developer

Romania Romania

Member



Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralWindows Vista Pinmember][cepick5:06 2 May '07  
QuestionRe: Windows Vista PinmemberMember 35758181:32 24 Sep '08  
GeneralDoesn't work with Netscape Messenger Pinmemberotrcomm17:07 10 Jul '04  
GeneralThis is useful for non-MS mail clients PineditorNishant S2:22 29 Sep '03  
Questionerror code:ERROR_SXS_ASSEMBLYNOTFOUND What is this? Pinmembergirishnadig6:55 18 Sep '03  
AnswerRe: error code:ERROR_SXS_ASSEMBLYNOTFOUND What is this? PinmemberSardaukar19:54 18 Sep '03  
GeneralKISS PinsussAnonymous8:24 25 Sep '02  
GeneralRe: KISS PinmemberSardaukar9:02 25 Sep '02  
GeneralRe: KISS PinmemberDaniel Turini10:28 25 Sep '02  
Sardaukar wrote:
This is not opening (nor detecting) the default mail client. It is opening a new mail message, nothing more. You can access using
::ShellExecute(NULL, "open", "mailto:bob@microsoft.com", NULL, NULL, SW_NORMAL);
 
your Outlook calendar? I think you can just send one new mail, nothing more

 
No, but this can:
 
::ShellExecute(NULL, "open", "outlook://Personal%20Folders/Calendar", NULL, NULL, SW_NORMAL);

 
"In an organization, each person rises to the level of his own incompetence." Peter's Principle
GeneralRe: KISS PinmemberSardaukar20:15 25 Sep '02  
GeneralRe: KISS PinmemberSardaukar20:21 25 Sep '02  
GeneralRe: KISS PinmemberAndreas Saurwein1:50 26 Sep '02  
GeneralRe: KISS PinmemberSardaukar2:47 26 Sep '02  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web01 | 2.5.120529.1 | Last Updated 25 Sep 2002
Article Copyright 2002 by Sardaukar
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid