The Command CreateProcess With the command WaitForSingleObject
can to open an image?
If Yes How can I open the image?
I tried to open but i don't know Where to put the path to open
if (CreateProcess(NULL, "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Accessories\Paint.lnk", NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
{
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
If you just want to open an existing image using defualt app then use ShellExectue API. For example:
ShellExecuteW(NULL, L"open", L"Z:\\cat.PNG", NULL, NULL, SW_SHOW);
You could also open image with mspaint using the same API:
ShellExecuteW(NULL, L"open", L"C:\\Windows\\system32\\mspaint.exe", L"Z:\\cat.PNG", NULL, SW_SHOW);
ShellExecuteEx will let you wait for finishing process.
You can do the same using CreateProcess. As #DavidHeffernan pointed out the second parameter of CreateProcess should point to writable memory else it will raise access violation. To make it clear I will just omit the first parameter. Example:
STARTUPINFOW process_startup_info{ 0 };
process_startup_info.cb = sizeof(process_startup_info); // setup size of strcture in bytes
PROCESS_INFORMATION process_info{ 0 };
wchar_t commandline_args[] = L"\"C:\\Windows\\system32\\mspaint.exe\" Z:\\cat.PNG";
if (CreateProcessW(NULL, commandline_args, NULL, NULL, TRUE, 0, NULL, NULL, &process_startup_info, &process_info))
{
//WaitForSingleObject(process_info.hProcess, INFINITE); // uncomment to wait till process finish
CloseHandle(process_info.hProcess);
CloseHandle(process_info.hThread);
}
I strongly recommend to read this CodeProject article (A newbie's elementary guide to spawning processes).
The CreateProcess function can only start .exe and .bat files. Use ShellExecute[Ex] if you want to launch files the same way the shell/Explorer does.
A process must have a PE EXE file as its main file and if you ask CreateProcess to start something else it is just going to fail. ShellExecute will look up the file extension in the registry to find the correct executable (or COM handler) to execute and this often ends up calling CreateProcess on your behalf with the file you specified as a command line parameter.
Using ShellExecuteEx with the SEE_MASK_NOCLOSEPROCESS flag might might give you a process handle you can wait on but you also have to be prepared for hProcess being NULL. This can happen if the registered application for the file type is already running and DDE or COM was used to open the file in this existing application instance...
Related
I'm new to the windows services and visual studio. I am trying to start a .exe file from a wind32 application. The code works fine and there is no error. I am using a CreateProcess() method and checked whether the method is running properly. There is no issues in it. The .exe file which i am calling simply creates text document. When i call that .exe file from console, it works fine, it creates the file. But when I call it from the wind32 app, it does not create any file. I am using Visual studio 2019. This is my code for calling the .exe file. `
STARTUPINFO info;
PROCESS_INFORMATION processInfo;
ZeroMemory(&info, sizeof(info));
info.cb = sizeof(info);
ZeroMemory(&processInfo, sizeof(processInfo));
LPCWSTR path = L"C:\\HP\\...(pathofexe).exe";
bool bSuccess = CreateProcess(path, NULL, NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo);
if (bSuccess)
{
cout << "Success";
}
else
{
cout << "Error : " << GetLastError() << endl;
}`
Rgarding the working directory mismatch that was discussed in the comments, The file may not be there because it's simply somewhere else.
You call:
CreateProcess(path, NULL, NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo);
Assuming you've read the documentation, you know the 8th parameter specifies the directory where the new process will run. Because you use NULL, this directory will be the same as that of the caller process, I assume "C:\\Users\\HP\\source\\repos\\ThisThingsName\\Debug\\".
That alone is not a problem, but given the context I believe the callee (SampleService.exe) calls the file function from its relative path, "\\Success.txt", rather than the full path, is that right?
In that case, when you open SampleService.exe manually, Success.txt would appear in "C:\\Users\\HP\\source\\repos\\SampleService\\Debug\\". However, when you open it using CreateProcess, it runs in "C:\\Users\\HP\\source\\repos\\ThisThingsName\\Debug\\" (because you did not specify otherwise), which is also where Success.txt would appear.
As I type this, I'm starting to doubt it, actually. Haven't you checked where it appears in Explorer?
So, curious problem, I'm trying to create a process, and then resume it, mostly exploring the Windows API. I've noticed that if I do this:
system("C:\\Windows\\System32\\calc.exe");
It will open a calculator exe, however if I try to do the same thing using CreateProcessA, I get this:
STARTUPINFO starting_info;
PROCESS_INFORMATION process_info;
// let's try and make a process
if (!CreateProcessA(NULL, "C:\\Windows\\System32\\calc.exe", NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &starting_info, &process_info)) {
return;
}
// resume thread
NtResumeThread(process_info.hThread, NULL);
This for some reason throws an error of 0xc0000142 most of the times when it "creates" the process, else it just fails.
What's going on?
See the following MSDN sample code for creating a process:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682512(v=vs.85).aspx
You need to zero out the si and pi structs, also set
si.cb = sizeof(si);
In the end, close process and thread handles.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
using this code snippet:
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
char szExe[] = "C:\\Apps\\Desktop\\Release\\simplesample.exe";
//char szExe[] = "C:\\Windows\\System32\\notepad.exe";
if(CreateProcess(0, szExe, 0, 0, 0, 0, 0, 0, &si, &pi))
{
// optionally wait for process to finish
WaitForSingleObject(pi.hThread, 0);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
return 0;
when I use notepad.exe, notepad gets launched.
However, when I use the path to simplesample.exe, it launches simplesample and crashes immediately. I fail to understand why simplesample won't launch properly from createProcess.
I can launch simplesample.exe from command prompt as is.
PS: Simplesample is a dx sample app using winmain
Ty to pass directory where simplesample.exe is to lpCurrentDirectory parameter of CreateProcess(). Probably, this program searches for assets, shaders or DLLs in current folder, but receives directory of calling process and thus it cannot find them.
From docs:
lpCurrentDirectory [in, optional]
The full path to the current directory for the process. The string can also specify a UNC path.
If this parameter is NULL, the new process will have the same current drive and directory as the calling process. (This feature is
provided primarily for shells that need to start an application and
specify its initial drive and working directory.)
I have two separate executable files, A.exe & B.dontrun, where A.exe launches B.dontrun after doing some initialization. The two processes then communicate to each other and A.exe exits after B.dontrun exits. This all behaves fine using CreateProcess and passing the executable name as the first argument when B.dontrun is named B.exe but if B.dontrun is named anything else (B.ex_ or B.bin) CreateProcess doesn't return an error, but the process isn't launched either.
I'd like B.dontrun to be named something that doesn't encourage people to run it directly, when they look in the directory they see A.exe and B.dontrun and there isn't confusion of which executable that they should be running.
At least up till and including Windows XP, the [cmd.exe] command interpreter recognizes a PE executable as such regardless of the filename extension, and runs it.
Which is one reason why it's not a good idea to start a text document with the letters "MZ"... ;-)
And which means that it’s not a good idea to try to prevent execution via filename mangling.
Instead, make the other process a DLL, and launch it via rundll32.
Cheers & hth.,
You need to specify the exe name in the cmd line argument rather than in the application name.
This works:
STARTUPINFO info;
ZeroMemory(&info, sizeof(info)); info.cb = sizeof(info);
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(pi));
TCHAR sz[1000]; // Note: lpCommandLine must be writable
lstrcpy(sz, L"c:\\users\\serge\\desktop\\notepad.dontrun");
CreateProcess(NULL, sz, NULL, NULL, FALSE, 0, NULL, NULL, &info, &pi);
printf("Error = %u\n", GetLastError());
This indeed gives a File not found error (2):
STARTUPINFO info;
ZeroMemory(&info, sizeof(info)); info.cb = sizeof(info);
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(pi));
CreateProcess(L"c:\\users\\serge\\desktop\\notepad.dontrun",
NULL, NULL, NULL, FALSE, 0, NULL, NULL, &info, &pi);
printf("Error = %u\n", GetLastError());
Note: Tested on Win7 x64
You should create the file as hidden.
CreateFile has an attribute you can use
FILE_ATTRIBUTE_HIDDEN 2 (0x2) The file is hidden. Do not include it in an ordinary directory listing.
Documentation here: http://msdn.microsoft.com/en-us/library/aa363858(VS.85).aspx
I am using CreateProcess() to run an external console application in Windows from my GUI application. I would like to somehow gather the output to know whether there were errors. Now I know I have to do something with hStdOutput, but I fail to understand what. I am new to c++ and an inexperienced programmer and I actually don't know what to do with a handle or how to light a pipe.
How do I get the output to some kind of variable (or file)?
This is what I have a the moment:
void email::run(string path,string cmd){
WCHAR * ppath=new(nothrow) WCHAR[path.length()*2];
memset(ppath,' ',path.length()*2);
WCHAR * pcmd= new(nothrow) WCHAR[cmd.length()*2];
memset(pcmd,' ',cmd.length()*2);
string tempstr;
ToWCHAR(path,ppath); //creates WCHAR from my std::string
ToWCHAR(cmd,pcmd);
STARTUPINFO info={sizeof(info)};
info.dwFlags = STARTF_USESHOWWINDOW; //hide process
PROCESS_INFORMATION processInfo;
if (CreateProcess(ppath,pcmd, NULL, NULL, FALSE, 0, NULL, NULL, &info, &processInfo))
{
::WaitForSingleObject(processInfo.hProcess, INFINITE);
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
}
delete[](ppath);
delete[](pcmd);
}
This code probably makes any decent programmer scream, but (I shouldn't even say it:) It works ;-)
The Question: How do I use hStdOutput to read the output to a file (for instance)?
Microsoft has an example in its knowledge base that demonstrates how to capture the output of a child console process. The basic principle is that the parent process creates pipes (one per standard handle to redirect) and passes the handles to CreateProcess.
The child process does not need to be modified for this to work, which is important if you do not have control over the child's source.
More information: How to spawn console processes with redirected standard handles