Jump to content

Recommended Posts

Hi all,

Bit of a fun one with querying WMI objects and setting errors within a function.  Below is example code that I've used from JSThePatriot previous UDFs but the example would apply to many other scenarios.  Basically the SetError should be called if $colItems is not an object as a result of the WMI query.  This is then used to create a corresponding error message.

I've tried disabling WMIC thus forcing it to not be an object, but rather than catching the error and telling me about it, the code simply fails therefore surely making the purpose of the logging useless??  I've experienced this before but in other languages such as java i would use a try catch etc and get around this....any suggestions for its use in AutoIT?


Thanks

 

 

#region Header
#comments-start
    Title:          Computer Information Automation UDF Library for AutoIt3 - EXAMPLES
    Filename:       CompInfoExamples.au3
    Description:    Examples using the UDF's from CompInfo.au3
    Author:         Jarvis J. Stubblefield (JSThePatriot) http://www.vortexrevolutions.com/
    Version:        00.03.08
    Last Update:    11.09.06
    Requirements:   AutoIt v3.2 +, Developed/Tested on WindowsXP Pro Service Pack 2
    Notes:          Errors associated with incorrect objects will be common user errors. AutoIt beta 3.1.1.63 has added an ObjName()
    function that will be used to trap and report most of these errors.

    Special thanks to Firestorm (Testing, Use), Koala (Testing, Bug Fix), and everyone else that has helped in the creation of this Example File.
#comments-end
#endregion Header

#region Global Variables and Constants
If Not(IsDeclared("$cI_CompName")) Then
    Global  $cI_CompName = @ComputerName
EndIf
Global Const $cI_VersionInfo        = "00.03.08"
Global Const $cI_aName              = 0, _
             $cI_aDesc              = 4
Global  $wbemFlagReturnImmediately  = 0x10, _   ;DO NOT CHANGE
$wbemFlagForwardOnly        = 0x20              ;DO NOT CHANGE
Global  $ERR_NO_INFO                = "Array contains no information", _
        $ERR_NOT_OBJ                = "$colItems isnt an object"
#endregion Global Variables and Constants

#Region Boot Configuration
Dim $BootConfig
_ComputerGetBootConfig($BootConfig)

If @error Then
    $error = @error
    $extended = @extended

    Switch $extended
        Case 1
            _ErrorMsg($ERR_NO_INFO)
        Case 2
            _ErrorMsg($ERR_NOT_OBJ)
    EndSwitch
EndIf

For $i = 1 To $BootConfig[0][0] Step 1
    MsgBox(0, "Test _ComputerGetBootConfig", "Name: " & $BootConfig[$i][0] & @CRLF & _
            "Boot Directory: " & $BootConfig[$i][1] & @CRLF & _
            "Configuration Path: " & $BootConfig[$i][2] & @CRLF & _
            "Last Drive: " & $BootConfig[$i][3] & @CRLF & _
            "Description: " & $BootConfig[$i][4] & @CRLF & _
            "Scratch Directory: " & $BootConfig[$i][5] & @CRLF & _
            "Setting ID: " & $BootConfig[$i][6] & @CRLF & _
            "Temp Directory: " & $BootConfig[$i][7])
Next
#endregion Boot Configuration

#region ---- Internal Functions
Func _ErrorMsg($message, $time = 0)
    MsgBox(48 + 262144, "Error!", $message, $time)
    ConsoleWrite("Error!" & $message & $time & @CRLF)
EndFunc
#endregion Internal Functions

Func _ComputerGetBootConfig(ByRef $aBootConfigInfo)
    Local $colItems, $objWMIService, $objItem
    Dim $aBootConfigInfo[1][8], $i = 1

    $objWMIService = ObjGet("winmgmts:\\" & $cI_Compname & "\root\CIMV2")
    $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_BootConfiguration", "WQL", $wbemFlagReturnImmediately + $wbemFlagForwardOnly)

    If IsObj($colItems) Then
        For $objItem In $colItems
            ReDim $aBootConfigInfo[UBound($aBootConfigInfo) + 1][8]
            $aBootConfigInfo[$i][0]  = $objItem.Name
            $aBootConfigInfo[$i][1]  = $objItem.BootDirectory
            $aBootConfigInfo[$i][2]  = $objItem.ConfigurationPath
            $aBootConfigInfo[$i][3]  = $objItem.LastDrive
            $aBootConfigInfo[$i][4]  = $objItem.Description
            $aBootConfigInfo[$i][5]  = $objItem.ScratchDirectory
            $aBootConfigInfo[$i][6]  = $objItem.SettingID
            $aBootConfigInfo[$i][7]  = $objItem.TempDirectory
            $i += 1
        Next
        $aBootConfigInfo[0][0] = UBound($aBootConfigInfo) - 1
        If $aBootConfigInfo[0][0] < 1 Then
            SetError(1, 1, 0)
        EndIf
    Else
        SetError(1, 2, 0)
    EndIf
EndFunc ;_ComputerGetBootConfig

 

Share this post


Link to post
Share on other sites

There is no try/catch or OnError in AutoIt, although there is a way to catch Object errors using ObjEvent and "AutoIt.Error". Here's how you can do it with the existing code you have.

#Region Header
#comments-start
    Title:          Computer Information Automation UDF Library for AutoIt3 - EXAMPLES
    Filename:       CompInfoExamples.au3
    Description:    Examples using the UDF's from CompInfo.au3
    Author:         Jarvis J. Stubblefield (JSThePatriot) http://www.vortexrevolutions.com/
    Version:        00.03.08
    Last Update:    11.09.06
    Requirements:   AutoIt v3.2 +, Developed/Tested on WindowsXP Pro Service Pack 2
    Notes:          Errors associated with incorrect objects will be common user errors. AutoIt beta 3.1.1.63 has added an ObjName()
    function that will be used to trap and report most of these errors.

    Special thanks to Firestorm (Testing, Use), Koala (Testing, Bug Fix), and everyone else that has helped in the creation of this Example File.
#comments-end
#EndRegion Header

#Region Global Variables and Constants
If Not (IsDeclared("$cI_CompName")) Then
    Global $cI_CompName = @ComputerName
EndIf
Global Const $cI_VersionInfo = "00.03.08"
Global Const $cI_aName = 0, _
        $cI_aDesc = 4
Global $wbemFlagReturnImmediately = 0x10, _   ;DO NOT CHANGE
        $wbemFlagForwardOnly = 0x20 ;DO NOT CHANGE
Global $ERR_NO_INFO = "Array contains no information", _
        $ERR_NOT_OBJ = "$colItems isnt an object"
#EndRegion Global Variables and Constants

#Region Boot Configuration
Dim $BootConfig
_ComputerGetBootConfig($BootConfig)

If @error Then
    $error = @error
    $extended = @extended

    Switch $extended
        Case 1
            _ErrorMsg($ERR_NO_INFO)
        Case 2
            _ErrorMsg($ERR_NOT_OBJ)
    EndSwitch
EndIf

For $i = 1 To $BootConfig[0][0] Step 1
    MsgBox(0, "Test _ComputerGetBootConfig", "Name: " & $BootConfig[$i][0] & @CRLF & _
            "Boot Directory: " & $BootConfig[$i][1] & @CRLF & _
            "Configuration Path: " & $BootConfig[$i][2] & @CRLF & _
            "Last Drive: " & $BootConfig[$i][3] & @CRLF & _
            "Description: " & $BootConfig[$i][4] & @CRLF & _
            "Scratch Directory: " & $BootConfig[$i][5] & @CRLF & _
            "Setting ID: " & $BootConfig[$i][6] & @CRLF & _
            "Temp Directory: " & $BootConfig[$i][7])
Next
#EndRegion Boot Configuration

#Region ---- Internal Functions
Func _ErrorMsg($message, $time = 0)
    MsgBox(48 + 262144, "Error!", $message, $time)
    ConsoleWrite("Error!" & $message & $time & @CRLF)
EndFunc   ;==>_ErrorMsg
#EndRegion ---- Internal Functions
Func _COMErrFunc() ; <<<<<<<<<<<<<<<<<<<<<<<<
    _ErrorMsg($ERR_NOT_OBJ)
EndFunc   ;==>_COMErrFunc

Func _ComputerGetBootConfig(ByRef $aBootConfigInfo)
    Local $oError = ObjEvent("AutoIt.Error", "_COMErrFunc") ; <<<<<<<<<<<<<<<<<<<
    Local $colItems, $objWMIService, $objItem
    Dim $aBootConfigInfo[1][8], $i = 1

    $objWMIService = ObjGet("winmgmts:\\" & $cI_CompName & "\root\CIMV2")
    $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_BootConfiguration", "WQL", $wbemFlagReturnImmediately + $wbemFlagForwardOnly)

    If IsObj($colItems) Then
        For $objItem In $colItems
            ReDim $aBootConfigInfo[UBound($aBootConfigInfo) + 1][8]
            $aBootConfigInfo[$i][0] = $objItem.Name
            $aBootConfigInfo[$i][1] = $objItem.BootDirectory
            $aBootConfigInfo[$i][2] = $objItem.ConfigurationPath
            $aBootConfigInfo[$i][3] = $objItem.LastDrive
            $aBootConfigInfo[$i][4] = $objItem.Description
            $aBootConfigInfo[$i][5] = $objItem.ScratchDirectory
            $aBootConfigInfo[$i][6] = $objItem.SettingID
            $aBootConfigInfo[$i][7] = $objItem.TempDirectory
            $i += 1
        Next
        $aBootConfigInfo[0][0] = UBound($aBootConfigInfo) - 1
        If $aBootConfigInfo[0][0] < 1 Then
            SetError(1, 1, 0)
        EndIf
    Else
        SetError(1, 2, 0)
    EndIf
EndFunc   ;==>_ComputerGetBootConfig

Although, I'd write your code this way to check to see if the ObjGet worked first, before checking for WMI values.

; What you have
    $objWMIService = ObjGet("winmgmts:\\" & $cI_CompName & "\root\CIMV2")
    $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_BootConfiguration", "WQL", $wbemFlagReturnImmediately + $wbemFlagForwardOnly)

    If IsObj($colItems) Then
; another way of doing it.
    $objWMIService = ObjGet("winmgmts:\\" & $cI_CompName & "\root\CIMV2")

    If IsObj($objWMIService) Then ; <<<<<<<<<<<<<<<<< Note change of variable name
        $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_BootConfiguration", "WQL", $wbemFlagReturnImmediately + $wbemFlagForwardOnly)

 


If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites

Awesome! Never knew you could do that.  I completely understand your final remark about checking the ObjGet worked first, that should be a simple change for my code, but as for the ObjEvent("AutoIt.Error","_COMErrFunc") I'm not quite there yet!

Does that mean I can still keep my SetErrors and all of that functionality (where applicable) within my code and this extra bit will catch those critical AutoIT errors that prevent it running then?  I'll have to dig through the related help file and get my head around it! :)

Thanks very much!

Edited by RC86

Share this post


Link to post
Share on other sites

The ObjEvent only catches COM errors.


If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites
3 minutes ago, BrewManNH said:

The ObjEvent only catches COM errors.

Gotcha, very handy! THanks for the help!

Share this post


Link to post
Share on other sites

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

  • Similar Content

    • By user4157124
      File- and stdout/-err (console) output of messages, regular- and COM Object errors, exit method and -code, etc.
      Just call _AUERLO_Log() after to be logged functions (no parameters required if preceding function returns @error on failure). Or replace ConsoleWrite() (and SciTE trace lines) by _AUERLO_Log() for existing scripts. _AUERLO_FileRead() and _AUERLO_View() to display error log file contents (or import as CSV file to Microsoft Excel for example). Register custom functions to adjust date/time format and replace or add output functionality (no UDF source code modifications required). Output to: file console (stdout and stderr) non-blocking notification (Beep(), SoundPlay(), etc.) prompt (GUI dialog; script-halting notification) Microsoft Windows Event Log custom (register function) Download:
      AUERLO v2.0.0 Remarks:
      AutoIt v3.3.14.3+ required. @ScriptLineNumber = 0 if from callback (like $AUERLO_OPT_FUNCEXIT, except for $AUERLO_OPT_FUNCCOM = Default), -1 if @compiled. Generates Au3Stripper warnings (to be ignored without consequence; #AutoIt3Wrapper_Au3stripper_OnError=ForceUse -safe). agpl-3.0 auerlo.au3 :
      _AUERLO_Set() _AUERLO_Log() _AUERLO_LogAlt() _AUERLO_LogWinAPI() _AUERLO_LogEnv() _AUERLO_Assert() _AUERLO_FileClear() _AUERLO_FileRead() _AUERLO_View() auerloConstants.au3 :
      $AUERLO_LVL__ENUM - debug levels, $AUERLO_OPT__ENUM - _AUERLO_Set() options, $AUERLO_RET__ENUM - Return codes, $AUERLO_ERR__ENUM - @error codes, and $AUERLO_ATR__ENUM - error item attributes. Usage explanation:
      If @error signifies failure (implicit logging) : _ArrayDisplay($sNotAnArray); Returns @error = 1. _AUERLO_Log() ; Logs as $AUERLO_LVL_TRACE, $AUERLO_LVL_ERROR on @error, $AUERLO_LVL_DEBUG on @extended. If @error Then ... ; _AUERLO_Log() transparently passes @error and @extended from _ArrayDisplay(). If return value signifies failure (explicit logging) : If FileExists('invalid path') = 0 Then _AUERLO_Log('', $AUERLO_LVL_ERROR) Global $g_hFile = FileOpen('invalid path') If $g_hFile = -1 Then _AUERLO_Log('', $AUERLO_LVL_ERROR) If (return) value or expression result signifies failure (implicit logging): Global $g_hFile = FileOpen('invalid path') _AUERLO_Assert(Not ($g_hFile = -1)) ; $AUERLO_LVL_DEBUG if True (success), $AUERLO_LVL_WARNING if False. _AUERLO_Assert(FileWrite($g_hFile, 'data')); Successfull return value (1) evaluates to True; failure (0) to False. _AUERLO_Assert(IsArray($g_sNotAnArray)) Import error log file contents: Global $g_aArray2D = _AUERLO_FileRead(); Reads from current error log file. _AUERLO_View($g_aArray2D) Configuration ($AUERLO_OPT__ENUM in auerloConstants.au3 for description of all options) : _AUERLO_Set($AUERLO_OPT_LOGFILE, False) ; Disables output to error log file. _AUERLO_Set($AUERLO_OPT_LOGSTD, True) ; Enables output to stdout/stderr (console). _AUERLO_Set($AUERLO_OPT_FNCEXIT, Default) ; Registers default exit handler (no script exit logging without). _AUERLO_Set($AUERLO_OPT_FNCEXIT, Null) ; Deregisters default exit handler. _AUERLO_Set($AUERLO_OPT_FNCCOM, Default) ; Registers default COM Object error handler (no COM error logging without). _AUERLO_Set($AUERLO_OPT_FNCCOM, Null) ; Deregisters COM Object error handler. _AUERLO_Set($AUERLO_OPT_FNCCOM, YourFunc); Registers custom COM Object error handler YourFunc().  
    • By user4157124
      File- and stdout/-err (console) output of messages, regular- and COM Object errors, exit method and -code, etc.
      More ...
    • By MFrancisca
      Hello! 
      I've been checking the logging UDFs in the wiki, mostly Log4a and Loga and I wanted to ask which one would you recommend for a script that will be executed remotely through PSExec. My main question is where the logs are located in that situation and if I can change that location to a custom one., because I need to retrieve them at the end of execution.
      So in a rough description the process is
      Open PSExec
      Send compiled AutoIT script to remote machine
      Execute script
      Copy logs from the remote to the local machine.
       
      Any opinions? 
    • By VADemon
      I've encountered a problem with a single file where I cannot retrieve it's Date-time. So far my code has worked well for over 30 files, but this one is a mystery I cannot debug myself due to insufficient Au3 knowledge.
      In line 11 "_Date_Time_FileTimeToArray" is called and for this particular file it sets the @error to 10. I don't know what that error code means, but it's not set by the _Date functions themselves I think.
      Overall, it could be a problem caused by any of the functions below, how can I properly debug this? / Does anybody know a what's causing this?
      _WinAPI_CreateFile() / _Date_Time_GetFileTime() / _Date_Time_FileTimeToArray()
      Func _SetFileTimes($sFilePath) Local $monthNumber[13] = ["", "January", "February", "March", "April", "May", "Juny", "July", "August", "September", "October", "November", "December"] Local $dayNumber[7] = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"] Local $fHandle = _WinAPI_CreateFile($sFilePath, 2, 2) ; read-only ; may NOT return a valid date for some reason! TODO Local $fTagFILETIME = _Date_Time_GetFileTime($fHandle) _WinAPI_CloseHandle($fHandle) ; This will return an empty array if theres no valid date $fModTime = _Date_Time_FileTimeToArray($fTagFILETIME[2]) ; last Modified if @error <> 10 then Local $year = $fModTime[2] Local $month = $fModTime[0] Local $day = $fModTime[1] Local $hour = $fModTime[3] Local $min = $fModTime[4] Local $sec = $fModTime[5] Local $ms = $fModTime[6] Local $weekday = $fModTime[7] Global $prettyTimestamp = StringFormat("%s, %s %d, %04d %02d:%02d:%02d", $dayNumber[$weekday], $monthNumber[$month], $day, $year, $hour, $min, $sec) Global $uploadDate = StringFormat("%04d-%02d-%02d", $year, $month, $day) $fModTime = _Date_Time_FileTimeToArray(_Date_Time_FileTimeToLocalFileTime($fTagFILETIME[2])) ; last Modified Local $year = $fModTime[2] Local $month = $fModTime[0] Local $day = $fModTime[1] Local $hour = $fModTime[3] Local $min = $fModTime[4] Local $sec = $fModTime[5] Local $ms = $fModTime[6] Local $weekday = $fModTime[7] ; GetUnixTime accounts for Local time, hence feed it local time Global $unixTimestamp = _GetUnixTime($year &"/"& $month &"/"& $day &" "& $hour&":"& $min &":"& $sec) else Global $prettyTimestamp = "N/A" Global $uploadDate = "" Global $unixTimestamp = "N/A" endif endfunc  
      _GetUnixTime returned the year 1601 start date, showing that $fModTime is probably equal 0. (But Why?)
      The file reports these dates in Explorer, it's on local NTFS drive:
      Created: ‎‎Wednesday, ‎31. ‎Januar ‎2018, ‏‎18:55:02
      Modified: ‎Wednesday, ‎10. ‎Januar ‎2018, ‏‎12:39:23
      Accessed: ‎Wednesday, ‎10. ‎Januar ‎2018, ‏‎12:39:23
×
×
  • Create New...