Platform SDK Shell >> Changing current path

by Q29uZm91bmRlZA » Sun, 17 Apr 2005 13:18:06 GMT

I am updating an old DOS C++ program for Windows 32 using Visual Studio.
Among other tasks, it changes the current directory before exiting. I have
tried SetCurrentDirectory, exec, spawn, etc. without luck. I believe these
only change the current path for the current process (the program.)

How can a program change the path for the command window?



Platform SDK Shell >> Changing current path

by Gary Chanson » Sun, 17 Apr 2005 19:54:26 GMT






You can't directly change the current directory of the parent process
running in a console window. The best you can do, assuming that this parent
process is CMD.EXE, is to fool it into changing the current directory for you.
This can be done by getting it to execute a CD command either by sending the
command to it as keyboard input using SendInput or by getting it to execute a
batch file with this command in it.

--
-GJC [MS Windows SDK MVP]
-Software Consultant (Embedded systems and Real Time Controls)
- http://www.mvps.org/ArcaneIncantations/consulting.htm
XXXX@XXXXX.COM




Platform SDK Shell >> Changing current path

by Jim Barry » Tue, 19 Apr 2005 02:11:12 GMT




Well, this is pretty tricky but you can do it on Windows 2000 and later, by using CreateRemoteThread and taking advantage of the fact that SetCurrentDirectory happens to have a signature compatible with that required of the thread entry point. Also, the Tool Help API provides the means to find the parent process. See below for some code that works for me. On systems earlier than Windows 2000 I think it is going to be tough to do without resorting to undocumented stuff.

DWORD GetParentProcessID()
{
DWORD result = 0;
HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (INVALID_HANDLE_VALUE != snap)
{
PROCESSENTRY32 entry = {sizeof(entry)};
if (Process32First(snap, &entry))
{
DWORD pid = GetCurrentProcessId();
do
{
if (pid == entry.th32ProcessID)
{
result = entry.th32ParentProcessID;
break;
}
}
while (Process32Next(snap, &entry));
}
CloseHandle(snap);
}
return result;
}

void SetCurrentDirectoryForProcess(HANDLE process, LPCTSTR dir)
{
if (void * mem = VirtualAllocEx(process, 0,
sizeof(TCHAR) * MAX_PATH, MEM_COMMIT, PAGE_READWRITE))
{
WriteProcessMemory(process, mem, dir, sizeof(TCHAR) * (lstrlen(dir) + 1), 0);
if (HANDLE thread = CreateRemoteThread(process, 0, 0,
LPTHREAD_START_ROUTINE(SetCurrentDirectory), mem, 0, 0))
{
WaitForSingleObject(thread, INFINITE);
CloseHandle(thread);
}
VirtualFreeEx(process, mem, 0, MEM_RELEASE);
}
}

void TestIt()
{
if (DWORD pid = GetParentProcessID())
{
if (HANDLE hp = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid))
{
SetCurrentDirectoryForProcess(hp, _T("c:\\"));
CloseHandle(hp);
}
}
}


--
Jim Barry, MVP for Windows SDK