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.
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);
}
This question already has an answer here:
checking the return value of a command executed using CreateProcess
(1 answer)
Closed 2 years ago.
This question is related to a previously asked question found here:
I'm able to invoke another executable within my runProgram() function. However, before this runProgram() function returns back to main() and closes the handle for the process. I need to retrieve the value that the executable returns when it exits...
Here is my current application:
#include <Windows.h>
#include <exception>
#include <stdio.h>
#include <tchar.h>
#include <cstdint>
#include <iostream>
uint32_t runProgram(LPCSTR lpApplicationName) {
STARTUPINFOA si;
PROCESS_INFORMATION pi;
// Set the size of the structures
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
// Run the program
CreateProcessA(
lpApplicationName, // the path
NULL, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
CREATE_NEW_CONSOLE, // Opens file in seperate console
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi // Pointer to PROCESS_INFORMATION structure
);
uint32_t error = GetLastError();
if ( error != 0)
std::cerr << error << "\n";
// How to retrieve and store the result from the exiting program above...?
uint32_t cache_size = 0;
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return cache_size;
}
int main() {
try {
const uint32_t cache_size = runProgram("CacheQuerry.exe");
std::cout << cache_size << '\n';
}
catch (const std::exception& e) {
std::cerr << e.what() << "\n\n";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
And I want to store the return value from this executable into runProgram()'s local variable: cache_size.
Here is the main.cpp from the invoked program:
#include "CacheQuerry.h"
int main() {
int error = cache_info();
if (error != 0)
std::cout << error << '\n';
else
std::cout << '\n';
std::cout << "l1d_cache_size = " << l1d_cache_size() << std::endl;
std::cout << "cache line size = " << cache_line_size() << '\n';
return l1d_cache_size();
}
The invoked program will return the value produced by l1d_cache_size() when this program exits. This is the value that I want to store within runProgram()'s cache_size variable. How do I get this return value after the program exits? The implementation of the function call found in "CacheQuerry.h" shouldn't be relevant here, but if you need to see it's implementation don't hesitate to ask. These are two separate projects within the same solution. The 1st main.cpp which is in its own project relies on the 2nd main.cpp within its own project.
You can get it by calling GetExitCodeProcess (pi.hProcess), after waiting on the handle but before you close it.
The exact code you need is:
DWORD exit_code;
BOOL ok = GetExitCodeProcess (pi.hProcess, &exit_code);
Strange this is not mentioned in the Remarks section for CreateProcess at all.
In c++ I want to open my text file with notepad, BUT:
Not to stop the program or wait to close the notepad...
Not to create a console/cmd tab (I'am using Visual studio 2017, windows)
Is it possible ?
I have this :
_popen("notepad.exe C:\X\X\X.txt", "r");
but it open a cmd tab.
(Windows only solution)
By modifying the example: https://learn.microsoft.com/en-us/windows/win32/procthread/creating-processes
for C++:
#include <iostream>
#include <Windows.h>
int main(int argc, char* argv[])
{
if (argc != 2)
{
std::cout << "Usage: " << argv[0] << " [cmdline]\n";
return EXIT_FAILURE;
}
STARTUPINFOA si = {sizeof(si)};
PROCESS_INFORMATION pi = {};
// Start the child process.
if (!CreateProcessA(nullptr, // No module name (use command line)
argv[1], // Command line
nullptr, // Process handle not inheritable
nullptr, // Thread handle not inheritable
false, // Set handle inheritance to FALSE
0, // No creation flags
nullptr, // Use parent's environment block
nullptr, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi)) // Pointer to PROCESS_INFORMATION structure
{
std::cout << "CreateProcess failed (" << GetLastError() << ").\n";
return EXIT_FAILURE;
}
// Wait until child process exits.
//WaitForSingleObject(pi.hProcess, INFINITE);
// Close process and thread handles.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return EXIT_SUCCESS;
}
I'm trying to read the std output of an external process (pgdump ) that I started with CreateProcess. I got this working with anonymous pipes but then the output is blocked and no like when I execute it via the commandline( missing end output). I have read numerous posts and discovered that I need CreateNamedPipes with WaitForSingleObject but I can't seem to get it to work. This is my working code with anonymous pipe but blocked and I'm missing the end of the output
#include <QDebug>
#include <QString>
#include <windows.h>
#include <sstream>
#include <iostream>
#include <random>
int main()
{
#define BUFFERSIZE 256
std::string program = "\"C:\\Program Files (x86)\\PostgreSQL\\10\\bin\\pg_dump.exe\"" +
std::string( " --dbname=postgresql://postgresUser:PostGresql13#127.0.0.1:5432/employee -j1 -Fd -b -v -f "
"C:\\development\\myproject\\Build\\debug\\1-export.psql");
HANDLE hReadStdOut = NULL;
HANDLE hWriteStdOut = NULL;
SECURITY_ATTRIBUTES saAttr;
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
ZeroMemory( &saAttr, sizeof( SECURITY_ATTRIBUTES ));
ZeroMemory( &piProcInfo, sizeof( PROCESS_INFORMATION ));
ZeroMemory( &siStartInfo, sizeof( STARTUPINFO ));
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
OVERLAPPED sOverlap;
if( !CreatePipe(&hReadStdOut, &hWriteStdOut, &saAttr, 0) )
{
std::ostringstream os;
os << GetLastError();
qDebug() << "create pipe error : " << QString::fromStdString( os.str());
}
TCHAR* szCmdline = new TCHAR[ program.size() + 1];
szCmdline[ program.size()] = 0;
std::copy( program.begin(), program.end(), szCmdline );
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.hStdError = hWriteStdOut;
siStartInfo.hStdOutput = hWriteStdOut;
siStartInfo.hStdInput = NULL;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
BOOL bSuccess = CreateProcess( NULL, szCmdline, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &siStartInfo,&piProcInfo );
if ( ! bSuccess )
{
std::ostringstream os;
os << GetLastError();
qDebug() << "create process error : " << QString::fromStdString( os.str());
}
else
{
CloseHandle( hWriteStdOut );
DWORD err;
DWORD nBytesRead;
char buf[BUFFERSIZE + 1];
int i(1);
for(;;)
{
std::cout << "iteration " << std::to_string( i ) << std::endl;
if( !ReadFile( hReadStdOut, buf, sizeof( buf), &nBytesRead, NULL) || !nBytesRead )
{}
if( GetLastError() == ERROR_SUCCESS )
{
}
std::cout.flush();
buf[nBytesRead] = '\0';
std::string string_ = buf;
std::cout << string_ << std::endl;
std::size_t found = string_.find("contents of");
if( !nBytesRead )
break;
i++;
}
CloseHandle(piProcInfo.hProcess);
CloseHandle(piProcInfo.hThread);
}
return 0;
}
For example, if your pg_dump.exe just write one line to standard output. There are several ways:
std::cout << "Hello World!\n";
printf("Hello World!\n");
std::cout << "Hello World!\n"<< std::endl;
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), "Hello World!\n", 14, &dwWritten, NULL);
If the pg_dump.exe exit after write the line, the ReadFile will not blocked and return with the line "Hello World!".
However, if the pg_dump.exe doesn't exit after write the line and continue other work. The first two write ways (1., 2.) will result in ReadFile blocked. But if you use the third or fourth way the ReadFile will block and return with the line "Hello World!".
What's the difference here is the first two write ways (std::cout << "Hello World!\n"; and printf("Hello World!\n");) has no flush operation at end of write but the third or fourth way has. std::endl and WriteFile flush the output buffer.
Summary:
Flush the output to cause it to be written to the underlying stream (which may be a file, a terminal or a pipe). Standard output is flushed at the following conditions:
When the program ends normally.
Use std::endl at the end.
Use WriteFile.
You can check if it is your case.
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;
}