Devcon - Unverständliche Rückgabeparamter

  • Hallo zusammen,


    ich hab ein Skirpt um via devcon bestimmte Hardware zu reseten.
    Dabei verwende ich die Parameter: "diabale & enable" oder "restart" (Problem besteht bei beiden Möglichkeiten)

    Spoiler anzeigen
    [autoit]

    Func _Devcon($aID, $mode)
    If Not FileExists($devcon) Then
    If $writelog Then _FileWriteLog($ci_log, 'Devcon.exe nicht gefunden - Programm beendet', 1)
    _Exit()
    EndIf
    Local $ID, $run, $msg
    Switch $mode
    Case 1

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 1 To $aID[0][0]
    $ID = "@" & $aID[$i][1]
    $run = Run($devcon & ' restart ' & $ID, @SystemDir, @SW_HIDE, $STDOUT_CHILD) ; refresh
    While 1
    $msg &= StdoutRead($run)
    If @error Then ExitLoop
    WEnd
    If $writelog Then _FileWriteLog($ci_log, 'Devcon return Message: ' & $msg, 1)
    Sleep(1000) ;1 Sekunde warten
    $msg = ''
    Next

    [/autoit] [autoit][/autoit] [autoit]

    Case 0
    For $i = 1 To $aID[0][0]
    $ID = "@" & $aID[$i][1]
    $run = Run($devcon & ' disable ' & $ID, @SystemDir, @SW_HIDE, $STDOUT_CHILD) ; deaktivieren
    While 1
    $msg &= StdoutRead($run)
    If @error Then ExitLoop
    WEnd
    If $writelog Then _FileWriteLog($ci_log, 'Devcon return Message: ' & $msg, 1)

    [/autoit] [autoit][/autoit] [autoit]

    Sleep(4000) ;4 Sekunden warten

    [/autoit] [autoit][/autoit] [autoit]

    $run = Run($devcon & ' enable ' & $ID, @SystemDir, @SW_HIDE, $STDOUT_CHILD) ; aktivieren
    $msg = ""
    While 1
    $msg &= StdoutRead($run)
    If @error Then ExitLoop
    WEnd
    If $writelog Then _FileWriteLog($ci_log, 'Devcon return Message: ' & $msg, 1)
    Sleep(1000) ;1 Sekunde warten
    $msg = ''
    Next
    EndSwitch

    [/autoit] [autoit][/autoit] [autoit]

    EndFunc ;==>_Devcon

    [/autoit]

    Manchmal kommt es jedoch vor, dass Devcon einen reboot vom System anfordert.
    Die Rückgabenachricht sieht dann so aus:

    Code
    PCI\VEN_18C3&DEV_0720&SUBSYS_DD0018C3&REV_01\4&3694E160&0&00A9: Disabled on reboot
    The 1 device(s) are ready to be disabled. To disable the devices, restart the
    
    
    devices or reboot the system


    Ein wirkliches Muster kann ich nicht erkennen. Das Problem tritt auch relativ selten auf. :S
    Welche Gründe kann es dafür geben?

    Gruß nuts

    Einmal editiert, zuletzt von nuts (14. Januar 2011 um 14:41)

  • Ich formuliere die Frage mal um:

    Weiss jemand wie man den Fehlerstatus von devcon auslesen kann?
    s. hier unter Hinweise: http://support.microsoft.com/kb/311272

    so gings leider nicht:

    [autoit]


    $run = Run($devcon & ' restart ' & $ID, @SystemDir, @SW_HIDE, $STDERR_MERGED) ; refresh
    While 1
    $msg_err &= StderrRead($run)
    If @error Then ExitLoop
    WEnd
    While 1
    $msg &= StdoutRead($run)
    If @error Then ExitLoop
    WEnd
    If $writelog Then _FileWriteLog($ci_log, 'Devcon return Message: ' &StringReplace($msg, @cr, @LF), 1)
    If $writelog Then _FileWriteLog($ci_log, 'Devcon return Error: ' & $msg_err, 1)

    [/autoit]
  • Hm?
    Nee DVB-S Hardware 8)

    Mit BitOR($STDOUT_CHILD, $STDERR_CHILD) gehts leider auch nicht ($STDOUT_CHILD+ $STDERR_CHILD wie in der Hilfe beschrieben klappt auch nicht).

    [autoit]


    $run = Run($devcon & ' restart ' & $ID, @SystemDir, @SW_HIDE,BitOR($STDOUT_CHILD, $STDERR_CHILD)) ; refresh
    While 1
    $msg_err &= StderrRead($run, true)
    If @error Then ExitLoop
    WEnd
    While 1
    $msg &= StdoutRead($run)
    If @error Then ExitLoop
    WEnd
    If $writelog Then _FileWriteLog($ci_log, 'Devcon return Message: ' &StringReplace($msg, @cr, @LF), 1)
    If $writelog Then _FileWriteLog($ci_log, 'Devcon return Error: ' & $msg_err, 1)

    [/autoit]

    So sieht das .log aus.

    Code
    2011-01-13 10:00:56 : Devcon return Error: 
    2011-01-13 10:00:56 : Devcon return Message: HDAUDIO\FUNC_01&VEN_10EC&DEV_0272&SUBSYS_15580771&REV_1000\4&1ABBB45C&0&0001: Requires reboot
    
    
    Not all of 1 device(s) restarted, at least one requires reboot to complete the operation.


    Bei einem angeforderten reboot müsste laut Doku doch eine 1 zurückgegeben werden? ?(

  • Hallo,

    ich vermute das im devcon ein bug ist, denn es scheint kein Error Stream geschrieben zu werden.

    ich habe das mal hiermit getestet:

    Spoiler anzeigen
    [autoit]

    ConsoleWrite("Test beginnt")
    ConsoleWriteError(1)
    Exit

    [/autoit]

    Das als exe Compiliert

    und das Script zum testen:

    Spoiler anzeigen
    [autoit]


    ; Demonstriert StdoutRead()
    #include <Constants.au3>

    [/autoit] [autoit][/autoit] [autoit]

    ;Local $foo = Run("devcon.exe restart 12345", @SystemDir, @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)
    Local $foo = Run("Return Werte Testen.exe", @SystemDir, @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)
    Local $line = ""
    Local $lineErr = ""

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    $lineErr &= StderrRead($foo)
    If @error Then ExitLoop
    WEnd
    MsgBox(0, "STDERR gelesen:", $lineErr)
    While 1
    $line &= StdoutRead($foo)
    If @error Then ExitLoop
    WEnd
    MsgBox(0, "STDOUT gelesen:", $line)

    [/autoit]

    Mit meiner Test exe kommen beide Streams, bei devcon kommt nur der Strdout

  • Also bei mir geht das

    Spoiler anzeigen
    [autoit]

    #include <Constants.au3>

    [/autoit] [autoit][/autoit] [autoit]

    _Devcon("devcon.exe help"); Kein Error
    _Devcon("devcon.exe findall"); Error

    [/autoit] [autoit][/autoit] [autoit]

    Func _Devcon($sCmd)
    Local $sErr = "", $sOut = ""
    Local $hPID = Run($sCmd, @SystemDir, @SW_HIDE, BitOR($STDERR_CHILD, $STDOUT_CHILD))
    While 1
    $sOut &= StdoutRead($hPID)
    If @error Then ExitLoop
    WEnd
    While 1
    $sErr &= StderrRead($hPID)
    If @error Then ExitLoop
    WEnd
    Switch StringLen($sErr)
    Case 0
    MsgBox(0, "Kein Error", "Kein Error" & @CRLF & @CRLF & $sOut)
    Case Else
    MsgBox(0, "ERROR", "StdErr: " & @CRLF & $sErr)
    EndSwitch
    EndFunc ;==>_Devcon

    [/autoit]
  • Geht es auch mit dem parameter restart?
    Die Nachricht, dass ein Neustart nötig ist kommt z.B. wenn die Hardware in Benutzung ist.
    Ich nehm dazu die Soundkarte und spiele ein mp3 ab.

    Das funktioniert bei mir nämlich dann nicht :(


    P.S: Vielleicht ganz interessant: devcon basiert scheinbar auf der setupAPI
    http://msdn.microsoft.com/en-us/library/ff550855.aspx


    Edit\
    Nach deiner Variante bekommt man aber auch nicht den Exitcode :?:

    Einmal editiert, zuletzt von nuts (13. Januar 2011 um 12:14)

  • Mhm ganz so einfach ists wohl doch nicht.
    Mit Runwait bekomme ich den Exitcode verliere aber die Rückmeldung von StdoutRead :(

    Zitat

    StdOut in eine Datei umlenken " > Log.txt"


    Wie geht das denn genau?

  • Hi

    mit " > test.txt" wird der stdout und mit " 2> test.txt" der stderr in eine Datei geschrieben anstatt in der Konsole ausgegeben
    um das nun in AutoIt umzusetzen, musst du die Befehle in eine Batchdatei auslagern:
    (vielleicht gibt es auch eine elegantere Lösung!?)

    Spoiler anzeigen
    [autoit]

    _Devcon('"' & @ScriptDir & '\devcon.exe"' & ' help'); Kein Error
    _Devcon('"' & @ScriptDir & '\devcon.exe"' & ' findall'); Error

    [/autoit] [autoit][/autoit] [autoit]

    Func _Devcon($sCmd)
    Local $hFile = FileOpen(@ScriptDir & "\temp.bat", 2)
    FileWriteLine($hFile, '@Echo off')
    FileWriteLine($hFile, $sCmd & ' > "' & @ScriptDir & '\stdout.txt" 2> "' & @ScriptDir & '\stderr.txt"')
    FileWriteLine($hFile, 'Exit ERRORLEVEL')
    FileClose($hFile)

    [/autoit] [autoit][/autoit] [autoit]

    Local $iExitCode = RunWait("temp.bat", @ScriptDir, @SW_HIDE)
    Local $sOut = FileRead("stdout.txt")
    Local $sErr = FileRead("stderr.txt")
    Switch $iExitCode
    Case 0
    MsgBox(0, "Kein Error", "Kein Error" & @CRLF & @CRLF & $sOut)
    Case Else
    MsgBox(0, "ERROR", "Exitcode: " & $iExitCode & @CRLF & @CRLF & $sErr)
    EndSwitch

    [/autoit] [autoit][/autoit] [autoit]

    FileDelete(@ScriptDir & "\temp.bat")
    FileDelete(@ScriptDir & "\stdout.txt")
    FileDelete(@ScriptDir & "\stderr.txt")
    EndFunc ;==>_Devcon

    [/autoit]

    E

  • Dann so:

    [autoit]

    #include <Constants.au3>
    #include <WinAPI.au3>

    [/autoit][autoit][/autoit][autoit]

    _Devcon("devcon.exe help"); Kein Error
    _Devcon("devcon.exe findall"); Error

    [/autoit][autoit][/autoit][autoit]

    Func _Devcon($sCmd)
    Local $sErr = "", $sOut = ""
    Local $hPID = Run($sCmd, @SystemDir, @SW_HIDE, BitOR($STDERR_CHILD, $STDOUT_CHILD))

    [/autoit][autoit][/autoit][autoit]

    Local $hProc = _WinAPI_OpenProcess(0x0400, 0, $hPID)
    While 1
    $sOut &= StdoutRead($hPID)
    If @error Then ExitLoop
    WEnd
    While 1
    $sErr &= StderrRead($hPID)
    If @error Then ExitLoop
    WEnd
    Local $aReturn = DllCall("kernel32", "hwnd", "GetExitCodeProcess", "handle", $hProc, "dword*", 0)
    If @error Or Not IsArray($aReturn) Then Return SetError(1, 0, False)
    Switch $aReturn[2]
    Case 0
    MsgBox(0, "Kein Error", "Kein Error" & @CRLF & @CRLF & $sOut)
    Case Else
    MsgBox(0, "ERROR", "Exitcode: " & $aReturn[2] & @CRLF & "StdErr: " & @CRLF & $sErr)
    EndSwitch
    _WinAPI_CloseHandle($hProc)
    EndFunc ;==>_Devcon

    [/autoit]

    E

  • Ich hab mal versucht diese Vorgehensweise in eine allgemeine Funktion zu packen:

    Spoiler anzeigen
    [autoit]


    Func _RunEx($sCmd, $iflag = 7)
    ; eukalyptus
    ; mod. nuts
    ;
    ; $iflag 1 => return Exitcode (String)
    ; $iflag 2 => return StdoutRead (String)
    ; $iflag 4 => return StderrRead (String)
    ; $iflag 7 (default) => return Exitcode & StdoutRead & StderrRead (Array)
    ; $iflag 3 return Exitcode & StdoutRead (Array)
    ; $iflag 5 return Exitcode & StderrRead (Array)
    ; $iflag 6 return StdoutRead & StderrRead (Array)

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Local $sErr = "", $sOut = ""
    Local $hPID = Run($sCmd, @SystemDir, @SW_HIDE, BitOR($STDERR_CHILD, $STDOUT_CHILD))

    [/autoit] [autoit][/autoit] [autoit]

    Local $hProc = _WinAPI_OpenProcess(0x0400, 0, $hPID)
    While 1
    $sOut &= StdoutRead($hPID)
    If @error Then ExitLoop
    WEnd
    While 1
    $sErr &= StderrRead($hPID)
    If @error Then ExitLoop
    WEnd
    Local $aexit = DllCall("kernel32", "hwnd", "GetExitCodeProcess", "handle", $hProc, "dword*", 0)
    If @error Or Not IsArray($aexit) Then
    _WinAPI_CloseHandle($hProc)
    Return SetError(1, 0, False)
    EndIf
    _WinAPI_CloseHandle($hProc)

    [/autoit] [autoit][/autoit] [autoit]

    Switch $iflag
    Case 7
    Return StringSplit($sOut & "|" & $sErr & "|" & $aexit[2], "|")
    Case 1
    Return $aexit[2]
    Case 2
    Return $sOut
    Case 4
    Return $sErr
    Case 3
    Return StringSplit($aexit[2] & "|" & $sOut, "|")
    Case 5
    Return StringSplit($aexit[2] & "|" & $sErr, "|")
    Case 6
    Return StringSplit($sOut & "|" & $sErr, "|")
    EndSwitch

    [/autoit] [autoit][/autoit] [autoit]

    EndFunc ;==>_RunEx

    [/autoit]