I'm trying to recast a char* to a LPWSTR to use in the CreateProcess API-function. However, I can't get it to work properly. (Compiler is not complaining in the end, however CreateProcess keeps telling me it can't find the path specified (error-code)). This makes me assume that recasting the char* into a LPWSTR fails and therefore, the path is not accessible. (I also tried it with functions such as mbstowcs, but without any luck so far.
My sample-code:
int StartCommand(char* Command) {
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
cout << Command << endl; //Shows the right command
wchar_t wtext[20];
mbstowcs(wtext, Command, strlen(Command) + 1);//Plus null
LPWSTR CommandLPWSTR = wtext;
if (!CreateProcess(NULL, CommandLPWSTR, NULL, NULL, FALSE, CREATE_NO_WINDOW | CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB, NULL, NULL, &si, &pi)) {
cout << GetLastError() << endl;
cout << GetLastErrorAsString() << endl; //TELLS ME: Can't find the path specified
Message = "Couldn't start command!";
Exit(Message);
}
AssignProcessToJobObject(Handle, pi.hProcess); // Does not work if without CREATE_BREAKAWAY_FROM_JOB
ResumeThread(pi.hThread);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return pi.dwProcessId;
}
Pid = StartCommand((char*)("C:/notepad.exe").c_str());
Related
to launch an exe, I have wrote the CreateProcess of this thread How do I open an .exe from another C++ .exe?
this works but if my first program end the cmd will close and i want to keep my launched program running
my code looks like that
void Client::StartServer(){
//init process structures
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
// get working directory
char tmp[512];
GetModuleFileName(NULL, tmp, 512);
stringstream sstmp;
string stmp;
sstmp << tmp;
stmp = sstmp.str();
//remove name.exe from path
while(stmp.back() != '\\'){
stmp.pop_back();
}
//launch
sstmp.str("");
sstmp << stmp << "Sim_Server.exe";
cout << "start : " << sstmp.str() << " end "<< endl;
LPCTSTR path = sstmp.str().c_str();
if( !CreateProcess(path,NULL,NULL,NULL,false,CREATE_NEW_CONSOLE,NULL,NULL,&si,&pi) ){
throw runtime_error("unable to launch server");
}
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
So my task goes like this:
The program needs 2 processes in one main function
First process creates or opens a file "log.txt" which is in the same directory where the program is located. Then it adds user input to this file.
Second process is a "monitor" of this file. It checks if the file exists, shows its size and shows how many characters were entered since the second process started.
Note that I am aware that the program itself is a process, but it needs to be done like that. There are some "tips" to use a file as mutex (CreateFile parameters) that would be the dsShareMode with FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE parameter.
Now my question is: how do you create 2 processes to handle its own line of code? I've seen many examples of CreateProcess function but I don't really understand the first two parameters of this function
lpApplicationName
and
lpCommandLine
What am I supposed to pass to it in order to run 2 processes, one to handle the user input and the other to be the "monitor"?
The first process is meant to handle those lines of code:
std::string buffer;
std::cout << "Enter your text:" << std::endl;
getline(std::cin, buffer);
HANDLE hFile = CreateFile("log.txt", FILE_APPEND_DATA, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
DWORD written = 0;
WriteFile(hFile, buffer.c_str(), buffer.size(), &written, NULL);
While the second process should only care about this:
hFile = CreateFile("log.txt", FILE_READ_ATTRIBUTES, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hFile == INVALID_HANDLE_VALUE)
{
std::cout << "CreateFile error " << GetLastError() << std::endl;
}
else
{
DWORD size = GetFileSize(hFile, NULL);
std::cout << "\nCurrent file size: " << size << std::endl;
CloseHandle(hFile);
}
int stringLength = 0;
for(int i=0; buffer[i]; i++)
stringLength++;
std::cout << "\nCharacters given since last startup: " << stringLength << std::endl;
Assuming you have a separate helper.exe, you can do:
CreateProcess(nullptr, "helper logger-mode", ...)
and
CreateProcess(nullptr, "helper monitor-mode", ...)
This will create two processes that see either logger-mode or monitor-mode in their second argument (argv[1]).
The question appears to demand having the same program being run as two separate processes. If that is the case, the program will need to handle command line arguments and tailor its functionality accordingly.
#Botje I've managed to do something like that. Could you take a look at tell me if such solution is acceptable?
int main(int argc, char *argv[])
{
std::string cmdline1 = "main Proc1";
std::string cmdline2 = "main Proc2";
std::string buffer;
HANDLE hFile;
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
ZeroMemory(&pi, sizeof(pi));
si.cb = sizeof(si);
CreateProcess(argv[0], const_cast<char *>(cmdline1.c_str()), NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
CreateProcess(argv[0], const_cast<char *>(cmdline2.c_str()), NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
if(strcmp(argv[1], "Proc1"))
{
while(1)
{
std::cout << "Enter your text:" << std::endl;
getline(std::cin, buffer);
hFile = CreateFile("log.txt", FILE_APPEND_DATA, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
DWORD written = 0;
WriteFile(hFile, buffer.c_str(), buffer.size(), &written, NULL);
}
}
if(strcmp(argv[1], "Proc2"))
{
DWORD charactersGiven = 0;
while(1)
{
hFile = CreateFile("log.txt", GENERIC_READ, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hFile == INVALID_HANDLE_VALUE)
{
std::cout << "CreateFile error " << GetLastError() << std::endl;
}
else
{
DWORD size = GetFileSize(hFile, NULL);
std::cout << "\nCurrent file size: " << size << std::endl;
if(charactersGiven == 0)
charactersGiven = size;
std::cout << "Characters given since last startup: " << size - charactersGiven << std::endl;
}
Sleep(4000);
}
}
return 0;
}
I want to set priority class for child process, but SetInformationJobObject function failes with 1314 error code. So how to solve this?
#include <windows.h>
#include <iostream>
using namespace std;
int main() {
JOBOBJECT_BASIC_LIMIT_INFORMATION limits;
limits.LimitFlags = JOB_OBJECT_LIMIT_PRIORITY_CLASS;
limits.PriorityClass = HIGH_PRIORITY_CLASS;
HANDLE Job = CreateJobObject(NULL, NULL);
SetInformationJobObject(Job, JobObjectBasicLimitInformation, &limits, sizeof(limits));
cout << GetLastError() << endl;
AssignProcessToJobObject(Job, GetCurrentProcess());
STARTUPINFO cif;
ZeroMemory(&cif, sizeof(STARTUPINFO));
cif.cb = sizeof(STARTUPINFO);
PROCESS_INFORMATION pi;
CreateProcess("sp.exe", NULL, NULL, NULL, FALSE, 0, NULL, NULL, &cif, &pi);
cout << "Child process priority = " << GetPriorityClass(pi.hProcess);
CloseHandle(Job);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
GetPriorityClass must return 128, but returns 32.
for (int i = 0; i < n; i++)
{
const char* cstr = strings[i].c_str();
swprintf_s(fullCommandLine, L"\"%s\" \"%s\" %S", pathToModule, pathToFile, cstr);
if(CreateProcess(NULL,
(LPWSTR)fullCommandLine,
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&si,
&pi))
{
cout << "succes";
}
else cout << "fail";
}
I'm creating n procesess to find string in given file like this, and In my module(wchich looks for given string in file) I want to send messages to other n-1 processes to quit
while (file >> readout)
{
if (readout == search)
{
cout << "I found string";
SendMessage(/*what should be here*/);
}
}
From where I could get handles to those other processes?
Please see my PostThreadMessage to Console Application.
I created that because it certainly is possible to send a message to a console program, we just must make a message loop, just as it is possible to show a window from a console program.
Note that PostThreadMessage needs a thread id, not a process id. Every process also has a thread id and a process's thread id is in the PROCESS_INFORMATION from CreateProcess.
The following is a larger example but easier to use for demonstrating that PostThreadMessage works in console programs. This program will call itself (passing its thread id) if there is no argument for it then it will wait for the new process to send messages. If there is an argument then it will assume the argument is a thread id and send a message to that thread followed by a WM_QUIT.
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
TCHAR szCmdline[300];
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
BOOL bSuccess = FALSE;
ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION));
ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.hStdError = NULL;
siStartInfo.hStdOutput = NULL;
siStartInfo.hStdInput = NULL;
DWORD dwThread;
MSG Msg;
TCHAR ThreadIdBuffer[40];
// if no argument then execute ourself then wait for a message from that thread
if (argc == 1) {
_itot_s(GetCurrentThreadId(), ThreadIdBuffer, 40, 10);
szCmdline[0] = '"';
szCmdline[1] = 0;
_tcscat_s(szCmdline, 300, argv[0]); // ourself
int n = _tcslen(szCmdline);
szCmdline[n++] = '"';
szCmdline[n++] = ' ';
szCmdline[n++] = 0;
_tcscat_s(szCmdline, 300, ThreadIdBuffer); // our thread id
bSuccess = CreateProcess(argv[0], // execute ourself
szCmdline, // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
0, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION
if (!bSuccess) {
std::cout << "Process not started\n";
return 0;
}
std::cout << "Waiting\n";
// Now wait for the other process to send us a message
while (GetMessage(&Msg, NULL, 0, WM_USER)) {
if (Msg.message == WM_COMMAND)
std::cout << "WM_COMMAND\n";
else
std::cout << "Message: " << Msg.message << '\n';
}
std::cout << "End of message loop\n";
return 0;
}
// if there is an argument then assume it is a threadid of another one of us
std::cout << "Press Enter to send the message\n";
if (std::wcin.get() != '\n')
return 0;
dwThread = _wtoi(argv[1]);
if (!PostThreadMessage(dwThread, WM_COMMAND, (WPARAM)0, (LPARAM)0))
std::cout << GetLastError() << " PostThreadMessage error\n";
if (!PostThreadMessage(dwThread, WM_QUIT, (WPARAM)0, (LPARAM)0))
std::cout << GetLastError() << " PostThreadMessage error\n";
return 0;
}
I want to make a program that opens a windows explorer window, waits for 5 seconds, and then closes the window. I've tried the following:
#include "stdafx.h"
#include <windows.h>
#include <string>
#include <sstream>
#include <iostream>
using namespace std;
void _tmain( int argc, TCHAR *argv[] ) {
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
if( argc != 2 ) {
cout << "Usage: " << argv[0] << "<path>";
return;
}
// Build the command string.
wstring app = L"explorer.exe ";
wstring str_command = app + argv[1];
wchar_t* command = const_cast<wchar_t*>( str_command.c_str() );
// Open the window.
if( !CreateProcess( NULL, // No module name (use command line)
command, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
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
) {
cout << "CreateProcess failed: " << GetLastError();
return;
}
cout << "Opened window!" << endl;
// Wait for it.
Sleep(5000);
cout << "Done waiting. Closing... ";
// Close explorer.
HANDLE explorer = OpenProcess(PROCESS_TERMINATE, false, pi.dwProcessId);
if( !explorer ) {
cout << "OpenProcess failed: " << GetLastError();
return;
}
if( !TerminateProcess( explorer, 0 ) ) {
cout << "TerminateProcess failed: " << GetLastError();
return;
}
// Close process and thread handles.
CloseHandle( explorer );
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
cout << "Done.";
}
I get it to open well enough, but I can't get it to close. TerminateProcess fails with error code 5. I've also tried posting a WM_CLOSE message to the window. I get a success value out of that, but the window stays open.
Please help!
I found this thread:
Close all browser windows?
It says:
Use the InternetExplorer object to open each window and invoke the Quit method when done. This has the added benefit of closing only the windows you opened (so that windows opened by the user or other applications are unaffected).
https://msdn.microsoft.com/library/aa752127.aspx
I know that this does not help much (missing snippets), but at least something.