Win32 annoyances and tips when working with files and processes
Avishkar Autar · Nov 11 2007 · Win32 Platform
1. ShellExecuteEx and lpFile
memset(&setupxInfo, 0, sizeof(SHELLEXECUTEINFO));
setupxInfo.cbSize = sizeof(SHELLEXECUTEINFO);
setupxInfo.fMask = SEE_MASK_FLAG_NO_UI |
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;
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
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 |
SHFileOp.fAnyOperationsAborted = FALSE;
SHFileOp.lpszProgressTitle = NULL;
SHFileOp.hNameMappings = NULL;
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.
After calling ShellExecuteEx or CreateProcess you can do the following to wait for the child process to terminate:
WaitForSingleObject( setupxInfo.hProcess, INFINITE );
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.