Win32 annoyances and tips when working with files and processes

1. ShellExecuteEx and lpFile

SHELLEXECUTEINFOW setupxInfo;
memset(&setupxInfo, 0,
sizeof(SHELLEXECUTEINFO));
setupxInfo.cbSize =
sizeof(SHELLEXECUTEINFO);
setupxInfo.fMask = SEE_MASK_FLAG_NO_UI |
SEE_MASK_NOCLOSEPROCESS;
setupxInfo.lpVerb = L
"open";
setupxInfo.lpFile = L
"setupx.exe"; // can't be full path
setupxInfo.nShow = SW_SHOWNORMAL;
setupxInfo.lpDirectory = L
"setupdir";
setupxInfo.lpParameters = NULL;

ShellExecuteExW(&setupxInfo);

The code above is correct and it works, however if the lpFile member of the SHELLEXECUTEINFO struct is the full path to the executable file the ShellExecuteEx call fails. It seem you must specify the working directory for the child process (lpDirectory) and the filename only for the lpFile member.

2. SHFileOperation and pFrom

SHFILEOPSTRUCTW SHFileOp;
ZeroMemory(&SHFileOp,
sizeof(SHFILEOPSTRUCT));
SHFileOp.hwnd = NULL;
SHFileOp.wFunc = FO_DELETE;
SHFileOp.pFrom = killFolder;
// double-null-terminated string, can't end with path separator
SHFileOp.pTo = NULL;
SHFileOp.fFlags = FOF_SILENT |
FOF_NOCONFIRMATION |
FOF_NOERRORUI |
FOF_NOCONFIRMMKDIR;
SHFileOp.fAnyOperationsAborted = FALSE;
SHFileOp.lpszProgressTitle = NULL;
SHFileOp.hNameMappings = NULL;
SHFileOperationW(&SHFileOp);

In the above code, SHFileOp.pFrom (killFolder variable) is a double-null-terminated string to a folder I want to delete (I want to also recursively delete everything inside the folder, that’s why I’m using SHFileOperation). However, aside from the peculiar double null-termination, the path can’t end with the path separator char or the SHFileOperation call fails.

3. WaitForSingleObject

After calling ShellExecuteEx or CreateProcess you can do the following to wait for the child process to terminate:

WaitForSingleObject( setupxInfo.hProcess, INFINITE );

4. fclose

Don’t forget to close your file handles. I spent a few hours today trying to figure out why I couldn’t delete an exe, thinking it was an issue with the ShellExecuteEx function. Turns out I opened the file and forgot to close it.

btw, Process Explorer is very helpful and a great tool for programmers; it’s wonderful for detecting things like unclosed file handles.

Leave a Reply