hi all
i'm new to c++ and decided to tackle c++ by doing a small project

i would like to write a program that will start other programs in the background and get its pid number

so far, i have used system() but i get the output of that program

anyone care to mentor me?

i just looked at that link and it appears that that is for linux.

btw. is this for windows?

does CreateProcess() work?

I'm sorry. You said "pid" and I immediately went into *nix mode.

In Windows the terminology is that each process has a handle. Which is the same thing. Go figure.

Anyway, yes, CreateProcess() is what you want. Here's a little function to automate it a little for simple (usual) cases.

#include <string>
#include <windows.h>

HANDLE ExecProcess(
  const std::string& arg0,
  const std::string& args,
  LONGBOOL is_inherit_handles = TRUE
  ) {
  HANDLE              result = INVALID_HANDLE_VALUE;
  std::string         cmdline;
  STARTUPINFO         startup_information = {0};
  PROCESS_INFORMATION process_information = {0};

  startup_information.cb = sizeof( STARTUPINFO );
  cmdline = string( '\"' ) +arg0 +"\" " +args;

  if (CreateProcess(
    arg0.c_str(),           // full path of program to execute
    cmdline.c_str(),        // complete command line
    NULL,                   // no process attribute handle inheritance
    NULL,                   // no thread attribute handle inheritance
    is_inherit_handles,     // such as stdin, etc.
    NORMAL_PRIORITY_CLASS,  // 
    NULL,                   // use the parent's environment
    NULL,                   // use the parent's current working directory
    &startup_information,   // (all defaults)
    &process_information    // resulting process info
    ))
    result = process_information.hProcess;

  CloseHandle( process_information.hThread );
  return result;
  }

You can use the returned handle to obtain information about the child process and wait for specific events. For example, to wait for the child to terminate, use

WaitForSingleObject( my_childs_process_handle, INFINITE );

Hope this helps.

Well good grief. Is there some sort of timeout on editing posts? I haven't been gone that long.

Anyway, to fix a couple of simple errors in the last...

#include <string>
#include <windows.h>

HANDLE ExecProcess(
  const std::string& arg0,
  const std::string& args,
  BOOL is_inherit_handles = TRUE
  ) {
  HANDLE              result = INVALID_HANDLE_VALUE;
  std::string         cmdline;
  STARTUPINFO         startup_information = {0};
  PROCESS_INFORMATION process_information = {0};

  startup_information.cb = sizeof( STARTUPINFO );
  cmdline = std::string( 1, '\"' ) +arg0 +"\" " +args;

  if (CreateProcess(
    arg0.c_str(),           // full path of program to execute
    const_cast<char*>(
          cmdline.c_str()), // complete command line
    NULL,                   // no process attribute handle inheritance
    NULL,                   // no thread attribute handle inheritance
    is_inherit_handles,     // such as stdin, etc.
    NORMAL_PRIORITY_CLASS,  // 
    NULL,                   // use the parent's environment
    NULL,                   // use the parent's current working directory
    &startup_information,   // (all defaults)
    &process_information    // resulting process info
    ))
    result = process_information.hProcess;

  CloseHandle( process_information.hThread );
  return result;
  }

Thank you for that snippet.

I'll have to study it for a while to get the hang of things since I've been working with php for a long time now

how would you call the function, ExecProcess()?

Ah, you've been brain-damaged by PHP. My condolences... er,

Oh, so you know PHP? Cool!

:)


Call it with the full path to your program and the command line arguments exactly as you would type them at the prompt: ExecProcess( "C:\WINDOWS\notepad.exe", "myfile.txt" ); If you don't like the idea of the new program having access to your open file descriptors, set the last argument to FALSE.

Hope this helps.

Do you not like php?

When I go to debug, I got the errors in my build log

1>------ Build started: Project: VanaManager, Configuration: Debug Win32 ------
1>Compiling...
1>ExecProcess.cpp
1>c:\documents and settings\asianguyjtran\desktop\vanamanager\vanamanager\execprocess.cpp(29) : error C2664: 'CreateProcessW' : cannot convert parameter 1 from 'const char *' to 'LPCWSTR'
1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>VanaManager.cpp
1>c:\documents and settings\asianguyjtran\desktop\vanamanager\vanamanager\execprocess.cpp(29) : error C2664: 'CreateProcessW' : cannot convert parameter 1 from 'const char *' to 'LPCWSTR'
1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>Generating Code...
1>Build log was saved at "file://c:\Documents and Settings\asianguyjtran\Desktop\VanaManager\VanaManager\Debug\BuildLog.htm"
1>VanaManager - 2 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

I think you need to disable unicode to remove those errors.
Try adding:

#undef UNICODE

at the very beginning of your source code.

You're right, but if the OP wants to use unicode (no idea why, but: )
You could call CreateProcess like this: CreateProcess(L"yourexe.exe", L"parameters", ....etc);

Yes, my example assumes you are using ANSI strings, not Unicode. You'll have to change the types appropriately:
std::string --> std::wstring
const_cast<char*>(...) --> const_cast<wchar_t*>(...)

If it makes a difference, you can wrap the appropriate code in #ifdefs for UNICODE

#ifdef UNICODE
const std::wstring& arg0,
const std::wstring& args,
#else
const std::string& arg0,
const std::string& args,
#endif

etc.

Thanks for the replies thusfar

I'm having a little trouble with calling the function and whatnot but I think I'll be able to figure it out

Another question.
Is it safe to put the code found in the 5th post in a file called ExecProcess.cpp and include it in the main file via #include ExecProcess.cpp?

That's actually what I had in mind.

Put the stuff in post 5 (with the UNICODE additions) into its own cpp file.
Then make a same-named hpp file to match it:

#ifndef EXECPROCESS_HPP
#define EXECPROCESS_HPP

#include <windows.h>

#ifdef UNICODE
HANDLE ExecProcess(
  const std::wstring& arg0,
  const std::wstring& args,
  BOOL is_inherit_handles = TRUE
  );
#else
HANDLE ExecProcess(
  const std::string& arg0,
  const std::string& args,
  BOOL is_inherit_handles = TRUE
  );
#endif

#endif

Then, #include "execprocess.hpp" in your program's code, and compile and link both cpp files. Using GCC it would be:

g++ myprog.cpp createprocess.cpp

Hope this helps.

I got the program to start, however, the output of the program showing.
Is it possible to have it run silently?

Also, to use
WaitForSingleObject( my_childs_process_handle, INFINITE );
How do I define my_childs_process_handle?

Here is what I've tried

#include <cstdlib>
#include <iostream>
#include "execprocess.hpp"

using namespace std;

int main(int argc, char *argv[])
{
    int LoginServer;
    cout << "Starting LoginServer ..." << endl;
    LoginServer = ExecProcess("LoginServer.exe", "LoginServer.log");
    getchar();
    return EXIT_SUCCESS;
}

Oh, by "in the background" you meant that you don't want to see it running...

You'll have to fill out the STARTUPINFO structure with the proper information. Make the following adjustments to the cpp file:

HANDLE ExecProcess(
  #ifdef UNICODE
  const std::wstring& arg0,
  const std::wstring& args,
  #else
  const std::string& arg0,
  const std::string& args,
  #endif
  BOOL is_inherit_handles,
  BOOL is_show_window
  ) {
  //same stuff as before
  ...
  STARTUPINFO startup_information = {0};
  ...
  startup_information.cb          = sizeof( STARTUPINFO );
  startup_information.dwFlags     = STARTF_USESHOWWINDOW;
  startup_information.wShowWindow = is_show_window ? SW_SHOW : SW_HIDE;
  ...
  //same stuff as before
  }

and to the header file:

...
HANDLE ExecProcess(
  #ifdef UNICODE
  const std::wstring& arg0,
  const std::wstring& args,
  #else
  const std::string& arg0,
  const std::string& args,
  #endif
  BOOL is_inherit_handles = TRUE,
  BOOL is_show_window     = TRUE
  );
...

Now when you call it, do it as:

HANDLE my_childs_handle = ExecProcess( "fooey", "", TRUE, FALSE );

Hope this helps.

I'm lost at this piece here

BOOL is_inherit_handles,
BOOL is_show_window

When I go to compile, I get this error

[Linker error] undefined reference to `ExecProcess(std::string const&, std::string const&, int)'

Everything else seems okay

You need to include the .cpp file, containing the ExecProcess() code, to your build process.
If you are working with an IDE, add that file to your project.

It looks like you haven't updated one of your files properly.

execprocess.cpp

// execprocess.cpp

#include "execprocess.hpp"

HANDLE ExecProcess(
  #ifdef UNICODE
  const std::wstring& arg0,
  const std::wstring& args,
  #else
  const std::string& arg0,
  const std::string& args,
  #endif
  BOOL is_inherit_handles,
  BOOL is_show_window
  ) {
  HANDLE              result = INVALID_HANDLE_VALUE;
  #ifdef UNICODE
  std::wstring        cmdline;
  #else
  std::string         cmdline;
  #endif
  STARTUPINFO         startup_information = {0};
  PROCESS_INFORMATION process_information = {0};

  startup_information.cb          = sizeof( STARTUPINFO );
  startup_information.dwFlags     = STARTF_USESHOWWINDOW;
  startup_information.wShowWindow = is_show_window ? SW_SHOW : SW_HIDE;  

  #ifdef UNICODE
  cmdline = std::wstring( 1, '\"' ) +arg0 +L"\" " +args;
  #else
  cmdline = std::string( 1, '\"' ) +arg0 +"\" " +args;
  #endif

  if (CreateProcess(
    arg0.c_str(),           // full path of program to execute
    #ifdef UNICODE
    const_cast<wchar_t*>(
    #else
    const_cast<char*>(
    #endif
          cmdline.c_str()), // complete command line
    NULL,                   // no process attribute handle inheritance
    NULL,                   // no thread attribute handle inheritance
    is_inherit_handles,     // such as stdin, etc.
    NORMAL_PRIORITY_CLASS,  // 
    NULL,                   // use the parent's environment
    NULL,                   // use the parent's current working directory
    &startup_information,   // (all defaults)
    &process_information    // resulting process info
    ))
    result = process_information.hProcess;

  CloseHandle( process_information.hThread );
  return result;
  }

// end execprocess.cpp

execprocess.hpp

// execprocess.hpp

#ifndef EXECPROCESS_HPP
#define EXECPROCESS_HPP

#include <string>
#include <windows.h>

HANDLE ExecProcess(
  #ifdef UNICODE
  const std::wstring& arg0,
  const std::wstring& args,
  #else
  const std::string& arg0,
  const std::string& args,
  #endif
  BOOL is_inherit_handles = TRUE,
  BOOL is_show_window     = TRUE
  );

#endif

// end execprocess.hpp

In your program:

#include <windows.h>
#include "execprocess.hpp"

...

HANDLE child_pid = ExecProcess( "fooey.exe", "/a quux", TRUE, FALSE );
if (child_pid != INVALID_HANDLE_VALUE)
  WaitForSingleObject( child_pid, INFINITE );
else complain();

...

When you compile, make sure that both your program's cpp and execprocess.cpp are included in the build. If you are using the command line, that would be something like g++ myprog.cpp execprocess.cpp ... If you are using VC++ or Code::Blocks or whatever, there is a Project menu that lets you list the files that are part of the project.

Hope this helps.

This article has been dead for over six months. Start a new discussion instead.