Modify

Opened 15 months ago

Last modified 13 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!

Attachments (0)

Change History (4)

comment:1 Changed 15 months ago by TicketCleanup

  • Version 3.3.14.0 deleted

Automatic ticket cleanup.

comment:2 Changed 13 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
Last edited 13 months ago by mLipok (previous) (diff)

comment:3 Changed 13 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.

Version 0, edited 13 months ago by jchd18 (next)

comment:4 Changed 13 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

Modify Ticket

Action
as new The ticket will remain with no owner.
Author


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

 
Note: See TracTickets for help on using tickets.