I want to start a process. To do so I called the CreateProcess method like this:
wchar_t *path = (wchar_t*) malloc(sizeof(wchar_t) * 500);
const char* const_path = "C:/Windows/notepad.exe";
for (int i = 0; i < strlen(const_path); i++)
{
path[i] = const_path[i];
}
PROCESS_INFORMATION pi;
STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
if (!CreateProcess(NULL,
path,
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&si,
&pi))
{
std::stringstream s;
s << "Could not start - Code " << GetLastError();
ui.processStateLabel->setText(s.str().c_str());
return;
}
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
Problem is: it gives me "Could not start - Code 0", which makes no sense, because error code 0 is successful operation and obviously (no window opened) the operation was not successful. What do I have to do to get this working?
As you already figured out, the string is not terminated. You might also want to quote the path.
You should call GetLastError before the std::stringstream object is created because you don't know what the constructor does under the hood, that will hopefully provide a better error code.
I forgot that strlen Method does not include the 0 termination, which is needed. Thus changing strlen(const_path) to strlen(const_path) + 1 in the for-loop is the solution.
Related
I have a C++ program which uses CreateProcess. This works fine when I manually trigger the application. However, when the application is triggered from the task scheduler it returns met the error code 6, what does this error-code refer to?
On the net I can't find any message corresponding to the error code?
The code I use:
int StartCommand(char* Command) {
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
bool CommandStatus = CreateProcess(NULL, Command, NULL, NULL, FALSE, CREATE_NO_WINDOW | CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB, NULL, NULL, &si, &pi);
AssignProcessToJobObject(FilerHandle, pi.hProcess); // Does not work if without CREATE_BREAKAWAY_FROM_JOB
ResumeThread(pi.hThread);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
if (CommandStatus) {
return pi.dwProcessId;
}
cout << GetLastError() << endl; //RETURNS ME 6
Message = "Couldn't start command!";
Exit(Message);
return 0;
}
Note that when I trigger it manually, the same command get's executed successfully
I am trying to dump a portion of the windows registry in a .txt file using the CreateProcess function. The code is along the lines of
PROCESS_INFORMATION pi;
STARTUPINFO si;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
CString cmdLine = "\"C:\\WINDOWS\\regedit.exe\" /e \"c:\\dump\\TestReg.txt\"
\"HKEY_LOCAL_MACHINE\\SOFTWARE\\MYSOFT\\\"";
LPSTR pCmdLine = (LPSTR)(const char*)cmdLine;
BOOL oc = CreateProcess(NULL, pCmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
if(oc == TRUE)
{
WaitForSingleObject(pi.hProcess, 1000);
GetExitCodeProcess(pi.hProcess, &exitCode);
if(exitCode != 0) ret = -1;
}
What I know
The CreateProcess returns TRUE and the last blocks executes
The process waits for the end and exits normally
However no file is produced at the end
The command line string works fine in command line, even when it operates from the same directory where the program is operating.
I have found something that is potentially useful where someone had basically the same problem. In the end it resulted in a dependency clash but the link does not explain very well how it was detected or fixed.
I use this code but i get a failed error: 2 i know that means the file doesn't exist but no idea what am doing wrong.
DWORD size = 1024;
TCHAR buff[1024];
int err = AssocQueryString(ASSOCF_INIT_IGNOREUNKNOWN, ASSOCSTR_EXECUTABLE, _T(".html"), NULL, buff, &size);
STARTUPINFOA si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
LPCSTR BrowLoc = (LPCSTR)buff;
if (!CreateProcessA(BrowLoc, // No module name (use command line)
NULL,
NULL, // Process handle not inheritable
NULL, // Thread handle not inhberitable
FALSE, // Set handle inheritance to FALSE
0, // 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());
getchar();
return 0;
}
I guess you are using unicode. In that case, force using multi-byte character for AssocQueryString().
Use the code below for the first 3 lines.
DWORD size = 1024;
char buff[1024];
int err = AssocQueryStringA(ASSOCF_INIT_IGNOREUNKNOWN, ASSOCSTR_EXECUTABLE, ".html", NULL, buff, &size);
Following the tutorial here, I decided to make a process class for C++ so that I did not have to constantly keep writing out the same code for starting a process. It does work starting the process, but when I pass a command line function, it does nothing. Example ("c:\\windows\\notepad.exe", "c:\\windows\\PFRO.txt"). What is the problem?
Note: format is just a basic formatting function, using vsprintf
class process
{
public:
static BOOL __stdcall start(LPCSTR _Proc_name, LPSTR _Command_line = NULL, LPSECURITY_ATTRIBUTES _Proc_attrib = NULL,
LPSECURITY_ATTRIBUTES _Thread_attrib = NULL, BOOL _Inherits_handles = FALSE, DWORD _Creation_flags = NULL,
LPVOID _Environment = NULL, LPCSTR _Cur_directory = NULL)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
if (!CreateProcess(_Proc_name, _Command_line, _Proc_attrib, _Thread_attrib,
_Inherits_handles, _Creation_flags, _Environment, _Cur_directory, &si, &pi))
{
fputs(format("process::start(...) failed [%d]\n", GetLastError()), stderr);
return false;
}
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return true;
}
};
int main()
{
process::start("c:\\windows\\notepad.exe", "c:\\windows\\PFRO.txt");
getchar();
}
When the command line parameter is parsed to provide arguments for a main function, the first token is taken to be the executable file. A called program might well try to open the second token as its file argument, and of course you there wasn't one.
The usual practice is to repeat the program name as the first token in the command line. For example
process::start("c:\\windows\\notepad.exe", "notepad c:\\windows\\PFRO.txt");
I am trying to open a PDF via Firefox with CreateProcess(), I am a beginner and know nothing about using CreateProcess, but in my last question someone pointed out the MSDN on it... it shows that:
To run a batch file, you must start the command interpreter;
set lpApplicationName to cmd.exe and set lpCommandLine to the
following arguments: /c plus the name of the batch file.
Therefore I created a batch file that runs perfectly fine with the system() command, there are no problems with the batch file.
I can't figure out why the system can't find the file and I don't know if its the batch file, the exe in the batch file, the PDF doc in the batch file or the location of cmd.exe... Any help is greatly appreciated...
void openPDF(char scansQueue[][MAX_NAME], int index)
{
// build batch file
char openPath[300];
char procCommand[MAX_NAME]="C:\\firefox";
char cmdEXE[MAX_NAME]="C:\\Windows\\System32\\cmd.exe";
fstream outfile;
outfile.open("C:\\firefox.bat");
copyCString(openPath,"\"C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe\"");
outfile << openPath;
outfile << ' ';
copyCString(openPath,"\"C:\\Scans\\");
catArray(openPath,scansQueue[index]);
catArray(openPath,"\"");
STARTUPINFOW si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
cout<<"PROCESS ATTEMPT"<<endl;
if(!CreateProcess((LPCTSTR)cmdEXE ,(LPWSTR)procCommand, NULL, NULL, false, 0, NULL, NULL, &si, &pi))cout << GetLastError();cout<<"PROCESS FAILED TO EXECUTE!!!";
}
This assumes the whole batch file thing is part of an XY problem, in that you don't really need to make a batch file, you really just want to launch Firefox with a command line parameter.
I also assume you don't really need to pass the whole array of filenames with an index for which to use, instead you should just pass the filename by itself as I did where I called the function.
#include <Windows.h>
#include <stdio.h>
void MsgBoxLastError()
{
LPWSTR lpMsgBuf = NULL;
if(FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPWSTR)&lpMsgBuf,
0, NULL ) != 0)
{
MessageBox(NULL, lpMsgBuf, L"Error", MB_OK);
}
LocalFree(lpMsgBuf);
}
void OpenWithFirefox(const char* Filename)
{
const WCHAR pathToFirefox[] = L"C:/Program Files (x86)/Mozilla Firefox/firefox.exe";
const WCHAR scanPrefix[] = L"file://C:/Scans/";
WCHAR fullCommandLine[MAX_PATH] = {0};
//Build full command line
swprintf_s(fullCommandLine, L"\"%s\" \"%s%S\"", pathToFirefox, scanPrefix, Filename);
STARTUPINFOW si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
BOOL success = CreateProcess(NULL, fullCommandLine, NULL, NULL, false, 0, NULL, NULL, &si, &pi);
if(success)
{
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
else
{
MsgBoxLastError();
}
}
int main()
{
const int MAX_NAME = 13;
char scansQueue[][MAX_NAME] =
{
"file1.pdf",
"file2.pdf"
};
for(int i = 0; i < 2; ++i)
{
OpenWithFirefox(scansQueue[i]);
}
return 0;
}