Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

CreateProcess SW_HIDE not working

1,572 views
Skip to first unread message

Bob

unread,
Dec 1, 2008, 7:32:05 PM12/1/08
to
Ive been reading many many other articles on this issue and playing
with variations of
my code to get it working and cannot seem to get it to work. I have a
thread that is launched
withing a MFC GUI application which Im trying to silently do work in.
Im using wget.exe which
works fine. In fact all the code works great except the stupid window
keeps popping up everytime
it launches my wget. I even tried to reduce the size of the window to
1 x 1 pixels and that
doesnt even work!

Can someone tell me why? Ive looked at the microsoft pages on article
Q150956 and anything
else I could see with no luck.

I appreciate it!

Relevant code here:

DWORD WINAPI myThreadFunc(LPVOID lpParam )
{
char cmd[255];
char ipfile[255];
char buf[25];
BOOL m_run = true;

while (m_run)
{
sprintf(ipfile, "C:\\bin\\myip.txt");
sprintf(cmd, "C:\\bin\\wget -q -nv http://10.10.10.1/cgi-bin/getip.cgi
-O %s", ipfile);

STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
//GetStartupInfo(&si);
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESIZE;
si.wShowWindow = SW_HIDE;
si.dwXSize = 1;
si.dwYSize = 1;

si.cb = sizeof(si); // Must set the size of structure
PROCESS_INFORMATION pi;
BOOL ret = CreateProcess(NULL, cmd, NULL, NULL, FALSE,
CREATE_NO_WINDOW, // | DETACHED_PROCESS,
NULL, NULL, &si, &pi);
if (ret)
{
WaitForSingleObject(pi.hProcess, 1000 * 2); // wait 2 seconds
CloseHandle(pi.hProcess);
}
Sleep(1000 * 5);
}
return 0;
}

David Ching

unread,
Dec 1, 2008, 8:24:46 PM12/1/08
to
"Bob" <je...@rahul.net> wrote in message
news:c40c9da3-125c-415d...@u18g2000pro.googlegroups.com...

> Ive been reading many many other articles on this issue and playing
> with variations of
> my code to get it working and cannot seem to get it to work. I have a
> thread that is launched
> withing a MFC GUI application which Im trying to silently do work in.
> Im using wget.exe which
> works fine. In fact all the code works great except the stupid window
> keeps popping up everytime
> it launches my wget. I even tried to reduce the size of the window to
> 1 x 1 pixels and that
> doesnt even work!
>
> Can someone tell me why? Ive looked at the microsoft pages on article
> Q150956 and anything
> else I could see with no luck.
>
> I appreciate it!
>
> Relevant code here:
> ...

> si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESIZE;
> si.wShowWindow = SW_HIDE;


The SW_ parameter above is passed to WinMain() ast the last parameter,
nCmdShow. Perhaps your wget.exe is ignoring this parameter?

In MFC apps, I think MFC will process it for you, but only if you create an
SDI/MDI app (the handling is done when creating the doc template, which is
not done when your app is a dialog-based app). For example, in your
CWinApp::InitInstance(), you do a DoModal() of your dialog which completely
ignores the parameter.

So fault may be in wget.exe.

-- David

Giovanni Dicanio

unread,
Dec 2, 2008, 3:35:50 AM12/2/08
to

"David Ching" <d...@remove-this.dcsoft.com> ha scritto nel messaggio
news:89918D3E-6677-4DD4...@microsoft.com...

> [...]


> So fault may be in wget.exe.

I agree with David's analysis.

Moreover, it seems to me that wget is a GNU app, it is free software so the
source code can be modified for your own needs (including starting
minimized, correctly processing nCmdShow parameter, or other):

http://www.gnu.org/software/wget/

Giovanni


Loic

unread,
Dec 2, 2008, 8:46:29 AM12/2/08
to
Bob wrote:
> Ive been reading many many other articles on this issue and playing
> with variations of
> my code to get it working and cannot seem to get it to work. I have a
> thread that is launched
> withing a MFC GUI application which Im trying to silently do work in.
> Im using wget.exe which
> works fine.

Don't use wget. Never use external app
Use API instead (1 line of code...)

Joseph M. Newcomer

unread,
Dec 2, 2008, 10:03:41 AM12/2/08
to
I was confused because the OP said "launch a thread", instead of "launch a process". It
is a common failure mode of people who learned in Unix that you have to run programs to do
trivial things, because the Unix API sucks so badly. So they don't even bother to look
for APIs to do the job; the natural reaction is "run a child process". Horribly
inefficient, no way to return meaningful error codes to the caller, etc. but it is the
only hammer they have, so all their problems look like nails.

(Of course, they tend to not even name the program, or assume that everyone in the world
knows, for example, what 'wget.exe' actually does). I assumed that this was an attempt to
spawn a thread within a program called wget.exe, rather than spawn a process that uses it.
Of course, no example of the CreateProcess code is shown, making it hard to analyze the
problem, also.
joe

Joseph M. Newcomer [MVP]
email: newc...@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm

Bob

unread,
Dec 3, 2008, 10:30:19 AM12/3/08
to

> Of course, no example of the CreateProcess code is shown, making it hard to analyze the
> problem, also.
>                                         joe

The relevant code portion was posted, I guess you missed it. Someone
else
suggested that if Im using wget I should redirect the stdout, stderr,
stdin and it
will fix that issue...

> >Don't use wget. Never use external app
> >Use API instead (1 line of code...)
>

Id rather find out what the equivalent API is to do the same job?

Thanks

David Ching

unread,
Dec 3, 2008, 12:56:27 PM12/3/08
to
"Bob" <je...@rahul.net> wrote in message
news:031a3d3d-c7ba-4bc1...@t39g2000prh.googlegroups.com...

> The relevant code portion was posted, I guess you missed it. Someone
> else
> suggested that if Im using wget I should redirect the stdout, stderr,
> stdin and it
> will fix that issue...

Is wget a command-liine app? IF so, it should honor the SW_HIDE! I've
specified this in CreateProcess() many times for command-line apps, and it
works fine. It's only if wget is a GUI app with a WinMain() that SW_HIDE
may not work.

-- David

Giovanni Dicanio

unread,
Dec 3, 2008, 2:22:12 PM12/3/08
to

"David Ching" <d...@remove-this.dcsoft.com> ha scritto nel messaggio
news:00CCA6C4-0C01-4849...@microsoft.com...

> Is wget a command-liine app?

It seems so to me.

> IF so, it should honor the SW_HIDE! I've specified this in
> CreateProcess() many times for command-line apps, and it works fine.

I read in the file 'mswindows.c' of wget 1.11.4 downloaded from here:

http://ftp.gnu.org/gnu/wget/

the following code:

<code>

/* Windows doesn't support the fork() call; so we fake it by invoking
another copy of Wget with the same arguments with which we were
invoked. The child copy of Wget should perform the same initialization
sequence as the parent; so we should have two processes that are
essentially identical. We create a specially named section object that
allows the child to distinguish itself from the parent and is used to
exchange information between the two processes. We use an event object
for synchronization. */
static void
fake_fork (void)
...
STARTUPINFO si;
...
/* Create the child process detached form the current console and in a
suspended state. */
xzero (si);
si.cb = sizeof (si);
rv = CreateProcess (exe, GetCommandLine (), NULL, NULL, TRUE,
CREATE_SUSPENDED | DETACHED_PROCESS,
NULL, NULL, &si, &pi);
if (!rv)
goto cleanup;
...

</code>

So it seems that wget calls CreateProcess on itself, too, and this time
minimization/hidden option is not passed.

This wget code seems kind of convoluted to me and I don't have time to
investigate deeper, but I would suggest the OP to use the debugger to step
in code (possibly putting a breakpoint there) and see if the above
CreateProcess statement is called.
If so, I think that that code should be modified such that the proper
minimization/hidden flag should be used (e.g. setting proper field in the
'STARTUPINFO si' variable)

Moreover, I wonder what is the one-line-of-code Windows-only API to
substitute wget :)

Giovanni

David Ching

unread,
Dec 3, 2008, 3:00:58 PM12/3/08
to
"Giovanni Dicanio" <giovanniD...@REMOVEMEgmail.com> wrote in message
news:OraUXyXV...@TK2MSFTNGP05.phx.gbl...

>
> So it seems that wget calls CreateProcess on itself, too, and this time
> minimization/hidden option is not passed.
> ...

> Moreover, I wonder what is the one-line-of-code Windows-only API to
> substitute wget :)
>

Ah, so! :-) You have solved the mystery (of why SW_HIDE does not work).
This is a typical example of Open Source, it simply fails to be usable! ;)

I don't think even high level languages like .NET or Python have one line of
code to do this! :-O

-- David

Giovanni Dicanio

unread,
Dec 3, 2008, 3:07:39 PM12/3/08
to

"David Ching" <d...@remove-this.dcsoft.com> ha scritto nel messaggio
news:OhwMiHYV...@TK2MSFTNGP02.phx.gbl...

> Ah, so! :-) You have solved the mystery (of why SW_HIDE does not work).
> This is a typical example of Open Source, it simply fails to be usable!
> ;)
>
> I don't think even high level languages like .NET or Python have one line
> of code to do this! :-O

:-))

G


Joseph M. Newcomer

unread,
Dec 3, 2008, 3:57:14 PM12/3/08
to
Sorry I missed seeing this code...

On Mon, 1 Dec 2008 16:32:05 -0800 (PST), Bob <je...@rahul.net> wrote:

>Ive been reading many many other articles on this issue and playing
>with variations of
>my code to get it working and cannot seem to get it to work. I have a
>thread that is launched
>withing a MFC GUI application which Im trying to silently do work in.
>Im using wget.exe which
>works fine. In fact all the code works great except the stupid window
>keeps popping up everytime
>it launches my wget. I even tried to reduce the size of the window to
>1 x 1 pixels and that
>doesnt even work!
>
>Can someone tell me why? Ive looked at the microsoft pages on article
>Q150956 and anything
>else I could see with no luck.
>
>I appreciate it!
>
>Relevant code here:
>
>DWORD WINAPI myThreadFunc(LPVOID lpParam )
>{
> char cmd[255];
> char ipfile[255];
> char buf[25];
> BOOL m_run = true;
>
> while (m_run)
> {
> sprintf(ipfile, "C:\\bin\\myip.txt");

****
Why sprintf? THere are so many things wrong with this one statement it is mind-boggling!

First, why 'char' as the datatype. 'char' is dead. It should not be used in ordinary
programs. There is no bounds checking to see that the buffer is not overrun, just trust
that the string is short enough. There is a presumption that the file is located on a
specific drive, in a specific directory. The buffer into which it is written has the
random number 255 as its limit, instead of _MAX_PATH, which is the longest path possible.
Note that _MAX_PATH is *not* 255, it is LONGER and therefore a buffer overrun can occur.

Note that this could all have been solved by
LPTSTR ipfile = _T("c:\\bin\myip.txt:);
which suffers from the problem of binding to a specific drive and directory, but
eliminates all other problems.

Or, in a sane world,
CString ipfile(_T("c:\\bin\myip.txt"));

since there is no reason to use fixed-size char buffers in modern programming. If you
don't like CString, use std::string. But generally forget that fixed-size buffers exist.
****
****


> sprintf(cmd, "C:\\bin\\wget -q -nv http://10.10.10.1/cgi-bin/getip.cgi
>-O %s", ipfile);

*****
CString cmd;
cmd.Fomat(_T("c:\\bin\wget -q -nv http://10.10.10.1/cgi-bin/getip.cgi -O %s"),
ipfile);

Note there is no possibility of buffer overrun here because there is no preallocated
buffer. The buffer here should be AT LEAST 2*_MAX_PATH but why bother when you don't need
to pre-allocate at all!

Now this assumes a specific IP address. It runs some kind of script with some option.
This presumably is going to write a file somewhere on the host machine's disk drive. What
good is this going to do? Why not just retrieve the data you want using HTTP? It doesn't
take that much effort to write this code (I've done it several times, and it is a small
number of lines of code, even though I have to look them up every time).

What I'm curious about is why a hardwired file name in what should nominally be a
write-protected directory of executables is being used. Generally, you should be using
GetTempName to generate a guaranteed-unique name, and it should written in the GetTempPath
directory, not into critical system directories. In any sane installation, the bin
directories are all read-only to protect against virus infestation.
****


>
> STARTUPINFO si;
> ZeroMemory(&si, sizeof(si));
> //GetStartupInfo(&si);
> si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESIZE;

****
As pointed out, only if your app honors the wShowWIndow option will it have any effect.
But wget.exe appears to be a non-GUI program, so this flag only applies to GUI programs.

You would want to reroute stdout and use the option that said to not display a console
window.
****


> si.wShowWindow = SW_HIDE;
> si.dwXSize = 1;
> si.dwYSize = 1;
>
> si.cb = sizeof(si); // Must set the size of structure
> PROCESS_INFORMATION pi;
> BOOL ret = CreateProcess(NULL, cmd, NULL, NULL, FALSE,
> CREATE_NO_WINDOW, // | DETACHED_PROCESS,
> NULL, NULL, &si, &pi);
> if (ret)
> {
> WaitForSingleObject(pi.hProcess, 1000 * 2); // wait 2 seconds

****
Any time a line like this appears, you can assume the design is flawed beyond redemption.
Why do you think that 2 seconds means anything whatsoever? If the process hasn't
finished, you're going to wait another 5 seconds for some inexplicable reason anyway. What
is going on here? Either it is going to terminate, in which case you want INFINITE, or it
is going to hang, in which case, just closing the handle, crossing your fingers, and
hoping is somewhat misplaced.
****


> CloseHandle(pi.hProcess);
> }
> Sleep(1000 * 5);
> }
> return 0;

****
You are spending more effort to set up a bad solution than it would take to write a good
solution. If you want the page contents (yes, I looked up wget), just read them using the
HTTP APIs.
joe
****

Joseph M. Newcomer

unread,
Dec 3, 2008, 3:58:49 PM12/3/08
to
Typical piece of Unix crud and cruft. I spent 15 years hating code that suffered from the
poor Unix API, and this is one of the many reasons I try to avoid "free" software.
joe

Giovanni Dicanio

unread,
Dec 3, 2008, 5:31:24 PM12/3/08
to

"Joseph M. Newcomer" <newc...@flounder.com> ha scritto nel messaggio
news:omsdj45kba78b3cst...@4ax.com...

> Typical piece of Unix crud and cruft. I spent 15 years hating code that
> suffered from the
> poor Unix API, and this is one of the many reasons I try to avoid "free"
> software.

I don't know what "crud and cruft" precisely means, but it seems not a
compliment ;-)

BTW: I don't envy you for working 15 years on that kind of code! It must
have been very hard and tough.

However, I think that there are also quality open-source codes available
(for example, wxWidgets, or QT as David pointed out recently, etc.).

Giovanni

David Ching

unread,
Dec 3, 2008, 9:40:31 PM12/3/08
to
"Giovanni Dicanio" <giovanniD...@REMOVEMEgmail.com> wrote in message
news:Og%23eCcZV...@TK2MSFTNGP02.phx.gbl...

>
> However, I think that there are also quality open-source codes available
> (for example, wxWidgets, or QT as David pointed out recently, etc.).
>

It seems to me, the quality open source code is either 1) those that have
commercial versions also available (e.g. Qt), or 2) those that are not cross
platform (e.g. NSIS).

Strictly free, cross platform code can cause a lot of pain to deploy.

-- David

Joseph M. Newcomer

unread,
Dec 3, 2008, 11:24:36 PM12/3/08
to
Go find an old water pipe, most likely a drain pipe under a sink. Look at the goop lining
the pipe. The word "crud" is a pretty good description of what you find.

From "The New Hacker's Dictionary" third edition:

crudware: pejorative term for the hundreds of megabytes of low-quality freeware circulated
by user's groups and BBS systems in the micro-hobbyist world.

cruft: An unpleasant substance. The dust that gathers under your bed is cruft. The TMRC
[Tech Model Railroad Club] dictionary correctly noted that attacking it with a broom
creates only more. 2. The result of shoddy construction. 3. [from "hand cruft", a pun on
"hand craft"] To write assembler code for something normally (and better) done by a
compiler. 4. Excess, superfluous junk, used esp. of redundant or superseded code.

cruftsmanship: the antithesis of craftsmanship.

See http://www.catb.org/~esr/jargon/

a useful file of words you will NOT find in the usual dictionaries!
joe

Giovanni Dicanio

unread,
Dec 4, 2008, 4:16:01 AM12/4/08
to

"Joseph M. Newcomer" <newc...@flounder.com> ha scritto nel messaggio
news:i7mej4h7bh23c7h3o...@4ax.com...

> See http://www.catb.org/~esr/jargon/
>
> a useful file of words you will NOT find in the usual dictionaries!

Thanks!

Giovanni

0 new messages