Modify

Opened 21 months ago

Last modified 18 months ago

#3970 new Feature Request

Macro @IsConsole

Reported by: Alecsis1 Owned by:
Milestone: Component: AutoIt
Version: Severity: None
Keywords: Cc:

Description

Hi all!
Sometimes there's need to distinguish, is a script compiled as Console or
GUI Application. For example, having compiled our script as GUI app we won't see any output from ConsoleWrite/ConsoleWriteError, so we should use MsgBox or smth other way.
Thus such macro I'd like to offer could be rather useful.
Thank you for attention!

Change History (4)

comment:1 Changed 21 months ago by TicketCleanup

  • Version 3.3.14.0 deleted

Automatic ticket cleanup.

comment:2 Changed 18 months ago by Andreik

Now we need macros for everything. This can be achieved easily without any macro.

If IsConsole() Then
	ConsoleWrite('Yayyy! I am a console application.' & @CRLF)
Else
	MsgBox(0, 'Yayyy!', 'I am a GUI application.')
EndIf

Func IsConsole()
	If Not @Compiled Then Return SetError(1, 0, Null)

	Local $IMAGE_SUBSYSTEM_WINDOWS_CUI = 3

	Local $tagIMAGE_DOS_HEADER =	'WORD e_magic; WORD e_cblp; WORD e_cp; WORD e_crlc; WORD e_cparhdr; ' & _
	'WORD e_minalloc; WORD e_maxalloc; WORD e_ss; WORD e_sp; WORD e_csum; WORD e_ip; WORD e_cs; ' & _
	'WORD e_lfarlc; WORD e_ovno; WORD e_res[4]; WORD e_oemid; WORD e_oeminfo; WORD e_res2[10]; LONG e_lfanew;'

	Local $tagIMAGE_FILE_HEADER = 'WORD Machine; WORD NumberOfSections; DWORD TimeDateStamp; ' & _
	'DWORD PointerToSymbolTable; DWORD NumberOfSymbols; WORD SizeOfOptionalHeader; WORD Characteristics;'

	If @AutoItX64 Then
		Local $tagIMAGE_OPTIONAL_HEADER = 'WORD Magic; BYTE MajorLinkerVersion; BYTE MinorLinkerVersion; ' & _
		'DWORD SizeOfCode; DWORD SizeOfInitializedData; DWORD SizeOfUninitializedData; DWORD AddressOfEntryPoint; ' & _
		'DWORD BaseOfCode; PTR ImageBase; DWORD SectionAlignment; DWORD FileAlignment; ' & _
		'WORD MajorOperatingSystemVersion; WORD MinorOperatingSystemVersion; WORD MajorImageVersion; ' & _
		'WORD MinorImageVersion; WORD MajorSubsystemVersion; WORD MinorSubsystemVersion; ' & _
		'DWORD Win32VersionValue; DWORD SizeOfImage; DWORD SizeOfHeaders; DWORD CheckSum; ' & _
		'WORD Subsystem; WORD DllCharacteristics; PTR SizeOfStackReserve; PTR SizeOfStackCommit; ' & _
		'PTR SizeOfHeapReserve; PTR SizeOfHeapCommit; DWORD LoaderFlags; DWORD NumberOfRvaAndSizes;'
	Else
		Local $tagIMAGE_OPTIONAL_HEADER = 'WORD Magic; BYTE MajorLinkerVersion; BYTE MinorLinkerVersion; ' & _
		'DWORD SizeOfCode; DWORD SizeOfInitializedData; DWORD SizeOfUninitializedData; DWORD AddressOfEntryPoint; ' & _
		'DWORD BaseOfCode; DWORD BaseOfData; PTR ImageBase; DWORD SectionAlignment; DWORD FileAlignment; ' & _
		'WORD MajorOperatingSystemVersion; WORD MinorOperatingSystemVersion; WORD MajorImageVersion; ' & _
		'WORD MinorImageVersion; WORD MajorSubsystemVersion; WORD MinorSubsystemVersion; ' & _
		'DWORD Win32VersionValue; DWORD SizeOfImage; DWORD SizeOfHeaders; DWORD CheckSum; ' & _
		'WORD Subsystem; WORD DllCharacteristics; PTR SizeOfStackReserve; PTR SizeOfStackCommit; ' & _
		'PTR SizeOfHeapReserve; PTR SizeOfHeapCommit; DWORD LoaderFlags; DWORD NumberOfRvaAndSizes;'
	EndIf

	Local $tagIMAGE_NT_HEADER = 'DWORD Signature;' & $tagIMAGE_FILE_HEADER & $tagIMAGE_OPTIONAL_HEADER

	Local $hFile = FileOpen(@AutoItExe, 16)
	Local $dBytes = FileRead($hFile)
	FileClose($hFile)

	Local $tExe = DllStructCreate('byte Data[' & BinaryLen($dBytes) & ']')
	Local $pExe = DllStructGetPtr($tExe)
	DllStructSetData($tExe, 'Data', $dBytes)

	Local $tIMAGE_DOS_HEADER = DllStructCreate($tagIMAGE_DOS_HEADER, $pExe)
	If DllStructGetData($tIMAGE_DOS_HEADER, 'e_magic') <> 0x5A4D Then
		Return SetError(2, 0, Null)
	EndIf

	Local $pPEHeader = $pExe + DllStructGetData($tIMAGE_DOS_HEADER, 'e_lfanew')
	Local $tIMAGE_NT_HEADER = DllStructCreate($tagIMAGE_NT_HEADER, $pPEHeader)
	If DllStructGetData($tIMAGE_NT_HEADER, 'Signature') <> 0x4550 Then
		Return SetError(3, 0, Null)
	EndIf

	Return DllStructGetData($tIMAGE_NT_HEADER, 'Subsystem') == $IMAGE_SUBSYSTEM_WINDOWS_CUI
EndFunc
Version 0, edited 18 months ago by Andreik (next)

comment:3 Changed 18 months ago by jchd18

Yes that, or simpler: always use CW() in place of ConsoleWrite() like this:

Func CW($s = "")
        If @Compiled Then
                _CUI_ConsoleWrite($s)
        Else
                _ConsoleWrite($s)
        EndIf
EndFunc   ;==>CW

Func _CUI_ConsoleWrite(ByRef $s)
        Local Static $hDll = DllOpen("kernel32.dll")
        Local Static $hCon = __CUI_ConsoleInit($hDll)
        DllCall($hDll, "bool", "WriteConsoleW", "handle", $hCon, "wstr", $s & @LF, "dword", StringLen($s) + 1, "dword*", 0, "ptr", 0)
        Return
EndFunc   ;==>_CUI_ConsoleWrite

; internal use only
Func __CUI_ConsoleInit(ByRef $hDll)
        DllCall($hDll, "bool", "AllocConsole")
;~      The following 2 lines don't work for compiled scripts due to a MS bug
;~              see last post in thread https://developercommunity.visualstudio.com/t/setconsoleoutputcpcp-utf8-results-in-code-page-850/413190
;~              where MS support acknowledges it's a (still unfixed) bug in Windows itself
;~              So you can only display current locale codepage using current console font in a console when your script is compiled
;~              When running your script from SciTE, the UTF8 setting of SciTE overrides this bug and Unicode can be displayed
;~      DllCall("Kernel32.dll", "bool", "SetConsoleCP", "uint", 65001)
;~      DllCall("Kernel32.dll", "bool", "SetConsoleOutputCP", "uint", 65001)
        Return DllCall($hDll, "handle", "GetStdHandle", "int", -11)[0]
EndFunc   ;==>__CUI_ConsoleInit

; Unicode-aware ConsoleWrite
Func _ConsoleWrite(ByRef $s)
        ConsoleWrite(BinaryToString(StringToBinary($s & @LF, 4), 1))
EndFunc   ;==>_ConsoleWrite

Works for CUI or GUI, compiled or not.

Last edited 18 months ago by mLipok (previous) (diff)

comment:4 Changed 18 months ago by anonymous

Ok, let there be built-in function IsConsole(), why no?
As for examples above I've got my own functions which are almost th same :)

Guidelines for posting comments:

  • You cannot re-open a ticket but you may still leave a comment if you have additional information to add.
  • In-depth discussions should take place on the forum.

For more information see the full version of the ticket guidelines here.

Add Comment

Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.