Click to Rate and Give Feedback
MSDN
MSDN Library
User Interface
Windows Shell
Shell Reference
Shell Functions
 ShellExecuteEx Function
ShellExecuteEx Function

Performs an operation on a specified file.

Syntax

BOOL ShellExecuteEx(      
    LPSHELLEXECUTEINFO lpExecInfo );

Parameters

lpExecInfo
The address of a SHELLEXECUTEINFO structure that contains and receives information about the application being executed.

Return Value

Returns TRUE if successful, or FALSE otherwise. Call GetLastError for error information.

Remarks

Because ShellExecuteEx can delegate execution to Shell extensions (data sources, context menu handlers, verb implementations) that are activated using Component Object Model (COM), COM should be initialized before ShellExecuteEx is called. Some Shell extensions require the COM single-threaded apartment (STA) type. In that case, COM should be initialized as shown here:

CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE)
There are certainly instances where ShellExecuteEx does not use one of these types of Shell extension and those instances would not require COM to be initialized at all. Nonetheless, it is good practice to always initalize COM before using this function.

With multiple monitors, if you specify an HWND and set the lpVerb member of lpExecInfo to "Properties", any windows created by ShellExecuteEx may not appear in the correct position.

If the function succeeds, it sets the hInstApp member of the SHELLEXECUTEINFO structure to a value greater than 32. If the function fails, hInstApp is set to the SE_ERR_XXX error value that best indicates the cause of the failure. Although hInstApp is declared as an HINSTANCE for compatibility with 16-bit Microsoft Windows applications, it is not a true HINSTANCE. It can only be cast to an int and compared to either 32 or the SE_ERR_XXX error codes.

Note  The SE_ERR_XXX error values are provided for compatibility with ShellExecute. To retrieve more accurate error information, use GetLastError. It may return one of the following values.

ErrorDescription
ERROR_FILE_NOT_FOUND The specified file was not found.
ERROR_PATH_NOT_FOUND The specified path was not found.
ERROR_DDE_FAIL The Dynamic Data Exchange (DDE) transaction failed.
ERROR_NO_ASSOCIATION There is no application associated with the given file name extension.
ERROR_ACCESS_DENIED Access to the specified file is denied.
ERROR_DLL_NOT_FOUND One of the library files necessary to run the application can't be found.
ERROR_CANCELLED The function prompted the user for additional information, but the user canceled the request.
ERROR_NOT_ENOUGH_MEMORY There is not enough memory to perform the specified action.
ERROR_SHARING_VIOLATION A sharing violation occurred.

Windows 95/98/Me: ShellExecuteEx is supported by the Microsoft Layer for Unicode (MSLU). To use this, you must add certain files to your application, as outlined in Microsoft Layer for Unicode on Windows Me/98/95 Systems.

Function Information

Minimum DLL Versionshell32.dll version 3.51 or later
Custom ImplementationNo
Headershellapi.h
Import libraryshell32.lib
Minimum operating systems Windows NT 4.0, Windows 95
UnicodeImplemented as ANSI and Unicode versions.

See Also

IShellExecuteHook, CoInitializeEx
Tags What's this?: Add a tag
Community Content   What is Community Content?
Add new content RSS  Annotations
Using lpExecInfo->lpClass and lpExecInfo->hkeyClass      KJK_Hyperion   |   Edit   |  

If you are afraid ShellExecute(Ex) might misidentify the file type, because the path might be ambiguous or if you use a non-standard type system, you can force one by filling the lpClass or hkeyClass fields in lpExecInfo. You set lpClass to either the extension (e.g. ".txt") or the URL scheme (e.g. "http") or the OLE ProgId/ClassId; better yet, you use AssocQueryKey to retrieve the appropriate hkeyClass for the given class name and verb. For example, this is how you safely execute URLs with ShellExecute(Ex):

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
 
#include <shellapi.h>
#include <shlwapi.h>
#include <wininet.h>
 
#include <strsafe.h>
 
BOOL ShellExecuteURLExInternal(LPSHELLEXECUTEINFO lpExecInfo)
{
    BOOL bRet;
    DWORD dwErr;
    HRESULT hr;
    PARSEDURL pu;
    TCHAR szSchemeBuffer[INTERNET_MAX_SCHEME_LENGTH + 1];
    HKEY hkeyClass;
 
    /* Default error codes */
    bRet = FALSE;
    dwErr = ERROR_INVALID_PARAMETER;
    hr = S_OK;
 
    lpExecInfo->hInstApp =
        (HINSTANCE)UlongToHandle(SE_ERR_ACCESSDENIED);
 
    /* Validate parameters */
    if
    (
        lpExecInfo->cbSize == sizeof(*lpExecInfo) &&
        lpExecInfo->lpFile != NULL &&
        (lpExecInfo->fMask & SEE_MASK_INVOKEIDLIST) == 0 &&
        (lpExecInfo->fMask & SEE_MASK_CLASSNAME) == 0 &&
        (lpExecInfo->fMask & 0x00400000) == 0 /* SEE_MASK_FILEANDURL */
    )
    {
        /* Extract the scheme out of the URL */
        pu.cbSize = sizeof(pu);
        hr = ParseURL(lpExecInfo->lpFile, &pu);
 
        /* Is the URL really, unambiguously an URL? */
        if
        (
            SUCCEEDED(hr) &&
            pu.pszProtocol == lpExecInfo->lpFile &&
            pu.pszProtocol[pu.cchProtocol] == TEXT(':')
        )
        {
            /* We need the scheme name NUL-terminated, so we copy it */
            hr = StringCbCopyN
            (
                szSchemeBuffer,
                sizeof(szSchemeBuffer),
                pu.pszProtocol,
                pu.cchProtocol * sizeof(TCHAR)
            );
 
            if(SUCCEEDED(hr))
            {
                /* Is the URL scheme a registered ProgId? */
                hr = AssocQueryKey
                (
                    ASSOCF_INIT_IGNOREUNKNOWN,
                    ASSOCKEY_CLASS,
                    szSchemeBuffer,
                    NULL,
                    &hkeyClass
                );
 
                if(SUCCEEDED(hr))
                {
                    /* Is the ProgId really an URL scheme? */
                    dwErr = RegQueryValueEx
                    (
                        hkeyClass,
                        TEXT("URL Protocol"),
                        NULL,
                        NULL,
                        NULL,
                        NULL
                    );
 
                    /* All clear! */
                    if(dwErr == NO_ERROR || dwErr == ERROR_MORE_DATA)
                    {
                        /* Don't let ShellExecuteEx guess */
                        lpExecInfo->fMask |= SEE_MASK_CLASSKEY;
                        lpExecInfo->lpClass = NULL;
                        lpExecInfo->hkeyClass = hkeyClass;
 
                        /* Finally, execute the damn URL */
                        bRet = ShellExecuteEx(lpExecInfo);
 
                        /* To preserve ShellExecuteEx's last error */
                        dwErr = NO_ERROR;
                    }
 
                    RegCloseKey(hkeyClass);
                }
            }
        }
    }
 
    /* Last error was a HRESULT */
    if(FAILED(hr))
    {
        /* Try to dissect it */
        if(HRESULT_FACILITY(hr) == FACILITY_WIN32)
            dwErr = HRESULT_CODE(hr);
        else
            dwErr = hr;
    }
 
    /* We have a last error to set */
    if(dwErr)
        SetLastError(dwErr);
 
    return bRet;
}
 
BOOL ShellExecuteURLEx(LPSHELLEXECUTEINFO lpExecInfo)
{
    BOOL bRet;
    SHELLEXECUTEINFO ExecInfo;
 
    /* We use a copy of the parameters, because you never know */
    CopyMemory(&ExecInfo, lpExecInfo, sizeof(ExecInfo));
 
    /* Do the magic */
    bRet = ShellExecuteURLExInternal(&ExecInfo);
 
    /* These need to be copied back */
    lpExecInfo->hInstApp = ExecInfo.hInstApp;
    lpExecInfo->hProcess = ExecInfo.hProcess;
    return bRet;
}
 
HINSTANCE ShellExecuteURL
(
    HWND hwnd,
    LPCTSTR lpOperation,
    LPCTSTR lpFile,
    LPCTSTR lpParameters,
    LPCTSTR lpDirectory,
    INT nShowCmd
)
{
    SHELLEXECUTEINFO ExecuteInfo;
 
    ExecuteInfo.fMask = SEE_MASK_FLAG_NO_UI; /* Odd but true */
    ExecuteInfo.hwnd = hwnd;
    ExecuteInfo.cbSize = sizeof(ExecuteInfo);
    ExecuteInfo.lpVerb = lpOperation;
    ExecuteInfo.lpFile = lpFile;
    ExecuteInfo.lpParameters = lpParameters;
    ExecuteInfo.lpDirectory = lpDirectory;
    ExecuteInfo.nShow = nShowCmd;
 
    ShellExecuteURLExInternal(&ExecuteInfo);
 
    return ExecuteInfo.hInstApp;
}

Note that we use ParseURL instead of more sophisticated functions like InternetCrackUrl because it's much more forgiving, and we only need to extract the scheme anyway

Failing with ERROR_NOT_SUPPORTED      Jan Ringoš ... Noelle Mallory - MSFT   |   Edit   |  
Perhaps it should be noted that the function fails with GetLastError() == ERROR_NOT_SUPPORTED when starting executable that requires elevation on Windows Vista and the SEE_MASK_FLAG_DDEWAIT was not used. At least this is how it behaves on my laptop. The solution obviously is to include the flag.
ShellExecuteEx ignores current input desktop.      ChristianWimmer   |   Edit   |  
ShellExecuteEx ignores the current input desktop. It always uses winsta0\default.
Instead use ShellExecute or CreateProcess.
Tags What's this?: Add a tag
Flag as ContentBug
Processing
© 2008 Microsoft Corporation. All rights reserved. Terms of Use  |  Trademarks  |  Privacy Statement
Page view tracker