A customer reported problems launching
the default Web browser with the
ShellExecuteEx
function:
int _tmain(int argc, _TCHAR* argv[]) { SHELLEXECUTEINFO sei = {0}; sei.cbSize = sizeof(sei); sei.nShow = SW_SHOWNORMAL; sei.lpFile = TEXT("www.microsoft.com"); sei.fMask = SEE_MASK_CLASSNAME; sei.lpVerb = TEXT("opennew"); sei.lpClass = TEXT("htmlfile"); ShellExecuteEx(&sei); return 0; }
This fails with sei.hInstApp = SE_ERR_FNF
.
If you don’t pass the SEE_MASK_CLASSNAME
flag and
leave lpClass = NULL
,
then the ShellExecuteEx
function will try to
figure out what your lpFile
refers to,
looking at the file extension,
looking for the file on the PATH
,
and if all else fails,
trying some autocorrection.
In this case, the customer was relying on the autocorrection,
since they left the http://
prefix off their URL.
One of the default autocorrection rules is that if the item that couldn’t
be launched begins with www
, then try again with
http://
in front.
On the other hand,
if you pass an explicit lpClass
,
then no name resolution is performed on the lpFile
.
You’re saying “Don’t do any sniffing and poking and autocorrection.
I have already determined that this item should be executed according
to the rules specified for
HKEY_CLASSES_ROOT\htmlfile
,
so just follow the rules and don’t question me.”
No second-guessing means that the ShellExecuteEx
function shrugged its shoulders and said,
“Well, I don’t see a file called www.microsoft.com
in the current directory, so I will fail with a file-not-found error.”
If you pass an explicit class, then
ShellExecuteEx
will
treat your lpFile
as if it were a file of that type.
If you have something and you want all the standard detection logic
to kick in, then don’t specify a class.
Bonus reading: The above program is simplified to illustrate the topic. A real-life version of this program needs some other scaffolding.
0 comments