DonationCoder.com forum
 
Read-only archive. This is a static copy of the DonationCoder.com forum. Reading and searching work as before; logging in, posting and private messages do not.
Archive of 2026-10-21 · About this archive · Main site

Author Topic: Is it possible to change to working directory within the running programm?  (Read 12,178 times)

crono

  • Charter Honorary Member
  • Joined in 2005
  • ***
  • Posts: 179
Hi all,

I have to write a tool which starts and runs on the shell (cmd.exe). It does some logic, takes some input from the user and finishes. Right before it finishes it should change the directory from which it was called. I have no clue if this is even possible. I tried to get the parent process and alter it this way, which results in crashes... 


C:\Home>my_tool.exe 
  ...doing some stuff...
  ...doing some stuff...
  ...doing some stuff...
  ...some user input....
  ...doing some stuff...
  ...finishing...
D:\Data\Documents>


Any Idea how to do this?

f0dder

  • [Well, THAT escalated quickly!]
  • Charter Honorary Member
  • Joined in 2005
  • ***
  • Posts: 9,153
    • Participated in NANY Challenge Once
What you want to do is change the working directory of the calling program, yes?

I dunno if this is possible to do in any clean way. Thing is, Current Working Directory is managed per-thread, not per-process. So the solution hack I'm thinking of would require finding your parent process (requires undocumented calls, iirc), locating the "correct thread", injecting code in the parent process to SetCurrentDirectory where you want, temporarily redirect the "correct thread" to this injected code, and then back to where it originally was.

Perhaps there's a cleaner way. A less hackish method would probably be running your tool from a batch file, and having the batch file CHDIR to the new folder.
- carpe noctem

crono

  • Charter Honorary Member
  • Joined in 2005
  • ***
  • Posts: 179
Quote
What you want to do is change the working directory of the calling program, yes?
Yes, this is what I would like to do.

Quote
I dunno if this is possible to do in any clean way.
I fear it is not :(, at least not in a clean way...

Quote
Thing is, Current Working Directory is managed per-thread, not per-process. So the solution hack I'm thinking of would require finding your parent process (requires undocumented calls, iirc)
I tried something in that way. It is very very very slow  :down:
Code: (csharp)
string pName = Process.GetCurrentProcess().ProcessName.ToString();
Process[] pList = Process.GetProcessesByName(pName);
// Getting the Process ID
PerformanceCounter PID = new PerformanceCounter("Process", "ID Process", pName);

// Getting the Parent Process ID
PerformanceCounter PPID = new PerformanceCounter("Process", "Creating Process ID", pName);

// Getting the Precess
Process p = Process.GetProcessById(int.Parse(PPID.NextValue().ToString()));

//trying to change the Dir... - which results in a Crash...
p.StandardInput.WriteLine("CD {0}",path);


Quote
A less hackish method would probably be running your tool from a batch file, and having the batch file CHDIR to the new folder.
This is a really good Idea and would be perfect if the Directory after finishing would be always the same (it is not), but how can I redirect only the last program Output to the Batchfile instead of all Output. The tool needs some (interactive) Userinput, so I can't capture all of the output...?

Thanks for the input f0dder :)


//edit: Idea:
The Batch have to look like this:
Code: (c)
call my_tool.exe 
call my_temp.bat

The my_temp.bat have to be created by my_tool.exe on the fly before finishing... I believe this will work...
Code: (c)
cd _DIR_

f0dder

  • [Well, THAT escalated quickly!]
  • Charter Honorary Member
  • Joined in 2005
  • ***
  • Posts: 9,153
    • Participated in NANY Challenge Once
Well, your code to get parent id does look extraordinarily slow - the performance counter API is pretty slow to deal with, especially the first call you make in a program. It'd probably be faster to use toolhelp32 and enumerate the processes until you find your own pid, and then check the th32ParentProcessID member... or use the undocumented NtQueryInformationProcess() function, which is pretty much instantaneous.

But even with the parent process PID, there isn't much you can do, without resorting to the hackhackhack I outlined in the previous post :)

Doing the multiple-batchfile approach is probably the cleanest.
- carpe noctem

hwtan

  • Charter Member
  • Joined in 2005
  • ***
  • Posts: 73
    • Programming School - Stage 1 Medal
    • Programming School - Deluxe Bonus Medal
    • Programming School - Dabbler Medal
    • Coding Snacks
    • Linux User
Alternative solution: write to the keyboard buffer.

Code: (cpp)
#include <Windows.h>

void writeKeyboardBuffer(const char* str)
{
	INPUT in;

	in.type = INPUT_KEYBOARD;
	in.ki.dwFlags = 0;
	in.ki.time = 0;
	in.ki.wScan = 0;
	in.ki.dwExtraInfo = 0;

	for (const char* ptr = str; *ptr != '\0'; ++ptr)
	{		
		SHORT key = VkKeyScan(*ptr);
		if (key & 0x0100)
		{
			in.ki.dwFlags = 0;
			in.ki.wVk = VK_SHIFT;
			SendInput(1, &in, sizeof(INPUT));	
		}

		in.ki.dwFlags = 0;
		in.ki.wVk = key & 0xFF;
		SendInput(1, &in, sizeof(INPUT));	

		if (key & 0x0100)
		{
			in.ki.dwFlags = KEYEVENTF_KEYUP;
			in.ki.wVk = VK_SHIFT;
			SendInput(1, &in, sizeof(INPUT));	
		}

		in.ki.dwFlags = KEYEVENTF_KEYUP;
		in.ki.wVk = key & 0xFF;
		SendInput(1, &in, sizeof(INPUT));	
	}
}

int main(int argc, char* argv[])
{
	const char* cmd = "cd D:\\TEMP\r";
	writeKeyboardBuffer(cmd);
}

f0dder

  • [Well, THAT escalated quickly!]
  • Charter Honorary Member
  • Joined in 2005
  • ***
  • Posts: 9,153
    • Participated in NANY Challenge Once
Alternative solution: write to the keyboard buffer.
Baaad idea :)

One thing is that it will obviously fail if the console window loses focus (and it might, for a zillion different reasons). Another potential problem the following blurb:
Quote
Microsoft Windows Vista. This function fails when it is blocked by User Interface Privilege Isolation (UIPI). Note that neither GetLastError nor the return value will indicate the failure was caused by UIPI blocking.
(obviously that would also block the other various hacks, but not the batchfile thingy).
- carpe noctem

Original address: https://www.donationcoder.com/forum/index.php?topic=13645.0