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;
}
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
> [...]
> 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
Don't use wget. Never use external app
Use API instead (1 line of code...)
(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
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
> 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
> 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:
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
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
> 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
>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
****
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
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
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
> See http://www.catb.org/~esr/jargon/
>
> a useful file of words you will NOT find in the usual dictionaries!
Thanks!
Giovanni