Different behaviour with console

Windows specific questions.
Post Reply
marpon
Posts: 342
Joined: Dec 28, 2012 13:31
Location: Paris - France

Different behaviour with console

Post by marpon »

here you have a test to evaluate the different behaviour we can have with console.

Code: Select all

''	test_console.bas    by marpon  14 March 2019

' to test the 4 possible usages of console
'
'	1	compiled in console mode and launched by console prompt, so using the existing launching console
'	2	compiled in console mode and not lauched by console prompt, so use the own console
'	3	compiled in GUI mode and launched by console prompt, so using the existing launching console ( the sleep is not completly solved, and the restore mode not easy)
'	4	compiled in GUI mode and not launched by console prompt, so use a new created own console



 'what is interresting is the GUI compilation,  the prog will work normally without the console in the side
 '		but if a problem occurs it is possible to track it via console.


#include once "windows.bi"
#Include Once "win/psapi.bi"                     ' for process
#include once "win/tlhelp32.bi"                  ' for process
#include once "crt/stdio.bi"                 	 ' for printf


function GetWindowsFromProcessID(byval dwProcessID as DWORD, byref wclass as string = "") as HWND
    ' find all hWnds (vhWnds) associated with a process id (dwProcessID)
    dim as HWND hCurWnd = NULL
	dim as dword dwtemp
	dim as zstring ptr pwclass = strptr(wclass) 
    do
        hCurWnd = FindWindowEx(NULL, hCurWnd, pwclass, NULL)
        dwtemp = 0
        GetWindowThreadProcessId(hCurWnd, @dwtemp)
        if (dwtemp = dwProcessID) then return hCurWnd
    loop while (hCurWnd <> NULL)
	return NULL
end function

function  getParentPID(byval pid as DWORD) as DWORD
    dim as HANDLE h = NULL
    dim as PROCESSENTRY32 pe
    dim as DWORD ppid
    pe.dwSize = sizeof(PROCESSENTRY32)
    h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
    if Process32First(h, @pe)<> 0 then
        do
            if pe.th32ProcessID = pid then
                ppid = pe.th32ParentProcessID
                exit do
            end if
        loop while( Process32Next(h, @pe)<> 0)
    end if
    CloseHandle(h)
    return (ppid)
end function



function in_console(byval iset as long, byref stitle as string) as long
	static s__console as long											'warning a static var here to track AllocConsole()
	dim hwincons as handle
	if iset = 1 and s__console = 0 THEN
		hwincons = GetConsoleWindow()
		if hwincons = 0 THEN
			AllocConsole()
			AttachConsole(GetCurrentProcessId())
			freopen( "CON", "r", stdin )
			freopen( "CON", "w", stdout )
			freopen( "CON", "w", stderr )
			hwincons = GetConsoleWindow()
			sleep 50
			if hwincons <> 0  THEN
				SetConsoleTitle(stitle)
				printf(!"\n\n\t==>  AllocConsole mode!\n\n")
				s__console = 1
				return 1
			else
				FreeConsole()
				return 0
			end if
		else
			return 2
		END IF
	elseif iset = 0 and s__console = 1 THEN
		FreeConsole()
		s__console = 0
		return 0
	END IF
	return 0
END function


sub restore_true_console(byval ppid as DWORD)
	dim as hwnd h1 = GetWindowsFromProcessID(ppid, "ConsoleWindowClass")
	 /' print "pid = " & ppid & "   hwnd = " & h1 '/ 
	if h1 THEN
		fflush(STDIN)
		fflush(STDOUT)
		fflush(STDERR)	
		freeconsole()
		PostMessage(h1, WM_KEYDOWN, VK_RETURN, 0) 'to restore the normal prompt in cmd console
		'PostMessage(h1, WM_KEYUP, VK_RETURN, 0)
	 /' else
		Keybd_event VK_RETURN , 0 , 0 , 0
		'Keybd_event VK_RETURN , 0 , KEYEVENTF_KEYUP , 0 '/ 
    END IF
	
END SUB


function check_cmd()as long
	dim as DWORD darr(10)
	dim as DWORD dcons = GetConsoleProcessList( @darr(0), 10)
	return (cast(long,dcons))-1
END FUNCTION


dim as long cons_type = check_cmd()
if cons_type < 0 THEN									'GUI mode
	messagebox 0, "No console yet", "info", 0
	dim as dword ppid = getParentPID(GetCurrentProcessId())
	if  ppid > 0  THEN
		fflush(STDIN)
		fflush(STDOUT)
		fflush(STDERR)
		AttachConsole(ppid)
		if GetConsoleWindow() THEN						'GUI mode :launched via prompt cmd
			freopen( "CON", "r", stdin )
			freopen( "CON", "w", stdout )
			freopen( "CON", "w", stderr )
			printf(!"\n\nGUI : Using the existing launching console\n")
			sleep 200
			printf(!"\ndoing someting here!\n")  'warning in that mode it is not possible to have easy interruption for sleep : have to be checked...
			sleep 400
			printf(!"\nLeaving now!\n")
			restore_true_console(ppid)
		else											'GUI mode :launched without prompt cmd
			if in_console(1, "New console for GUI") then
				printf (!"GUI : Created new console, wait 4s  or press any key to stop\n")
				sleep 4000
			else
				messagebox 0, "No console at all", "info", 0
			end if
        END IF
	else
		messagebox 0, "Still No console", "info", 0
    END IF
elseif cons_type = 0 THEN								'console mode :launched without prompt cmd
	printf !"\nIn 'real' console mode using own console, wait 4s  or press any key to stop " : print
	sleep 4000
else													'console mode :launched via prompt cmd
	printf !"\nIn 'real' console mode using the existing launching console, wait 4s  or press any key to stop " : print
	sleep 4000
END IF


compile with or without console mode, you will see 4 differents ways to always have a console when needed

that is very interresting if you want to track some events , debugg mode, error catching...
it is also helpful if you make libs or dlls, you can incorporate the console code on them to be sure you will always give a console,
even the global prog will be compiled on GUI mode.

as always do not hesitate to test and send your remarks...

by the way, give also some interresting functions you could have some use for.
Post Reply