Welcome Guest.   Make a donation to an author on the site August 21, 2014, 08:58:56 PM  *

Please login or register.
Or did you miss your validation email?


Login with username and password (forgot your password?)
Why not become a lifetime supporting member of the site with a one-time donation of any amount? Your donation entitles you to a ton of additional benefits, including access to exclusive discounts and downloads, the ability to enter monthly free software drawings, and a single non-expiring license key for all of our programs.


You must sign up here before you can post and access some areas of the site. Registration is totally free and confidential.
 
Check out and download the GOE 2007 Freeware Challenge productivity tools.
   
   Forum Home   Thread Marks Chat! Downloads Search Login Register  
Pages: [1]   Go Down
  Reply  |  New Topic  |  Print  
Author Topic: Is it possible to change to working directory within the running programm?  (Read 4705 times)
crono
Charter Honorary Member
***
Posts: 178


see users location on a map View Profile Give some DonationCredits to this forum member
« on: June 11, 2008, 01:17:22 PM »

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?
Logged
f0dder
Charter Honorary Member
***
Posts: 8,774



[Well, THAT escalated quickly!]

see users location on a map View Profile WWW Read user's biography. Give some DonationCredits to this forum member
« Reply #1 on: June 11, 2008, 06:03:13 PM »

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.
Logged

- carpe noctem
crono
Charter Honorary Member
***
Posts: 178


see users location on a map View Profile Give some DonationCredits to this forum member
« Reply #2 on: June 11, 2008, 07:44:26 PM »

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 Sad, 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  thumb down
Formatted for C# with the GeSHI Syntax Highlighter [copy or print]
  1. string pName = Process.GetCurrentProcess().ProcessName.ToString();
  2. Process[] pList = Process.GetProcessesByName(pName);
  3. // Getting the Process ID
  4. PerformanceCounter PID = new PerformanceCounter("Process", "ID Process", pName);
  5.  
  6. // Getting the Parent Process ID
  7. PerformanceCounter PPID = new PerformanceCounter("Process", "Creating Process ID", pName);
  8.  
  9. // Getting the Precess
  10. Process p = Process.GetProcessById(int.Parse(PPID.NextValue().ToString()));
  11.  
  12. //trying to change the Dir... - which results in a Crash...
  13. 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 smiley


//edit: Idea:
The Batch have to look like this:
Formatted for C with the GeSHI Syntax Highlighter [copy or print]
  1. call my_tool.exe
  2. 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...
Formatted for C with the GeSHI Syntax Highlighter [copy or print]
  1. cd _DIR_

Logged
f0dder
Charter Honorary Member
***
Posts: 8,774



[Well, THAT escalated quickly!]

see users location on a map View Profile WWW Read user's biography. Give some DonationCredits to this forum member
« Reply #3 on: June 11, 2008, 08:09:52 PM »

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 smiley

Doing the multiple-batchfile approach is probably the cleanest.
Logged

- carpe noctem
hwtan
Charter Member
***
Posts: 72



see users location on a map View Profile Give some DonationCredits to this forum member
« Reply #4 on: June 17, 2008, 06:48:55 AM »

Alternative solution: write to the keyboard buffer.

Formatted for C++ with the GeSHI Syntax Highlighter [copy or print]
  1. #include <Windows.h>
  2.  
  3. void writeKeyboardBuffer(const char* str)
  4. {
  5. INPUT in;
  6.  
  7. in.type = INPUT_KEYBOARD;
  8. in.ki.dwFlags = 0;
  9. in.ki.time = 0;
  10. in.ki.wScan = 0;
  11. in.ki.dwExtraInfo = 0;
  12.  
  13. for (const char* ptr = str; *ptr != '\0'; ++ptr)
  14. {
  15. SHORT key = VkKeyScan(*ptr);
  16. if (key & 0x0100)
  17. {
  18. in.ki.dwFlags = 0;
  19. in.ki.wVk = VK_SHIFT;
  20. SendInput(1, &in, sizeof(INPUT));
  21. }
  22.  
  23. in.ki.dwFlags = 0;
  24. in.ki.wVk = key & 0xFF;
  25. SendInput(1, &in, sizeof(INPUT));
  26.  
  27. if (key & 0x0100)
  28. {
  29. in.ki.dwFlags = KEYEVENTF_KEYUP;
  30. in.ki.wVk = VK_SHIFT;
  31. SendInput(1, &in, sizeof(INPUT));
  32. }
  33.  
  34. in.ki.dwFlags = KEYEVENTF_KEYUP;
  35. in.ki.wVk = key & 0xFF;
  36. SendInput(1, &in, sizeof(INPUT));
  37. }
  38. }
  39.  
  40. int main(int argc, char* argv[])
  41. {
  42. const char* cmd = "cd D:\\TEMP\r";
  43. writeKeyboardBuffer(cmd);
  44. }
Logged
f0dder
Charter Honorary Member
***
Posts: 8,774



[Well, THAT escalated quickly!]

see users location on a map View Profile WWW Read user's biography. Give some DonationCredits to this forum member
« Reply #5 on: June 17, 2008, 07:56:01 AM »

Alternative solution: write to the keyboard buffer.
Baaad idea smiley

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).
Logged

- carpe noctem
Pages: [1]   Go Up
  Reply  |  New Topic  |  Print  
 
Jump to:  
   Forum Home   Thread Marks Chat! Downloads Search Login Register  

DonationCoder.com | About Us
DonationCoder.com Forum | Powered by SMF
[ Page time: 0.062s | Server load: 0.18 ]