patterncMinor
Daemonize a process under Microsoft Windows
Viewed 0 times
processmicrosoftunderwindowsdaemonize
Problem
I wrote a simple tool to allow to daemonize any process under Microsoft Windows.
The goal is to push any process into the background with no questions asked. That includes GUI applications, which means that the main window will not be created...or at least not shown. For console applications it will simply detach the process from the current console and not open another one. Usage is simple:
So let's cut to the code:
```
#include
#include
#include
// The important things to note and know:
//
// * Only works with ASCII paths and filenames.
// * Quotes all arguments regardless of content.
// * SW_HIDE in STARTUPINFO is needed for GUI applications
// * DETACHED_PROCESS in CreateProcessA is needed for command line applications
//
int main(int argc, char *argv[]) {
if (argc 2) {
// We only need to concatenate arguments if there
// actually are arguments.
int idx;
// Calculate the length of all arguments
size_t argLength = 0;
for (idx = 1; idx < argc; idx++) {
argLength += strlen(argv[idx] + 2 + 1); // One for the space, two for the quotes.
}
argLength--; // Strip the last space.
// Reserve some memory and NULL the new string.
//The + 1 is the space for the last null character.
arguments = (char)malloc(sizeof(char) (argLength + 1));
arguments[0] = 0;
// Now concatenate the arguments.
for (idx = 1; idx < argc; idx++) {
strcat(arguments, "\"");
strcat(arguments, argv[idx]);
strcat(arguments, "\"");
if (idx < argc - 1) {
strcat(arguments, " ");
}
}
}
STARTUPINFO startInfo;
PROCESS_INFORMATION process;
ZeroMemory(&startInfo, sizeof(startInfo));
ZeroMemory(&process, sizeof(process));
startInfo.cb = sizeof(startInfo);
// Tell the system to use/honor the ShowWindow flags.
s
The goal is to push any process into the background with no questions asked. That includes GUI applications, which means that the main window will not be created...or at least not shown. For console applications it will simply detach the process from the current console and not open another one. Usage is simple:
daemonize.exe PROGRAM [ARGUMENTS]So let's cut to the code:
```
#include
#include
#include
// The important things to note and know:
//
// * Only works with ASCII paths and filenames.
// * Quotes all arguments regardless of content.
// * SW_HIDE in STARTUPINFO is needed for GUI applications
// * DETACHED_PROCESS in CreateProcessA is needed for command line applications
//
int main(int argc, char *argv[]) {
if (argc 2) {
// We only need to concatenate arguments if there
// actually are arguments.
int idx;
// Calculate the length of all arguments
size_t argLength = 0;
for (idx = 1; idx < argc; idx++) {
argLength += strlen(argv[idx] + 2 + 1); // One for the space, two for the quotes.
}
argLength--; // Strip the last space.
// Reserve some memory and NULL the new string.
//The + 1 is the space for the last null character.
arguments = (char)malloc(sizeof(char) (argLength + 1));
arguments[0] = 0;
// Now concatenate the arguments.
for (idx = 1; idx < argc; idx++) {
strcat(arguments, "\"");
strcat(arguments, argv[idx]);
strcat(arguments, "\"");
if (idx < argc - 1) {
strcat(arguments, " ");
}
}
}
STARTUPINFO startInfo;
PROCESS_INFORMATION process;
ZeroMemory(&startInfo, sizeof(startInfo));
ZeroMemory(&process, sizeof(process));
startInfo.cb = sizeof(startInfo);
// Tell the system to use/honor the ShowWindow flags.
s
Solution
It looks good: very good, assuming it works (i.e. has the run-time behaviour that you want: I don't know the effect of calling
You don't
I don't see why you need the
Instead of
Also, shouldn't it be
If when you say "C/C++" you mean "C++", then it's more conventional these days to use
For example, using
The reason for
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.
... which helps to explain why arguments must be
CreateProcess in that way).You don't
free(arguments) but that doesn't matter because memory will be reclaimed by the O/S when the process exits. Similarly, in theory I'd expect an API call to release message.I don't see why you need the
(LPSTR) cast. Using a cast can hide compiler warnings/errors, which should be fixed instead of their causing errors at run-time.Instead of
int idx; it's better to not define a local variable until the moment at which you initialize it: instead you could say, for (int idx = 1; idx < argc; idx++).Also, shouldn't it be
for (int idx = 2; idx < argc; idx++)? Because, idx=1 is the 'command' parameter, not the first 'argument' parameter.If when you say "C/C++" you mean "C++", then it's more conventional these days to use
std::string instead of C-style strings (but this is an unusually short program; perhaps although I don't know why you want to avoid the hassle of linking to the STL, especially if you know enough to avoid the many pitfalls of C-style string manipulation, which you seem to have).For example, using
std::string you could write the following, which is simpler than the string-manipulation code you have at the moment:std::string s;
for (int idx = 1; idx < argc; idx++)
{
s += "\"" + argv[idx] + "\"";
if (idx < argc - 1) {
s += " ";
}
}
char* arguments = strdup(s.c_str());The reason for
strdup in the above is that MSDN says ...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.
... which helps to explain why arguments must be
char not const char. Sometimes you can ignore these (the windows API sometimes doesn't say its parameters are const when in fact they are), but doing so may be unsafe bad practice (so I use strdup above -- note that strdup'ed memory should be free'ed).Code Snippets
std::string s;
for (int idx = 1; idx < argc; idx++)
{
s += "\"" + argv[idx] + "\"";
if (idx < argc - 1) {
s += " ";
}
}
char* arguments = strdup(s.c_str());Context
StackExchange Code Review Q#38793, answer score: 3
Revisions (0)
No revisions yet.