[R] Commande DOS renvoi APPCRASH

Aide et conseils concernant AutoIt et ses outils.
Règles du forum
.
Répondre
Avatar du membre
ricky
Niveau 7
Niveau 7
Messages : 443
Enregistré le : ven. 06 févr. 2009 09:25
Localisation : Suisse
Status : Hors ligne

[R] Commande DOS renvoi APPCRASH

#1

Message par ricky »

Hello,

J'ai un script complexe qui exécute plusieurs commandes, dont des commandes dos. Mais, je ne sais pour quelle raison, j'en ai une qui aléatoirement me fait planter tout le programme et je n'en vois pas la raison.

Voici la commande : Netsh AdvFirewall firewall show rule name=all
Au milieu du programme elle plante, mais exécutée depuis une fenêtre dos, il n'y a aucun problème.

Code : Tout sélectionner

Func _OEMToAnsi($sOEM)

    $errorFunction &= " - OEMToAnsi"
    Local $a_Error[6] = [5, "unable to use the DLL file", "unknown 'return type'", "'function' not found in the DLL file", "bad number of parameters", "bad parameter"]

    ; http://autoitscript.fr/forum/viewtopic.php?f=21&t=4108&hilit=conversion+OEM+ANSI
    Local $a_AnsiFName = DllCall('user32.dll', 'Int', 'OemToChar', 'str', $sOEM, 'str', '')
    If @error Then SetError(1, 0, "Error : " & $a_Error[@error] & " (" & $sOEM & ")")
    Return $a_AnsiFName[2]

EndFunc   ;==>_OEMToAnsi

Func DosCommand($sCommand)

    Local $sCmdOutput= "", $sValue = ""
    Local $hWndCmd = Run(@ComSpec & " /c " & $sCommand, "", @SW_HIDE, $STDOUT_CHILD )

    While True
;~         $sCmdOutput = StdoutRead($hWndCmd)
        If @error Then ExitLoop
        ; this section will display it as it is being read
        If $sCmdOutput <> "" Then
            If $sCmdOutput <> "" Then $sValue &= _OEMToAnsi($sCmdOutput)
        EndIf
        ; end section
    WEnd

    Return $sValue

EndFunc
Ai-je un problème de codage?

De plus, en début de script j'utilise la commande :

Code : Tout sélectionner

Local $oErrorHandler = ObjEvent('AutoIt.Error', '_ObjErrorHandler')
Mais celui-ci ne capte pas l'erreur et fait un crash du Windows, pourquoi?

Merci d'avance pour l'aide à ses deux problèmes, mais liés.
Modifié en dernier par ricky le jeu. 18 juin 2015 16:02, modifié 1 fois.
Avatar du membre
ricky
Niveau 7
Niveau 7
Messages : 443
Enregistré le : ven. 06 févr. 2009 09:25
Localisation : Suisse
Status : Hors ligne

Re: [..] Commande DOS renvoi APPCRASH

#2

Message par ricky »

Hello,

personne ne peut m'aider sur mon problème?
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2284
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [..] Commande DOS renvoi APPCRASH

#3

Message par jchd »

Juste une petite remarque : la conversion OEM --> ANSI n'est pas correcte car les jeux de caractères sont différents. Si on veut récupérer sous AutoIt les mêmes caractères que DOS emploie, il faut cette version :

Code : Tout sélectionner

Func _OemToStr($sOEM)
    Local $iCodepage = 850      ; <<<<<<<<<<<<<<<<< DOS codepage value is installation dependant!
    Local $tText = DllStructCreate("byte[" & StringLen($sOEM) & "]")
    DllStructSetData($tText, 1, $sOEM)
    Local $aResult = DllCall("kernel32.dll", "int", "MultiByteToWideChar", "uint", $iCodepage, "dword", 0, "struct*", $tText, "int", DllStructGetSize($tText), _
                                "ptr", 0, "int", 0)
    Local $tWstr = DllStructCreate("wchar[" & $aResult[0] & "]")
    $aResult = DllCall("Kernel32.dll", "int", "MultiByteToWideChar", "uint", $iCodepage, "dword", 0, "struct*", $tText, "int", DllStructGetSize($tText), _
                                "struct*", $tWstr, "int", $aResult[0])
    Return DllStructGetData($tWstr, 1)
EndFunc   ;==>_OemToStr
Par contre, la commande DOS depuis le script fonctionne parfaitement chez moi.
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
Avatar du membre
ricky
Niveau 7
Niveau 7
Messages : 443
Enregistré le : ven. 06 févr. 2009 09:25
Localisation : Suisse
Status : Hors ligne

Re: [..] Commande DOS renvoi APPCRASH

#4

Message par ricky »

Merci beaucoup pour cette fonction.
Effectivement, ça à l'air de mieux marcher, le programme n'a pas l'air de planter au même endroit.

Oui, la commande était juste, je l’exécutais en dehors du programme et elle marchait sans problème.

Dernière question, pourquoi "AutoIt.Error" n'a pas capté le crash de l'application?
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2284
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [..] Commande DOS renvoi APPCRASH

#5

Message par jchd »

Ce gestionnaire d'erreur ne peut s'activer que sur détection d'une erreur provenant d'objets COM, donc inutile et inefficace sur du code ne manipulant que des variants AutoIt natifs (non COM).

Pour une raison que j'ignore, la transformation OEM --> Unicode ne fonctionne pas correctement : OemToCharW transforme les caractères de contrôle en codepoints Unicode sans aucun rapport, par exemple CRLF devient ♪◙, soit 0x0D --> 0x266A et 0x0A --> 0x25D9. Je recommande donc de ne pas utiliser ces fonctions et préférer les variantes similaires au code proposé, qui fonctionneront aussi sur des chaînes non bornées, tandis que OemToChar[|A|W] est limité à 64K caractères (par limitation de DllCall).

Ah oui : je vois que tu es en Suisse, donc vérifie le codepage DOS que tu emploies, ce n'est peut-être pas 850. Il y a moyen d'aller récupérer cette valeur par programme mais je n'ai pas le temps de chercher ça maintenant.

Quelle taille fait stdout ? Redirige la sortie de la commande (lancée dans une boîte de commande cmd.exe) vers un vieux bon fichier pour voir :
Netsh AdvFirewall firewall show rule name=all > Z:\path\FWrules.txt

Est-ce que ça fonctionne si tu fais la même chose depuis AutoIt, quite à traiter ultérieurement le fichier résultant ?
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
Avatar du membre
ricky
Niveau 7
Niveau 7
Messages : 443
Enregistré le : ven. 06 févr. 2009 09:25
Localisation : Suisse
Status : Hors ligne

Re: [..] Commande DOS renvoi APPCRASH

#6

Message par ricky »

Hello,

mais maintenant la fonction fonctionne (avec ta fonction dans le fichier à la place de _OEMToAnsi). J'ai testé et en sortie j'ai 4235 lignes dans le fichier en sortie, voir le fichier en sortie.
FWrules.txt
(197.29 Kio) Téléchargé 48 fois
Le problème est que je dois faire un script qui fonctionne pour n'importe quel codepage. Dans ce cas je suis en Suisse, mais ce programme doit marcher n'importe ou. Alors comment faire en fonction du codepage?

Mon codepage est bien le 850 : http://www.computerhope.com/chcphlp.htm
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2284
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [..] Commande DOS renvoi APPCRASH

#7

Message par jchd »

Ca doit le faire : https://msdn.microsoft.com/en-us/librar ... 85%29.aspx
Argh, non, ça c'est le codepage ANSI, côté appli Windows pur et dur.
Il y a probablement une entrée dans une ruche qui donne ça, mais je ne sais pas trop où dénicher ça. En attendant, l'appel doit marcher.
Je cherche autre chose.
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
Avatar du membre
ricky
Niveau 7
Niveau 7
Messages : 443
Enregistré le : ven. 06 févr. 2009 09:25
Localisation : Suisse
Status : Hors ligne

Re: [..] Commande DOS renvoi APPCRASH

#8

Message par ricky »

Mais je comprends pas ou tu veux en venir.
En tapant "chcp" dans une commande dos, on a le codepage :

Code : Tout sélectionner

C:\>chcp
Active code page: 850

C:\>
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2284
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [..] Commande DOS renvoi APPCRASH

#9

Message par jchd »

Oui bien sûr, mais si on pouvait le récupérer sans faire une regex sur la sortie de CHCP, ça serait quand même plus simple !
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2284
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [..] Commande DOS renvoi APPCRASH

#10

Message par jchd »

La valeur est dans : HKLM\SYSTEM\CurrentControlSet\Control\Nls\Codepage OEMCP
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
Avatar du membre
ricky
Niveau 7
Niveau 7
Messages : 443
Enregistré le : ven. 06 févr. 2009 09:25
Localisation : Suisse
Status : Hors ligne

Re: [..] Commande DOS renvoi APPCRASH

#11

Message par ricky »

Merci, je viens aussi de le trouver. Voilà le code modifié.

Code : Tout sélectionner

Func _OemToStr($sOEM)
    Local $iCodepage = RegRead("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage","OEMCP") 
    Local $tText = DllStructCreate("byte[" & StringLen($sOEM) & "]")
    DllStructSetData($tText, 1, $sOEM)
    Local $aResult = DllCall("kernel32.dll", "int", "MultiByteToWideChar", "uint", $iCodepage, "dword", 0, "struct*", $tText, "int", DllStructGetSize($tText), _
                                "ptr", 0, "int", 0)
    Local $tWstr = DllStructCreate("wchar[" & $aResult[0] & "]")
    $aResult = DllCall("Kernel32.dll", "int", "MultiByteToWideChar", "uint", $iCodepage, "dword", 0, "struct*", $tText, "int", DllStructGetSize($tText), _
                                "struct*", $tWstr, "int", $aResult[0])
    Return DllStructGetData($tWstr, 1)
EndFunc   ;==>_OemToStr
Merci pour ton aide.
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2284
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [R] Commande DOS renvoi APPCRASH

#12

Message par jchd »

Pour référence ultérieure ici, je poste ce script qui met en lumière les erreurs de conversion entre jeux de caractères OEM et ANSI ou Unicode (chaînes AutoIt) produites par la fonction OemToChar (W ou A).

Unicode impératif au niveau du source ET de la console Scite, sinon on n'y comprend plus rien !

Je cross-poste dans le post d'exemple. Euh, non, je ne retrouve pas le post qui était de notre Tlem je crois...

Code : Tout sélectionner

Func _OemToStr($sOEM, $iCodepage = Default)
    If $iCodepage = Default Then $iCodepage = Int(RegRead("HKLM\SYSTEM\CurrentControlSet\Control\Nls\Codepage", "OEMCP"))
    Local $tText = DllStructCreate("byte[" & StringLen($sOEM) & "]")
    DllStructSetData($tText, 1, $sOEM)
    $aResult = DllCall("kernel32.dll", "int", "MultiByteToWideChar", "uint", $iCodepage, "dword", 0, "struct*", $tText, "int", StringLen($sOEM), _
            "ptr", 0, "int", 0)
    Local $tWstr = DllStructCreate("wchar[" & $aResult[0] & "]")
    $aResult = DllCall("kernel32.dll", "int", "MultiByteToWideChar", "uint", $iCodepage, "dword", 0, "struct*", $tText, "int", StringLen($sOEM), _
            "struct*", $tWstr, "int", $aResult[0])
    Return DllStructGetData($tWstr, 1)
EndFunc   ;==>_OemToStr

Func _StrToOem($sStr, $iCodepage = Default)
    If $iCodepage = Default Then $iCodepage = Int(RegRead("HKLM\SYSTEM\CurrentControlSet\Control\Nls\Codepage", "OEMCP"))
    $aResult = DllCall("kernel32.dll", "int", "WideCharToMultiByte", "uint", $iCodepage, "dword", 0, "wstr", $sStr, "int", StringLen($sStr), _
            "ptr", 0, "int", 0, "ptr", 0, "ptr", 0)
    Local $tOem = DllStructCreate("byte[" & $aResult[0] & "]")
    $aResult = DllCall("Kernel32.dll", "int", "WideCharToMultiByte", "uint", $iCodepage, "dword", 0, "wstr", $sStr, "int", StringLen($sStr), _
            "struct*", $tOem, "int", $aResult[0], "ptr", 0, "ptr", 0)
    Return DllStructGetData($tOem, 1)
EndFunc   ;==>_StrToOem

Func _OemToCharW($sOEM)
    Local $aStr = DllCall('user32.dll', 'Int', 'OemToCharW', 'str', $sOEM, 'wstr', '')
    If Not @error Then Return $aStr[2]
EndFunc   ;==>_OemToCharW

Func _OemToCharA($sOEM)
    Local $aAnsi = DllCall('user32.dll', 'Int', 'OemToCharA', 'str', $sOEM, 'str', '')
    If Not @error Then Return $aAnsi[2]
EndFunc   ;==>_OemToCharA

; Unicode-aware ConsoleWrite
Func __ConsoleWrite($s)
    ConsoleWrite(BinaryToString(StringToBinary($s, 4), 1))
EndFunc   ;==>__ConsoleWrite

 ConsoleWrite("Diff    Oem       _OemStr     _OemToCharW   _OemToCharA" & @LF)
_ConsoleWrite("━━━━  ━━━━━━━━   ━━━━━━━━━━   ━━━━━━━━━━━   ━━━━━━━━━━━" & @LF)

Local $a, $c, $w, $s
For $i = 0x01 To 0xFF
    $c = Chr($i)
    $a = _OemToCharA($c)
    $w = _OemToCharW($c)
    $s = _OemToStr($c)
    _ConsoleWrite(' ' & ($w <> $s ? "W" : " ") & ($a <> $s ? "A" : " ") & _
            "   0x" & Hex($i, 2) & " " & _
            ((AscW($c) < 0x20 Or AscW($c) = 0x7F Or AscW($c) = 0xF0) ? "CTRL" : "‷" & $s & "‴ ") & _
            "  0x" & Hex(AscW($s), 4) & " " & _
            ((AscW($s) < 0x20 Or (AscW($s) > 0x7E And AscW($s) < 0x90) Or AscW($s) = 0xAD) ? "CTRL" : "‷" & $s & "‴ ") & _
            "  0x" & Hex(AscW($w), 4) & " " & _
            ((AscW($w) < 0x20 Or (AscW($w) > 0x7E And AscW($w) < 0x90) Or AscW($w) = 0xAD) ? "CTRL" : "‷" & $w & "‴ ") & _
            "    0x" & Hex(AscW($a), 2) & " " & _
            ((Asc($a) < 0x20 Or Asc($a) = 0x7F Or Asc($a) = 0xAD) ? "CTRL" : "‷" & $a & "‴") & @LF)
Next
Dans la colonne Diff de différences, un W signifie que le code obtenu par OemToCharW ne correspond pas à la conversion correcte entre OEM et Unicode, un A signifie que le code ANSI produit est distinct du code Unicode correct (ce qui n'est pas surprenant pour certains caractères OEM qui n'ont pas d'équivalence ANSI).

Outre les caractères de bordure de tableau, simples, doubles ou mixtes, on voit que le gros problème réside dans une conversion fantaisiste des caractères de contrôle, qui perdent alors tout leur sens.

La morale est de n'utiliser que des fonctions basées sur MultiByteToWideChar et WideCharToMultiByte et de ne surtout pas utiliser OemToChar(A ou W).

Edit : légères améliorations
Modifié en dernier par jchd le lun. 22 juin 2015 12:08, modifié 1 fois.
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
Avatar du membre
ricky
Niveau 7
Niveau 7
Messages : 443
Enregistré le : ven. 06 févr. 2009 09:25
Localisation : Suisse
Status : Hors ligne

Re: [R] Commande DOS renvoi APPCRASH

#13

Message par ricky »

Merci beaucoup pour les précisions.
Répondre