- Win32 Console Applications
- Posted by Fenster on March 22nd, 2005
Does anyone know if there is any way that an application can tell
whether it was started from a command line from within an existing
command console or by a double click of the executable from Explorer?
Thanks.
--
Fenster
- Posted by Sten Westerback on March 22nd, 2005
"Fenster" <fenster@croctec.co.uk> wrote in message
news:7HI6OKAbBEQCFwVg@FensterPC.croctec.co.uk...
All processes are started by the same subsystem (assuming Win32 apps).
So not unless the command line has some switch or execute the EXE from
different paths in the different cases and then get the path to the running
application.
Why do you need to know that?
- Sten
- Posted by James Brown on March 22nd, 2005
No way other than checking the parent-process
(which may not still exist when you do this check), and
seeing if that parent process is cmd.exe / explorer.exe...
or check if its a console/windows app..
there's no sure-fire way of doing it anyway.
James
--
www.catch22.net
Free win32 software, sourcecode and tutorials
"Fenster" <fenster@croctec.co.uk> wrote in message
news:7HI6OKAbBEQCFwVg@FensterPC.croctec.co.uk...
- Posted by Severian on March 22nd, 2005
On Tue, 22 Mar 2005 15:55:34 +0000 (UTC), Fenster
<fenster@croctec.co.uk> wrote:
The code below (GetParentProcessId) will find the parent process ID. I
didn't try to make it pretty because I was learning WMI and in a
hurry. It's not failsafe but should work under most situations. I
don't know about Windows version compatibility.
If the parent process still exists, you can check if it is a console
app; one way to do that would be to get its name:
....
TCHAR imgpath[_MAX_PATH];
HANDLE hproc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE,
GetParentProcessId());
# if (_WIN32_WINNT >= 0x0500)
if (hproc)
GetProcessImageFileName(hproc, imgpath, sizeof imgpath);
# endif
OutString(hdc, L"Parent process: %lu %s",
GetParentProcessId(), imgpath);
....
// GetParentProcessId()
#include <windows.h>
#include <tchar.h>
#include <wbemcli.h>
static DWORD ReportError(LPCTSTR errmsg)
{
MessageBox(NULL, errmsg, L"Failure", MB_OK|MB_ICONHAND);
return 0;
}
extern "C" DWORD GetParentProcessId(void)
{
DWORD parent_id = 0;
IWbemLocator *ploc = NULL;
IWbemServices *psvc = NULL;
IEnumWbemClassObject *penu = NULL;
IWbemClassObject *pobj = NULL;
VARIANT var;
TCHAR query[1000];
ULONG uret;
if (FAILED(CoInitializeEx(0, COINIT_MULTITHREADED)))
return ReportError(L"Unable to initialize COM");
if (FAILED(CoCreateInstance(CLSID_WbemLocator, 0,
CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *)&ploc)))
return ReportError(L"Unable to initialize WMI");
if (FAILED(CoInitializeSecurity(NULL, -1, NULL, NULL,
RPC_C_AUTHN_LEVEL_DEFAULT,
RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0)))
return ReportError(L"Unable to set security for WMI");
if (FAILED(ploc->ConnectServer(L"root\\cimv2",
NULL, NULL, NULL, 0, NULL, NULL, &psvc))) {
ploc->Release();
return ReportError(L"Unable to connect to WMI server");
}
if (FAILED(CoSetProxyBlanket((IUnknown *)psvc, RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL,
RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE))) {
psvc->Release();
ploc->Release();
return ReportError(L"Unable to set proxy blanket");
}
_stprintf(query, L"SELECT * FROM WIN32_Process WHERE ProcessId=%d",
GetCurrentProcessId());
if (FAILED(psvc->ExecQuery(L"WQL", query,
WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY,
NULL, &penu))) {
psvc->Release();
ploc->Release();
return ReportError(L"Unable to locate process");
}
if (FAILED(penu->Next(WBEM_INFINITE, 1, &pobj, &uret))) {
penu->Release();
psvc->Release();
ploc->Release();
return ReportError(L"Unable to retrieve process object");
}
if (!FAILED(pobj->Get(L"ParentProcessId", 0, &var, NULL, NULL)))
parent_id = var.ulVal;
pobj->Release();
penu->Release();
psvc->Release();
ploc->Release();
CoUninitialize();
return parent_id;
}
--
Sev
- Posted by Fenster on March 23rd, 2005
In message <7cZ%d.41268$k4.806170@news1.nokia.com>, Sten Westerback
<sten.westerback@NO_SPAMnokia.com> writes
I have console app that runs fine in a console but if I forget to do
that and double-click the .exe instead it disappears, along with the
results it's just generated and displayed, as soon as it finishes.
If I run from inside the Visual C++ IDE it displays a "press key to
continue" type message after it stops, giving me time to check the
results before they disappear.
It's a relatively minor problem/grumble but I thought it be nice if it
could be done and it would help keep my stress levels down for when I
forget run the app in a console window.
When setting shortcut properties in the old days there used to be a
checkbox to close window on exit but that seems to have gone as far as I
can see. I'm running Windows 2000 if that makes a difference.
Thanks.
--
Fenster
- Posted by Fenster on March 23rd, 2005
In message <42407317$0$26749$cc9e4d1f@news.dial.pipex.com>, James Brown
<remove_james_dot_brown7_at_virgin_dot_net@?.?.inv alid> writes
How do I check if it's a console/windows app?
--
Fenster
- Posted by Alex Blekhman on March 23rd, 2005
Fenster wrote:
If it's all that you want, then here's simplest solution:
puts("Press <Enter> key to exit.");
getchar();
MSVC IDE patches console window in similar way for your convenience.
- Posted by James Brown on March 23rd, 2005
One way:
Find the Pid of parent (Toolhelp / ZwQueryProcessInformation)
OpenProcess
GetModuleFileNameEx (to get the path)
CreateFile
ReadFile - read PE header and look at options in the
header to see if its console/gui/posix etc.
CloseHandle/ cleanup etc.
Personally I would try to find another way to solve
your problem..
James
--
www.catch22.net
Free win32 software, sourcecode and tutorials
"Fenster" <fenster@croctec.co.uk> wrote in message
news:6yVqTpAtIRQCFwmT@FensterPC.croctec.co.uk...
- Posted by James Brown on March 23rd, 2005
"Fenster" <fenster@croctec.co.uk> wrote in message
news:7yEqDRApHRQCFwGQ@FensterPC.croctec.co.uk...
When you execute (not debug) a program via the VS IDE, it
spawns a child process (vcspawn.exe) ...which then spawns a
further child process (yourapp.exe) - so vcspawn.exe acts as a
"wrapper" around your program (but only when your program is
a console-application). when your console-exe closes, vcspawn.exe
displays the "press any key to continue" and waits for a key-press.
A much better way to solve your problem (imho):
When your console-application starts via explorer, a new console
window is created by the win32 subsystem. Your program is the
owner of this console window - and you are at the "root" of the
console chain - so when your app exits, the console will close.
If you are started via another console program (i.e. cmd.exe
or vcspawn.exe) then your program will be attached to its console,
but you will *not* own that console window. So you can do a check
when your program exits - if your process owns the console window, then you
need to display a "press any key" message. If someone else owns the
window, then you are a "child" console process and you can assume
that the parent process will do this for you:
void DisplayExitMessage()
{
DWORD pid = 0;
HWND hwndConsole;
// note, need Win2k and new Platform SDK for this API.
// use FindWindow if earlier windows
hwndConsole = GetConsoleWindow();
GetWindowThreadProcessId(hwndConsole, &pid);
if(pid != 0 && pid == GetCurrentProcessId())
{
printf("Press any key to exit");
getchar();
}
}
Hope this helps,
James
--
www.catch22.net
Free win32 software, sourcecode and tutorials
- Posted by Gordon Smith on March 23rd, 2005
In article <3aclk3F661e95U1@individual.net>, Alex Blekhman
<tkfx^N05P4M^@yahoo.com> writes
Thanks but I've already got that and it's fine but it's an unnecessary
bit of user interaction if the application is being run in a console
window.
--
Fenster
- Posted by Gordon Smith on March 23rd, 2005
In article <42412876$0$26745$cc9e4d1f@news.dial.pipex.com>, James Brown
<remove_james_dot_brown7_at_virgin_dot_net@?.?.inv alid> writes
I'll try it tomorrow, thanks.
--
Fenster
- Posted by Fenster on March 24th, 2005
In message <+dZsd2AaifQCFwEe@gordys.demon.co.uk>, Gordon Smith
<gordon@NoSpam.Please.co.uk> writes
I had to declare _WIN32_WINNT myself, which I wouldn't have thought I'd
have to do, but otherwise it works a treat. Thanks very much.
--
Fenster
- Posted by Mike Weller on March 26th, 2005
Fenster wrote:
MS has an article that might help you... there is no best way but you
can see a method here:
http://support.microsoft.com/default...kb;en-us;99115
Also see
http://www.we11er.co.uk/programming/...p.html#Pausing
- Posted by Scott Moore on March 28th, 2005
Fenster wrote:
The problem is backwards. Command line procedures aren't supposed to
know about Windows, they may have been written before Windows existed.
Explorer just throws them into a window, then closes that when they
terminate, which, IMHO, is bad behavior. Explorer SHOULD check if it
is launching a console executable, vs. a full windowed executable,
and hold the console if so. The console mode is a single code in the
programs PE (portable executable) header, and its actual purpose
in Windows NT/XP is to cause a console launcher like the command
executive to wait until the task finishes. If you launch a graphic/
windowed program from the command line WITH the console mode selected,
what you get is a graphical windowed program, running in its own
window, but that causes the original command line launcher to hold
until the program is finished. Also, any inputs and outputs to the
standard in and out will end up back in the original window.
Anyways, explorer can and should:
1. Check if it is launching a console mode program.
2. Create a console for the program to run in (attached to).
3. Exec the program and HOLD until the termination of the program
(or execute a subtask that holds for the program).
4. Set the title of the console to be "program xx -- terminated".
5. Wait until the user terminates the window.
Unconsidered here is the case of a console mode program that was
designed to be self terminating, ie., runs its own screen surface
and exit dialog.
Of course, we don't have access to explorer code. However, theres
two ways to skin that cat. First, (and IMHO preferable) write
a non-braindamaged explorer with console automatic hold as a
settable option, sell that and make some money for yourself.
Second, explorer is only connecting the .exe extention to a standard
suffix handler, which is the execute handler. It should be possible
to redefine .exe suffix handling to a wrapper that performs the
above actions.
- Posted by Fenster on March 29th, 2005
In message <d24ceb$k54$3@wisteria.csv.warwick.ac.uk>, Mike Weller
<spam@we11er.co.uk> writes
Thanks.
The "cmd.exe /k" method looks good if the application is started from a
shortcut but I'm not sure to implement it otherwise.
The check cursor position is 0,0 also seems seriously flawed to me. For
example, I have a console application that moves the cursor based on
ANSI sequences that come in over the serial port.
--
Fenster