Modify

Opened 3 years ago

Last modified 2 years 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 by TicketCleanup, 3 years ago

Version: 3.3.14.0

Automatic ticket cleanup.

comment:2 by Andreik, 2 years ago

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 2 years ago by mLipok (previous) (diff)

comment:3 by jchd18, 2 years ago

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 2 years ago by mLipok (previous) (diff)

comment:4 by anonymous, 2 years ago

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 :)

Modify Ticket

Action
as new The ticket will remain with no owner.

Add Comment


E-mail address and name can be saved in the Preferences .
 
Note: See TracTickets for help on using tickets.