Jump to content



Photo

Need Help With Handling Errors


  • Please log in to reply
13 replies to this topic

#1 JoCoTek

JoCoTek

    Seeker

  • Active Members
  • 7 posts

Posted 25 April 2012 - 10:12 PM

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






#2 JohnOne

JohnOne

    John

  • Active Members
  • PipPipPipPipPipPip
  • 8,827 posts

Posted 25 April 2012 - 10:17 PM

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
Run('hh mk:@MSITStore:'&StringReplace(@AutoItExe,'.exe','.chm')&'::/html/tutorials/helloworld/helloworld.htm','',@SW_MAXIMIZE)

#3 JoCoTek

JoCoTek

    Seeker

  • Active Members
  • 7 posts

Posted 25 April 2012 - 10:25 PM

The strange part, is that the error occurs AFTER that loop has run through for the problem DLL, only when it is finished with loop 1, and starts on loop 2 does it popup the error.

#4 kylomas

kylomas

    Want to see God laugh? Tell him you have plans!

  • Active Members
  • PipPipPipPipPipPip
  • 2,036 posts

Posted 25 April 2012 - 10:28 PM

JoCoTek,

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

kylomas
"Really?, How Do you know the're not random numbers?"Forum Rules

#5 JoCoTek

JoCoTek

    Seeker

  • Active Members
  • 7 posts

Posted 25 April 2012 - 10:41 PM

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?

#6 JohnOne

JohnOne

    John

  • Active Members
  • PipPipPipPipPipPip
  • 8,827 posts

Posted 25 April 2012 - 11:06 PM

$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, 25 April 2012 - 11:06 PM.

AutoIt Absolute Beginners Require a serial
Run('hh mk:@MSITStore:'&StringReplace(@AutoItExe,'.exe','.chm')&'::/html/tutorials/helloworld/helloworld.htm','',@SW_MAXIMIZE)

#7 JoCoTek

JoCoTek

    Seeker

  • Active Members
  • 7 posts

Posted 25 April 2012 - 11:30 PM

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.

#8 JohnOne

JohnOne

    John

  • Active Members
  • PipPipPipPipPipPip
  • 8,827 posts

Posted 26 April 2012 - 12:04 AM

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
Run('hh mk:@MSITStore:'&StringReplace(@AutoItExe,'.exe','.chm')&'::/html/tutorials/helloworld/helloworld.htm','',@SW_MAXIMIZE)

#9 JoCoTek

JoCoTek

    Seeker

  • Active Members
  • 7 posts

Posted 26 April 2012 - 03:12 PM

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.

#10 BrewManNH

BrewManNH

    באָבקעס מיט קודוצ׳ה

  • MVPs
  • 6,797 posts

Posted 26 April 2012 - 03:24 PM

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.

How to ask questions the smart way!

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 editorGUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.

GUIToolTip UDF Demo - Demo script to show how to use the GUIToolTip UDF to create and use customized tooltips.

Posted Image


#11 JoCoTek

JoCoTek

    Seeker

  • Active Members
  • 7 posts

Posted 26 April 2012 - 03:52 PM

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.

AutoIt         
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, 26 April 2012 - 03:54 PM.


#12 JohnOne

JohnOne

    John

  • Active Members
  • PipPipPipPipPipPip
  • 8,827 posts

Posted 26 April 2012 - 04:01 PM

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:

http://www.autoitscript.com/forum/topic/137927-dllcallbackregister/

Edited by JohnOne, 26 April 2012 - 04:03 PM.

AutoIt Absolute Beginners Require a serial
Run('hh mk:@MSITStore:'&StringReplace(@AutoItExe,'.exe','.chm')&'::/html/tutorials/helloworld/helloworld.htm','',@SW_MAXIMIZE)

#13 trancexx

trancexx

    Hm, I really shouldn't.

  • Active Members
  • PipPipPipPipPipPip
  • 5,186 posts

Posted 26 April 2012 - 04:17 PM

It's done like this:
AutoIt         
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


#14 JoCoTek

JoCoTek

    Seeker

  • Active Members
  • 7 posts

Posted 26 April 2012 - 04:36 PM

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, 26 April 2012 - 04:37 PM.





0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users