ShellExecuteEx function
Performs an operation on a specified file.
Syntax
BOOL ShellExecuteEx( __inout LPSHELLEXECUTEINFO lpExecInfo );
Parameters
- lpExecInfo [in, out]
-
Type: LPSHELLEXECUTEINFO
A pointer to a SHELLEXECUTEINFO structure that contains and receives information about the application being executed.
Return value
Type: BOOL
Returns TRUE if successful; otherwise, FALSE. Call GetLastError for extended 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 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.
When DLLs are loaded into your process, you acquire a lock known as a loader lock. The DllMain function always executes under the loader lock. It is important that you do not call ShellExecuteEx while you hold a loader lock. Because ShellExecuteEx is extensible, you could load code that does not function properly in the presence of a loader lock, risking a deadlock and therefore an unresponsive thread.
With multiple monitors, if you specify an HWND and set the lpVerb member of the SHELLEXECUTEINFO structure pointed to by lpExecInfo to "Properties", any windows created by ShellExecuteEx might 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 Windows applications, it is not a true HINSTANCE. It can be cast only to an int and can be compared only to either the value 32 or the SE_ERR_XXX error codes.
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.
| Error | Description |
|---|---|
| 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 specified 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. |
Requirements
|
Minimum supported client | Windows XP |
|---|---|
|
Minimum supported server | Windows 2000 Server |
|
Header |
|
|
Library |
|
|
DLL |
|
|
Unicode and ANSI names | ShellExecuteExW (Unicode) and ShellExecuteExA (ANSI) |
See also
Send comments about this topic to Microsoft
Build date: 9/7/2011
SEE_MASK_FLAG_NO_UISEE_MASK_FLAG_NO_UISEE_MASK_FLAG_NO_UI
SEE_MASK_FLAG_NO_UI does not disable the message popup indicating there is no association found for the file. (search internet or select from list of programs choice)
Returns (hInstApp==42) when a file association is not set for a file, and the dialog pops up.
- 5/26/2011
- d3x0r
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 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
- 10/20/2007
- KJK_Hyperion
- 9/2/2009
- EricLaw-MSFT
<DllImport("shell32.dll", EntryPoint:="ShellExecuteEx")> _
Private Shared Function ShellExecute(ByRef s As SHELLEXECUTEINFO) As Integer
End Function
[DllImport("shell32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool ShellExecuteEx(ShellExecuteInfo info);
Public Shared Sub DisplayFileProperties(ByVal xFileName As String, ByVal hwnd As IntPtr)
Const SEE_MASK_INVOKEIDLIST As Integer = &HC
Const SW_SHOW As Integer = 5
Dim shInfo As New SHELLEXECUTEINFO()
With shInfo
.cbSize = Marshal.SizeOf(shInfo)
.lpFile = xFileName
.nShow = SW_SHOW
.fMask = SEE_MASK_INVOKEIDLIST
.lpVerb = "properties"
.hwnd = hwnd
End With
ShellExecute(shInfo)
End Sub
<StructLayout(LayoutKind.Sequential)> Private Structure SHELLEXECUTEINFO
Public cbSize As Integer
Public fMask As Integer
Public hwnd As IntPtr
Public lpVerb As String
Public lpFile As String
Public lpParameters As String
Public lpDirectory As String
Public nShow As Integer
Public hInstApp As IntPtr
Public lpIDList As IntPtr
Public lpClass As String
Public hkeyClass As IntPtr
Public dwHotKey As Integer
Public hIcon As IntPtr
Public hProcess As IntPtr
End Structure
Instead use ShellExecute or CreateProcess.
- 5/18/2008
- Christian.Wimmer
- 3/4/2008
- Jan Ringoš
- 3/4/2008
- Noelle Mallory
