Jump to content

Need Help With Handling Errors


Recommended Posts

Afternoon,

I am trying to make a basic program that un-registers then re-registers every DLL or OCX in a path provided. So far everything is working great, except when the program encounters a DLL that does not except the DllUnregisterServer or DllRegisterServer entry points. When my tool encounters such a DLL I get the following error.

"The program can't start because somefile.dll is missing from your computer. Try reinstalling the program to fix the problem."

Of course the file is not missing, or it would not have attempted to register it, so I tried registering it manually with RegSvr32 and got the following message.

"The module C:\MyPath\somefile.dll was loaded but the entry-point DllRegisterServer was not found.

Make sure that C:\MyPath\somefile.dll is a valid dll or ocx file and then try again."

So it would seem the issue is simply with that DLL, but I need some way to prevent the popup from with AutoIT. I have read various sections about error handling, but I am simply not understanding how to implement it.

The following is the portion of code that is giving the error, but it is simply a system error and the AutoIT script does in fact continue running. But this needs to run silently on a lot of users machines. A list of files is stored in the variable "$FilesToRegister"

For $i = 1 to $FilesToRegister[0]

$aCall = DllCall($RegisterPath & $FilesToRegister[$i], "long", "DllUnregisterServer")

If IsArray($aCall) = 1 Then $Msg = $aCall[0]
If IsArray($aCall) = 0 Then $Msg = $aCall

If @error Or $Msg <> 0 Then
  WriteLog(1,"UnReg FAILED " & @TAB & $Msg & @TAB & $RegisterPath & $FilesToRegister[$i])
Else
  WriteLog(1,"UnReg SUCCESS" & @TAB & "-0000000000" & @TAB & $RegisterPath & $FilesToRegister[$i])
EndIf

Next
Link to comment
Share on other sites

I don't think you could suppress such an error, but you might be able to detect the

error window via it's title or class (if they don't clash with something else)

and log, and close the window accordingly.

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

JoCoTek,

Try moving your error checking routine immediately after the DLL call.

kylomas

I have changed it all around, but the error does not happen in any of that code, only after it runs through. To test that I did the following.

For $i = 1 to $FilesToRegister[0]
MsgBox(0,"Msg",$i & "-" & 1)
$aCall = DllCall($RegisterPath & $FilesToRegister[$i], "long", "DllUnregisterServer")
MsgBox(0,"Msg",$i & "-" & 2)
If IsArray($aCall) = 1 Then $Msg = $aCall[0]
MsgBox(0,"Msg",$i & "-" & 3)
If IsArray($aCall) = 0 Then $Msg = $aCall
MsgBox(0,"Msg",$i & "-" & 4)
If @error Or $Msg <> 0 Then
  MsgBox(0,"Msg",$i & "-" & 5)
  WriteLog(1,"UnReg FAILED " & @TAB & $Msg & @TAB & $RegisterPath & $FilesToRegister[$i])
Else
  MsgBox(0,"Msg",$i & "-" & 5)
  WriteLog(1,"UnReg SUCCESS" & @TAB & "-0000000000" & @TAB & $RegisterPath & $FilesToRegister[$i])
EndIf
MsgBox(0,"Msg",$i & "-" & 6)
Next

So I had a popup on the screen after every step, such as 1-1, 1-2, 1-3, etc. The error happens after 2-1, but before 2-2, meaning it completes a full loop, and happens on the second execution of "$aCall = DllCall($RegisterPath & $FilesToRegister[$i], "long", "DllUnregisterServer")"

Is there something I need to clear at the end of my loop perhaps?

Link to comment
Share on other sites

$aCall = DllCall($RegisterPath & $FilesToRegister[$i], "long", "DllUnregisterServer")
If @error Then
   ;etc...
EndIf

As it stands in your code your @error is only checking if Msgbox Succeeded.

Or in earlier code only checking if IsArray succeeded.

Edited by JohnOne

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

As it stands in your code your @error is only checking if Msgbox Succeeded.

Or in earlier code only checking if IsArray succeeded.

Sadly I have tried many variations (see below), and others using DllOpen(), but they all end with the same result. If only there was a way to test if the function was available in the DLL before I attempted to call it.

For $i = 1 to $FilesToRegister[0]

$MyDLL = $RegisterPath & $FilesToRegister[$i]
$MyCall = DllCall($MyDLL, "long", "DllUnregisterServer")
If @error = 0 Then
  If IsArray($MyCall) = 1 Then $Msg = $MyCall[0]
  If IsArray($MyCall) = 0 Then $Msg = $MyCall
  msgbox(0,"msg",$MyDLL & " still results in an error " & $Msg)
  If $Msg = 0 Then
    WriteLog(1,"UnReg SUCCESS" & @TAB & "-0000000000" & @TAB & $MyDLL)
   Else
    WriteLog(1,"UnReg FAILED " & @TAB & $Msg & @TAB & $MyDLL)
   EndIf
  Else
   $Msg = "-0000000000"
   msgbox(0,"msg",$MyDLL & " still results in an error " & $MyCall)
   WriteLog(1,"UnReg FAILED " & @TAB & $Msg & @TAB & $MyDLL)
  EndIf
SetError(0)
Next

This script works, and has the exact same resulting error on the screen.

Link to comment
Share on other sites

From what I have read, there is no absolute way to test this.

But dllcall should set @error if the function is not found.

However, what if the dll is not registered to begin with, what would happen then?

Have you had a look at the MSDN documentation about using this?

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

But dllcall should set @error if the function is not found.

It does indeed set the error, which in turn my code records to a log, clears, and continues, but the system error still pops up none the less.

However, what if the dll is not registered to begin with, what would happen then?

There are actually about 50 dll's and ocx files in my test folder, and it doesn't matter if they are registered already or not, only 2 of them cause this error and they do it every time, using autoit, vbs, or the command prompt.

Have you had a look at the MSDN documentation about using this?

No, i am not really familiar with using dll's as I am more a high level scripter than a programmer, mostly with vbs. The little I did read was using .net as examples so I didn't see how I could translate it to autoit, but then again I am a noob at this so not sure.

I am not really concerned about these 2 dll's, they cant be registered anyways, and don't need to be, but I do need to have the error go away.

Link to comment
Share on other sites

Are they always the same DLLs? If so, put a check in your script to bypass making the attempt with those 2 DLLs, if the filename = the bad DLL, then go to the next one in the list.

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

Link to comment
Share on other sites

Are they always the same DLLs? If so, put a check in your script to bypass making the attempt with those 2 DLLs, if the filename = the bad DLL, then go to the next one in the list.

Funny you should say that. As I need this to work now, I decided to do that exact thing, but it still fails, but only once this time. It seems that it is failing on the dll call AFTER the bad dll, so there has to be some clear step or something that I am missing.

See below for my current code. For a test I have 4 dll's in my folder. It just so happens that as it goes in reverse alphebetical order, my two bad dll's end up running first. After that it should work fine on my next two. I have a msg box popup telling me which dll is about to run, and if it should or should not run based on those two if's. The first two loops popup with the names of my bad dlls as expected, with a 0 that they should not be ran. During those two loops my log indicates "UnReg SKIPPED", so the DllCall function was never ran against these two files. However on loop 3, with a dll that is good and should be ran, i get a popup saying that dll TWO could not be found. I am at a total loss as to what is happening. I have looked at my below code over and over, and can not see how dll 2 should be involved in loop 3 in any way shape or form.

For $i = 1 to $FilesToRegister[0]
$UseDLL = 1
$MyDLL = ""
$MyCall = ""
SetError(0)
$MyDLL = $RegisterPath & $FilesToRegister[$i]
If StringInStr($FilesToRegister[$i],"xmltok") <> 0 Then $UseDLL = 0
If StringInStr($FilesToRegister[$i],"xmlparse") <> 0 Then $UseDLL = 0

MsgBox(0,"Msg",$FilesToRegister[$i] & " - " & $UseDLL)
If $UseDLL = 1 Then

   $MyCall = DllCall($MyDLL, "long:cdecl", "DllUnregisterServer")
   If @error = 0 Then
    If IsArray($MyCall) = 1 Then $Msg = $MyCall[0]
    If IsArray($MyCall) = 0 Then $Msg = $MyCall
    If $Msg = 0 Then
      WriteLog(1,"UnReg SUCCESS" & @TAB & "-0000000000" & @TAB & $MyDLL)
     Else
      WriteLog(1,"UnReg FAILED " & @TAB & $Msg & @TAB & $MyDLL)
     EndIf
    Else
     SetError(0)
     WriteLog(1,"UnReg FAILED " & @TAB & "-0000000000" & @TAB & $MyDLL)
    EndIf
  Else
   WriteLog(1,"UnReg SKIPPED" & @TAB & "-0000000000" & @TAB & $MyDLL)
  EndIf
Next
Edited by JoCoTek
Link to comment
Share on other sites

In the documentation I read, it did mention that unregisterserver and reg... were callback functions.

Perhaps you might need to use dllcallbackregister.

I was asking about that function some time ago, I'll try to find the link.

EDIT:

Edited by JohnOne

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

It's done like this:

Global Const $SEM_FAILCRITICALERRORS = 1
;...

Local $iOldMode = _SetErrorMode($SEM_FAILCRITICALERRORS)
;...Now do what you do here...
#cs
For $i = 1 To $FilesToRegister[0]
    $aCall = DllCall($RegisterPath & $FilesToRegister[$i], "long", "DllUnregisterServer")
    If IsArray($aCall) = 1 Then $Msg = $aCall[0]
    If IsArray($aCall) = 0 Then $Msg = $aCall
    If @error Or $Msg <> 0 Then
        WriteLog(1, "UnReg FAILED " & @TAB & $Msg & @TAB & $RegisterPath & $FilesToRegister[$i])
    Else
        WriteLog(1, "UnReg SUCCESS" & @TAB & "-0000000000" & @TAB & $RegisterPath & $FilesToRegister[$i])
    EndIf
Next
#ce
_SetErrorMode($iOldMode)

;...


Func _SetErrorMode($iMode)
    Local $aCall = DllCall("kernel32.dll", "dword", "SetErrorMode", "dword", $iMode)
    If @error Then Return SetError(1, 0, 0)
    Return $aCall[0]
EndFunc

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

Well that was easy... thank you so much for the assistance.

I actually found right before you posted this, that it had something to do with the working directory of the autoit script. I was calling this autoit script with the following command line, but within a batch file. The batch file and the autoit script were in a directory on my flash drive. But the same thing happened when I put it in any directory other than the target of "C:Program FileseClinicalWorks".

"C:Program FilesAutoIt3AutoIt3.exe" "N:sandboxdeployecw2!ecw_Register.au3" "C:Program FileseClinicalWorks"

I am unsure why this resulted in an error though, and only on those two dlls, and only on the first two loops. The path to each dll is explicitly defined, and even verified in my log as the exact paths to the files. Then after the first two errors popup, everything continues like normal.

If I move the autoit script to the folder "C:Program FileseClinicalWorks", or add a "CD /D "C:Program FileseClinicalWorks"" command in my batch file, it all works fine."

But I really do appreciate your post on how to ignore the errors if needed.

Edited by JoCoTek
Link to comment
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
 Share

  • Recently Browsing   0 members

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