Need help here, I'm trying to create a process in c++ with the windows api, whats happening is the process is being created which is cmd.exe however I want cmd.exe to open cd'd at a certain directory i.e. root c:\, however the process is opened at the dir of the executable.
I tried passing in "cd \" as the second argument of the CreateProcess function to no avail
Here's a snippet of the code:
TCHAR program[] = TEXT("C:/Windows/System32/cmd.exe");
TCHAR command[] = TEXT("cd /");
STARTUPINFO info;
PROCESS_INFORMATION processInfo;
ZeroMemory(&info,sizeof(STARTUPINFO));
ZeroMemory(&processInfo,sizeof(PROCESS_INFORMATION));
BOOL processResult =
CreateProcess(program,
command, NULL, NULL,
TRUE, CREATE_NEW_CONSOLE,
NULL, NULL,
&info,
&processInfo);
if(!processResult){
std::cerr << "CreateProcess() failed to start program \""
<< program << "\"\n";
exit(1);
}
std::cout << "Started program \""
<< program << "\" successfully\n";
Help would be extremely appreciated!
Thanks
If you want the cd / (or any other command) to have any effect, you need to use either the /k or /c flags for the command prompt. You can look these switches up in the documentation for cmd.exe, but basically, /c runs the command and then terminates, while /k runs the command and keeps the console session open. You almost certainly want /k here.
But really, you should be specifying the directory as the working directory for the process, not executing a change-directory command.
You can do this easily by calling the ShellExecute function, as Raw N suggested. The working directory is one of its parameters. ShellExecute (or ShellExecuteEx) is easier to use than CreateProcess, and should be preferred unless you need some special low-level behavior that you can only get with CreateProcess.
This works with CreateProcess too: pass the path as the lpCurrentDirectory parameter.
Whatever you do, don't hard-code paths! Use the %comspec% environment variable on Windows NT. It would also work to just execute cmd, letting the default search paths do their job.
Related
As the title may suggest, i am trying to open a .bat file via "ShellExecute" function.
It works with very basic .bat scripts, such as "hello world" ones, but won't work with others containing commands for running game servers.
For example, here is a batch script for a "Killing Floor 1" server:
ucc server KF-Mountainpass.rom?game=KFmod.KFGameType?VACSecured=true?MaxPlayers=6?GamePassword=genrl -log=server.log
PAUSE
Please note that this batch works perfectly when manually clicking on it, but gives the following error when opened via ShellExecute:
"ucc" is not recognized as an internal or external command, operable program or batch file.
I have also tested on other batch files for other game servers, having the same result.
So, here is a list of what i have tried so far, and did not work:
ShellExecute(NULL, "open", "cmd.exe", "C:\\windows\\system32\\cmd.exe /C C:\\Cartella_Server\\Server_KF1\\System\\KF_Server_Launcher.bat", NULL, SW_SHOW);
ShellExecute(NULL,"open", C:\\Cartella_Server\\Server_KF1\\System\\KF_Server_Launcher.bat", NULL, NULL, SW_SHOW);
ShellExecute(NULL, "open", "cmd.exe", "/C C:\\Cartella_Server\\Server_KF1\\System\\KF_Server_Launcher.bat", NULL, SW_SHOW);
Is there any solution to this?
Thanks in advance for your time :)
It is because the script is loading inside the directory of cmd.exe
Why? Because you didn't fill the working directory field.
Have a look at the 5th parameter of ShellExecute:
https://msdn.microsoft.com/en-us/library/windows/desktop/bb762153%28v=vs.85%29.aspx
Most likely, the ucc program is in the same directory as tha launcher script. So it works when you click on it, because your current directory is one with the file, but when you run your program your current directory is different.
Solution - provide proper directory in fifth ShellExecute argument, as per https://msdn.microsoft.com/en-us/library/windows/desktop/bb762153(v=vs.85).aspx
In my line of work I use msconfig a lot and I'm wanting to create a tool with various buttons on it so I can easily access my most commonly used programs. I'm using the Win32API to create the GUI and buttons, however I am having trouble getting msconfig to run. In my program I have
void callMsconfig()
{
ShellExecute(NULL,(LPCWSTR)L"open", (LPCWSTR)L"C:\\Windows\\System32\\msconfig.exe", NULL, NULL, SW_SHOWDEFAULT);
}
and an action statement so when the button is pressed the function is called. I've tried replacing ShellExecute() with system() and CreateProcess(). I've also replaced "open" with "runas" and the most I've gotten is the error saying C:\Windows\System32\msconfig.exe cannot be found when I know it is there because I've checked. What am I doing wrong? I'm using Windows 10 Home if that helps any.
If you have created a 32bit app that is running inside of the WOW64 emulator on 64bit systems, the C:\Windows\System32\ folder is silently redirected by WOW64 to the C:\Windows\SysWOW64\ folder, which does not have an msconfig.exe file. You need to account for that. Either create a 64bit executable, or use the Sysnative alias in 32bit code that runs inside of WOW64. Sysnative is documented on MSDN:
File System Redirector:
32-bit applications can access the native system directory by substituting %windir%\Sysnative for %windir%\System32. WOW64 recognizes Sysnative as a special alias used to indicate that the file system should not redirect the access. This mechanism is flexible and easy to use, therefore, it is the recommended mechanism to bypass file system redirection. Note that 64-bit applications cannot use the Sysnative alias as it is a virtual directory not a real one.
Try something more like this:
#include <shlwapi.h>
void callMsconfig()
{
BOOL IsWow64 = FALSE;
WCHAR szCmdLine[MAX_PATH] = {0};
IsWow64Process(GetCurrentProcess(), &IsWow64);
if (IsWow64)
{
GetWindowsDirectoryW(szCmdLine, MAX_PATH);
PathAppendW(szCmdLine, L"Sysnative");
}
else
{
GetSystemDirectoryW(szCmdLine, MAX_PATH);
}
PathAppendW(szCmdLine, L"msconfig.exe");
ShellExecuteW(NULL, NULL, szCmdLine, NULL, NULL, SW_SHOWDEFAULT);
}
However, do note that if UAC is enabled and you try to launch msconfig.exe from a 32bit process running inside of WOW64, the 32bit process MUST be running elevated or else ShellExecute() (and CreateProcess()) will fail to find the file correctly. I don't know why, but that is how it works. UAC Elevation is not required when launching msconfig.exe from a 64bit process.
If you don't want to elevate your entire program, you will have to make it launch a separate elevated process that can then launch msconfig.exe. You could just have the program launch a second copy of itself with a command-line parameter so it knows to just launch msconfig.exe and then exit itself. To launch an elevated process, you can use ShellExecute() specifying the runas verb.
This is what I have, starting powershell.exe without the command and closing directly after it.
why doesnt it work?
int main(int argc, char *argv[])
{
[...]
CreateProcess( NULL, // No module name (use command line)
"powershell.exe -command \".C:\\test\\t.ps1\" ",
[...]
&si, // Pointer to STARTUPINFO structure
&pi ); // Pointer to PROCESS_INFORMATION structure
return 0;
}
in normal cmd the command would look like this:
powershell -command ".c:\test\t.ps1"
and in the file this one-liner, if you want to test it:
write-host "hello world" |out-file C:\test\hi.txt
should write hello world in the console and create hi.txt in the folder
The command line should be either:
CreateProcess(NULL, // No module name (use command line)
"powershell.exe -command \"& {C:\\test\\t.ps1}\"",
or
CreateProcess(NULL, // No module name (use command line)
"powershell.exe -file C:\\test\\t.ps1",
In general, for executing scripts use -File unless the exit code is important to you. If it is, use -Command because there is a bug with -File where it always returns 0 (success) even if there is an error.
If you want the execution of powershell.exe to prompt for elevation, use the ShellExecute API instead. Pass in "RunAs" for lpOperation and you can specify a hidden window with the nShowCmd parameter.
I wrote a project in windows form application in C++ by Visual Studio 2010. I need to open the cmd and then type special command and run other program.
I use this function :
system("cmd.exe /c dir c:\\");
but by this function I just saw cmd for a second and then it was disappeared.
then I add this line :
cin.get();
but it did not work.
also I use this function :
char program[] = "C:\Windows\System32\cmd.exe";
WinExec((LPCSTR)program, SW_SHOWMINIMIZED);
but it did not work either! Can you help me please?
Have you tried the following?
system("cmd /k dir c:\\");
/k keeps the cmd prompt window open after the executing process has terminated.
But, to be honest, it may be better to use the Windows Terminal Services API for finer control, if you so desire. But, depending on what you want to do - that might be overkill.
And, regarding your second question: don't forget to escape your backslashes in:
const char program[] = "C:\\Windows\\System32\\cmd.exe";
WinExec((LPCSTR)program, SW_SHOWMINIMIZED);
References:
https://superuser.com/questions/306167/how-to-prevent-the-command-prompt-from-closing-after-execution
You could try
cin.ignore();
maybe also in combination with cin.get()
cin.get();
cin.ignore();
I think normally cin.get() worked fine in my programs.
I'm using VS2010 and I would like to call an exe file which I've created in another directory.
I've tried the following:
int main(){
system("C:\\Users\\Li\\Desktop\\Debug\\modelExample_4pcs.exe");
return 0;
};
but I get "The system could not find the file specified" error.
I've tried to run the exe file directly from the command line, and it only works when I'm inside its directory.
Could you please tell me how can I run it from a different directory?
(I'm using win7)
Thanks,
Li.
You should try using CreateProcess Windows API funcion: http://msdn.microsoft.com/en-us/library/ms682425%28VS.85%29.aspx
Try opening the file for reading, just to check that you have the path right:
char* filename = "C:\\Users\\Li\\Desktop\\Debug\\modelExample_4pcs.exe" ;
FILE* fp = fopen (filename, "rb") ; // Open for reading, binayr mode
if (fp == 0) {
printf ("Duh! File not found\n") ;
exit (0) ;
}
printf ("File found\n") ;
fclose (fp) ;
// Now try the system call, as before:
system(filename);
What happens?
You should be able to use ShellExecute like so: (adjusting the params sent to ShellExecute for your situation) http://msdn.microsoft.com/en-us/library/bb762153(VS.85).aspx?ppud=4
HINSTANCE hinst = ShellExecute( NULL, _T("open"), commandLine.c_str(), additionalParams.c_str(), NULL, SW_RESTORE );
if(hinst <= (HINSTANCE)SHELLEXERROR)// see: http://msdn2.microsoft.com/en-us/library/bb762153.aspx for further info on the return values
Now given that you are using Win7, you may be having a privilege issue and you need to run at an elevated level (i.e. administrator) you can test this by opening cmd as admin and running your exe from another directory
and as Steve mentioned above you can certainly use CreateProcess.
HTH,
EB
System() may not be able to find cmd.exe to open your environment.
Try using cmd.exe to execute your app via the /C option.
System("C:\\WINDOWS\\system32\cmd.exe /C \"C:\\Users\\Li\\Desktop\\Debug\\modelExample_4pcs.exe\"");
Try this using CreateProcess. Less (or at least different) environmental dependencies than using system(). At least you will get a nice Win32 error code if this still fails.
http://msdn.microsoft.com/en-us/library/ms682425(VS.85).aspx
Check your path, and make sure you escape all characters: C:\\Users\Li..
Is the error from running the main program, not from launching modelExample_4pcs.exe? Try commenting out the system() call and see if you get the same error.
Your main program is not on the path when you're outside its folder...
Is modelExample_4pcs.exe trying to load another file from the current working folder, and THAT's what's generating the error?
Maybe try chdir() before the call to system().
Just change to the directory first, like you would do from the command prompt:
system("C: && CD \\Users\\Li\\Desktop\\Debug\\ && modelExample_4pcs.exe");