This question already has an answer here:
CreateProcess method ends up with an error
(1 answer)
Closed 6 years ago.
I was reading about CreateProcess function in c++ and I wanted to try it. Basic idea of the code is to have my main execute another process (notepad). Really, it’s just the basic code. When I run the program, I get:
First-chance exception at 0x752bb763 in createprocess.exe: 0xC0000005: Access violation writing location 0x00be57b8.
Unhandled exception at 0x752bb763 in createprocess.exe: 0xC0000005: Access violation writing location 0x00be57b8.
When I make a break point for where the error occurs, I get taken to tidtable.c (which is for accessing threads, I guess).
Specifically in tidtable.c at CRTIMP PFLS_GETVALUE_FUNCTION __cdecl __set_flsgetvalue()
I really don’t know what or how to avoid this problem. The error occurs with the CreateProcess call (ie, it never outputs the “out of create”).
My code is:
#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
#include <strsafe.h>
#include <direct.h>
#include <string.h>
#include <conio.h>
int main(VOID)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
//allocate memory
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
fprintf(stderr, "This is just a test");
//create child process
if (!CreateProcess(NULL,
L"C:\\Windows\\Notepad.exe",
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&si,
&pi))
{
fprintf(stderr, "create process failed");
return -1;
}
fprintf(stderr, "out of create");
//parent waits for child to complete
WaitForSingleObject(pi.hProcess, INFINITE);
fprintf(stderr, "after wait");
printf("Child Complete");
//close handle
CloseHandle(pi.hProcess);
// CloseHandle(pi.hthread);
}
If anyone knows how to overcome this problem, your help would be appreciated.
The problem is that the second parameter of the CreateProcess function is an in/out parameter.
If you specify it as a string like you did, it is a constant string and the function when it is called cannot write to the memory location, thus you have a memory access violation. The correct way is to call your function like this:
LPTSTR szCmdline = _tcsdup(TEXT("C:\\Windows\\Notepad.exe"));
//create child process
if (!CreateProcess(NULL,
szCmdline,
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&si,
&pi))
{
fprintf(stderr, "create process failed");
return -1;
}
You may also want to read this blog article.
The 2nd arg to CreateProcess cannot be const or a literal string because the func attempts to modify the string. Copy the literal to a local array and then pass that as the 2nd arg.
Related
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 4 months ago.
Improve this question
i have to pass a string into my process, but for some reason i can't
i've tried to pass a path and an argument in function, i've tried to put a \0 after the argument, i've tried to pass an argument or space + an argument but it doesn't passes.
could you please help me?
#include <stdio.h>
#include <tchar.h>
#include <iostream>
#include <string>
using namespace std;
void _tmain(int argc, TCHAR* argv[])
{
cout << "we are here!\n";
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
string first = "C:\\Users\\User\\source\\repos\\1\\x64\\Debug\\1.exe"; //Initializing a name of our file
wstring temp = wstring(first.begin(), first.end()); // Initializing an object of wstring
LPCWSTR file_name = temp.c_str(); // Applying c_str() method on temp
string s1 = " 1.exe 1\0";
LPWSTR cl1 = (LPWSTR)s1.c_str();
// Start the child process.
if (!CreateProcess(file_name, // No module name (use command line)
cl1, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
CREATE_NEW_CONSOLE, // Creating console for our application
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi) // Pointer to PROCESS_INFORMATION structure
)
{
printf("CreateProcess failed (%d).\n", GetLastError());
return;
}
// Wait until child process exits.
WaitForSingleObject(pi.hProcess, INFINITE);
// Close process and thread handles.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
cout << "we are done!\n";
}
thanks for your help in advance
Are you compiling in Unicode or Multibyte (MBCS)?
Assuming you are compiling in Unicode you can avoid the use of string objects and use wstring objects instead.
To initialize a wstring you have to prefix the double quoted string with an L, i.e.
wstring first(L"C:\\Users\\User\\source\\repos\\1\\x64\\Debug\\1.exe");
So, you can avoid the use of temp variable.
Note: Is more efficient to initialize a (w)string using the constructor instead of the assignment operator.
Also, the cast in
string s1 = " 1.exe 1\0";
LPWSTR cl1 = (LPWSTR)s1.c_str();
is nos valid, as s1.c_str() return type is const char* (or LPCSTR).
Instead, you can declare
wstring s1(L" 1.exe 1\0");
LPCWSTR cl1 = s1.c_str();
In fact, you don't need to assign the result of c_str() to another variable. You can call to c_str() when you are calling to CreateProcess. The code could be something as:
//Initializing a name of our file
wstring first(L"C:\\Users\\User\\source\\repos\\1\\x64\\Debug\\1.exe");
wstring s1(L" 1.exe 1\0");
// Start the child process.
if (!CreateProcess(first.c_str(), // No module name (use command line)
const_cast<LPWSTR>(s1.c_str()), // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
CREATE_NEW_CONSOLE, // Creating console for our application
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi) // Pointer to PROCESS_INFORMATION structure
)
{
printf("CreateProcess failed (%d).\n", GetLastError());
return;
}
If you are compiling with MBCS you should change wstring by string and remove the L prefix when initializing strings. The rest of the code could remain the same.
This question already has answers here:
I need to open an image with Microsoft Paint
(1 answer)
Open image with create process and ms paint
(1 answer)
Closed 11 months ago.
So I'm trying to open mspaint using winAPI. For some reason, the window doesn't shown and I don't know why. Here is my code:
#include <Windows.h>
#include <iostream>
int main()
{
STARTUPINFOA si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = true;
CreateProcessA("mspaint.exe", (LPSTR)"mspaint.exe", NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return 0;
}
Thanks for any help.
Apart from the lack of error checking in your code (and the illegal cast), if you refer to the documentation, you will see that:
The function will not use the search path.
So, unless mspaint.exe happens to reside in the current directory (which is most unlikely) then CreateProcess won't find it.
The best solution is to use ShellExecute, something along these lines (error checking omitted for brevity):
HINSTANCE hInstance = ShellExecuteA (NULL, "open", "mspaint.exe", NULL, NULL, SW_SHOWNORMAL);
Like CreateProcess, ShellExecute doesn't wait for the launched process to complete before returning. If you want to do that, you can use ShellExecuteEx passing the SEE_MASK_NOCLOSEPROCESS flag and then wait on the process handle returned before finally closing it (in the same way you are doing now).
I have a pre-compiled exe (native C++11) which crashes (access violation error) at some point in iterative process. I can not afford debugging it and re-compile it again for now.
I thought of a dirty solution. I will make another program that is responsible for executing that exe and when it stopped working, I simply re-execute it again.
Is it possible? How can I know that the program was stopped?
Note: I am on Windows and doing development using MSVS.
I have found a solution with help of #Richard Hodges.
Make a new program with the this code:
#include <Windows.h>
#include <string>
#include <iostream>
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
int main(int argc, const char**argv) {
while (true) {
TCHAR ProcessName[256];
STARTUPINFO si;
PROCESS_INFORMATION pi;
wcscpy(ProcessName, L"FaultyProgram.exe");
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
// Start the child process.
if (!CreateProcess(NULL, // No module name (use command line)
ProcessName, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
CREATE_NEW_CONSOLE, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi) // Pointer to PROCESS_INFORMATION structure
)
{
printf("CreateProcess failed (%d).\n", GetLastError());
return 0;
}
// Wait until child process exits.
WaitForSingleObject(pi.hProcess, INFINITE);
// Close process and thread handles.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
return 0;
}
And the most important part is to disable UI Error message when a program crash by changing this value in the registry:
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\Windows Error Reporting
"DontShowUI"=dword:00000001
instead of:
"DontShowUI"=dword:00000000
This question already has answers here:
CreateProcess() fails with an access violation [duplicate]
(3 answers)
Closed 9 years ago.
I am getting an exception when I run this code:
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
CreateProcess(NULL, L"program.dat", NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
// Wait until child process exits.
WaitForSingleObject( pi.hProcess, INFINITE );
// Close process and thread handles.
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
I get the exception on WaitForSingleObject.
Thanks :)
As clearly as much that can be stated in the documentation::
The Unicode version of this function, CreateProcessW, can modify the contents of this string. Therefore, this parameter cannot be a pointer to read-only memory (such as a const variable or a literal string). If this parameter is a constant string, the function may cause an access violation.
Yours L"program.dat" falls under this rule. Copy the string in some WCHAR variable and pass that instead.
I can reproduce the exception using your code. I think the problem is that the second arg to CreateProcess is an in/out one. The doc states:
The system adds a terminating null character to the command-line string to separate the file name from the arguments. This divides the original string into two strings for internal processing.
See CreateProcess function
The second arg must NOT point to read-only memory.
Using the Visual Studio debugger and stepping in assembler code, the trap is indeed caused by the _CreateProcessInternal function in Kernel32 trying to write 0x to the end of L"program.dat", which, as a string constant, is in a "non writable" section.
Use below code:
wchar_t * pCommandLine = L"program.dat";
wchar_t CommandLine[ 64 ];
wcscpy( CommandLine, pCommandLine );
CreateProcess(NULL, CommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
and the exception will vanish.
As for Creating a Child Process with "program.dat" ?!? That's another story.
I am using CreateProcess, but I can't start a process I am using the following code but I am getting the error "Invalid access to memory location" but I don't know why.
Is there any problem with my code?
#include <Windows.h>
#include <stdio.h>
//#include "common.h"
int main(void)
{
DWORD creation_flags = DEBUG_PROCESS;
STARTUPINFO startupinfo;
PROCESS_INFORMATION process_information;
char *path_to_exe = "D:\\dbg\\calc.exe";
startupinfo.dwFlags = 0x1;
startupinfo.wShowWindow = 0x0;
startupinfo.cb = sizeof(startupinfo);
if(CreateProcess( path_to_exe,
NULL,
NULL,
NULL,
NULL,
creation_flags,
NULL,
NULL,
&startupinfo,
&process_information)){
printf("We have successfully launched the process!\n");
printf("[*] PID: %d\n", process_information.dwProcessId);
}
else
printf("[*] Error: %d.\n", GetLastError());
}
You have only filled in 3 fields of the startupinfo Structure.
The remaining fields are filled with garbage, and some of that garbage is likely leading to bad problems.
You should fully initialize the structure, explicitly putting NULL, 0 and other "empty" values where you don't want to specify anything.
Try zeroing the startup info structure. Some of it's members (e.g. lpTitle) are used even if you don't set an explicit flag.
Also beware that CreateProcess may temporarily write to the application name string, so you may want to avoid passing a read-only string literal. This only happens with the unicode version of the function though, at least on recent versions of Windows.