Jump to content

StdoutRead with Unicode Characters -> OemToCharW


Recommended Posts

Hi All,

I have a little problem with parsing commandline application into a GUI.

I thought it was another unicode problem

Ticket 1512

For example : German text isn't parsed correctly into the GUI if you take a look at the example given in the above URL check the image with the correct text. In the above URL they told me it's caused by the following

"It's nothing to do with StdoutRead(): chkdsk and many other command line utilities shipped with Windows use traditionally OEM charset, while AutoIt (as primarily GUI app) uses ANSI or corr. Windows codepage."

To Fix the problem this should be the solution

$ret = DllCall("user32.dll", "BOOL", "OemToCharW", "str", $line, "wstr", "")
If $ret[0] Then $line = $ret[2]

But this will produce some other characters/symbols in the GUI

Thanks

Best regards,

Emiel

Example code:

#RequireAdmin
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseUpx=n
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <Constants.au3>

Local $line

$Parent = GUICreate  ("OemToCharW Test", 520, 260, -1, -1)
$Logbox = GUICtrlCreateEdit('', 10, 10, 500, 200, BitOR($ES_READONLY, $WS_VSCROLL))
$Button = GuiCtrlCreateButton("Run", 10, 220, 80, 20)
GuiSetState ()


While 1
    $msg = GuiGetMsg()
    Switch $msg
        Case -3
            Exit
        Case -100 To 0
            ContinueLoop
        Case $GUI_EVENT_CLOSE
            Exit
        Case $Button
            _Check ()
    EndSwitch
Wend

Func _Check()
    GUICtrlSetData ($Button, "Stop")
    GUICtrlSetData($Logbox, "")

    $Pid = Run(@SystemDir & '\chkdsk.exe c:', @SystemDir, @SW_HIDE, $STDIN_CHILD + $STDOUT_CHILD)
    While 1
        $msg = GUIGetMsg()
            Select
                Case $msg = $GUI_EVENT_CLOSE or $msg = $Button
                    ProcessClose ($Pid)
                    Exitloop
            EndSelect
            $line = StdoutRead($Pid)
            ;$ret = DllCall("user32.dll", "BOOL", "OemToCharW", "str", $line, "wstr", "")
            ;If $ret[0] Then $line = $ret[2]
            If @error Then
                ExitLoop
            Else
                GUICtrlSetData($Logbox, @LF, True)
                GUICtrlSetData($Logbox, $line, True)
            EndIf
        WEnd
    GUICtrlSetData ($Button, "Run")
EndFunc

Best regards,Emiel Wieldraaijer

Link to comment
Share on other sites

Hi All,

I have a little problem with parsing commandline application into a GUI.

I thought it was another unicode problem

Ticket 1512

For example : German text isn't parsed correctly into the GUI if you take a look at the example given in the above URL check the image with the correct text. In the above URL they told me it's caused by the following

"It's nothing to do with StdoutRead(): chkdsk and many other command line utilities shipped with Windows use traditionally OEM charset, while AutoIt (as primarily GUI app) uses ANSI or corr. Windows codepage."

To Fix the problem this should be the solution

$ret = DllCall("user32.dll", "BOOL", "OemToCharW", "str", $line, "wstr", "")
If $ret[0] Then $line = $ret[2]

But this will produce some other characters/symbols in the GUI

Thanks

Best regards,

Emiel

Example code:

#RequireAdmin
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseUpx=n
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <Constants.au3>

Local $line

$Parent = GUICreate  ("OemToCharW Test", 520, 260, -1, -1)
$Logbox = GUICtrlCreateEdit('', 10, 10, 500, 200, BitOR($ES_READONLY, $WS_VSCROLL))
$Button = GuiCtrlCreateButton("Run", 10, 220, 80, 20)
GuiSetState ()


While 1
    $msg = GuiGetMsg()
    Switch $msg
        Case -3
            Exit
        Case -100 To 0
            ContinueLoop
        Case $GUI_EVENT_CLOSE
            Exit
        Case $Button
            _Check ()
    EndSwitch
Wend

Func _Check()
    GUICtrlSetData ($Button, "Stop")
    GUICtrlSetData($Logbox, "")

    $Pid = Run(@SystemDir & '\chkdsk.exe c:', @SystemDir, @SW_HIDE, $STDIN_CHILD + $STDOUT_CHILD)
    While 1
        $msg = GUIGetMsg()
            Select
                Case $msg = $GUI_EVENT_CLOSE or $msg = $Button
                    ProcessClose ($Pid)
                    Exitloop
            EndSelect
            $line = StdoutRead($Pid)
            ;$ret = DllCall("user32.dll", "BOOL", "OemToCharW", "str", $line, "wstr", "")
            ;If $ret[0] Then $line = $ret[2]
            If @error Then
                ExitLoop
            Else
                GUICtrlSetData($Logbox, @LF, True)
                GUICtrlSetData($Logbox, $line, True)
            EndIf
        WEnd
    GUICtrlSetData ($Button, "Run")
EndFunc

I see that you assume StdoutRead() reads text until a linebreak is encountered. This is not right. StdoutRead() returns as many characters as available in the buffer (sometimes it is only one).

With slight modifications and OemToChar commented in your script runs as expected (in German Windows):

#RequireAdmin
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseUpx=n
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <Constants.au3>

Local $line

$Parent = GUICreate  ("OemToCharW Test", 520, 260, -1, -1)
$Logbox = GUICtrlCreateEdit('', 10, 10, 500, 200, BitOR($ES_READONLY, $WS_VSCROLL))
$Button = GuiCtrlCreateButton("Run", 10, 220, 80, 20)
GuiSetState ()


While 1
    Dim $msg = GuiGetMsg()
    Switch $msg
        Case -3
            Exit
        Case -100 To 0
            ContinueLoop
        Case $GUI_EVENT_CLOSE
            Exit
        Case $Button
            _Check ()
    EndSwitch
Wend

Func _Check()
    GUICtrlSetData ($Button, "Stop")
    GUICtrlSetData($Logbox, "")

    Local $Pid = Run(@SystemDir & '\chkdsk.exe c:', @SystemDir, @SW_HIDE, $STDIN_CHILD + $STDOUT_CHILD)
    While $Pid
        $msg = GUIGetMsg()
        Select
            Case $msg = $GUI_EVENT_CLOSE or $msg = $Button
                ProcessClose ($Pid)
                Exitloop
        EndSelect
        Dim $line = StdoutRead($Pid)
        If @error Then
            ExitLoop
        Else
            $ret = DllCall("user32.dll", "BOOL", "OemToCharW", "str", $line, "wstr", "")
            If $ret[0] Then $line = $ret[2]
            ;GUICtrlSetData($Logbox, @LF, True)
            GUICtrlSetData($Logbox, $line, True)
        EndIf
    WEnd
    GUICtrlSetData ($Button, "Run")
EndFunc

The other little boxes printed into $Logbox are backspace/backtab characters (s. http://en.wikipedia.org/wiki/Control_character) - in the StdOut the have the effect that the old output is deleted in the console and next status message appears on the same line.

Edited by doudou

UDFS & Apps:

Spoiler

DDEML.au3 - DDE Client + Server
Localization.au3 - localize your scripts
TLI.au3 - type information on COM objects (TLBINF emulation)
TLBAutoEnum.au3 - auto-import of COM constants (enums)
AU3Automation - export AU3 scripts via COM interfaces
TypeLibInspector - OleView was yesterday

Coder's last words before final release: WE APOLOGIZE FOR INCONVENIENCE 

Link to comment
Share on other sites

  • 4 years later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...