smackdab has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks,

I am trying to use DBI and optionally a sql or oracle (or other ;) DB.

I do a: eval "use dbd:Oracle;";

But if Oracle isn't installed, Windows pops up an error of a missing oracle dll BEFORE I get the DIE handler...

Is there a way to catch this error, BEFORE??? or do I just have to stick with an error message after the Windows error?

thanks!

Replies are listed 'Best First'.
Re: dynamic use and missing .dll
by castaway (Parson) on Apr 17, 2003 at 06:40 UTC
    'use' statements are run at compile time, not at runtime, so that's why it's dying without running your die handler (I assume, its hard to say without seeing the code!)
    To do it like that, use 'require' instead of 'use', which would then be done at runtime and should produce the required result.
    DBI shouldn't need you to do that at all though, it includes the DBD needed itself, and I'm guessing if you try to 'connect' to a resource that isn't available, it'll return a sensible error message in $DBI::errstr which you can parse. (Untested though.. )

    C.

Re: dynamic use and missing .dll
by Jenda (Abbot) on Apr 17, 2003 at 13:56 UTC

    Which DLL does it complain about? The .../auto/DBD/Oracle/Oracle.dll or some DLL that's part of the Oracle client libraries? If the first it would probably be best to do something like:

    my $found = 0; for my $dir (@INC) { if (-e "$dir/auto/DBD/Oracle/Oracle.dll") { $found = 1; last; } } if ($found) { ...
    If it is some other DLL then you will have to do something similar, but through a different list of directories. I guess through split(';', $ENV{PATH}) or in $ENV{ORACLE_HOME} or something. (I do not have Oracle to see where does it put its stuff.) Basicaly it seems you will have to make sure the DLL exists before you try to load the module.

    Update: castaway and flounder99 seem to have missed that smackdab uses eval "use DBD::Oracle" which IS something that executes at "runtime" (we all know there is not just one compile time and runtime, but anyway) and does set the $@ correctly. The problem appears to be elsewhere. It appears that DBD::Oracle loads a DLL that references some other DLLs. If those DLLs are not found Windows show a message box. And only after you click-off this messagebox, the loading of DBD::Oracle fails and issues an exception. The exception IS caught correctly then.

    So I believe the only way to suppress the messagebox (short of modifying the code of the DLL that failed to load the other DLL) is to make sure all necessary DLLs may be found. Not a nice solution, but the only solution I see.

    Jenda
    Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.
       -- Rick Osborne

    Edit by castaway: Closed small tag in signature

      Thanks Jenda, your update describes it exactly...wish I could have said that first time ;-)

      I should have said it was a dll in the oracle\bin directory...I guess to find the DLL before I do the "eval use DBD::Oracle" I would try and find a registry entry or environment var and then do a dir search like you say...

      For now, I am letting the error popup and then I popup a description of it (I have a Tk GUI).

      THANKS!

Re: dynamic use and missing .dll
by flounder99 (Friar) on Apr 17, 2003 at 13:23 UTC
    Use require and put it in a BEGIN block. Don't forget to import any functions you might need. I'm not sure if that will catch a missing dll that is not loaded until it is used, but it will detect if the module you want to use is not installed.
    #!/usr/bin/perl -w use strict; BEGIN { eval 'require NoneSuch'; die "Hey, you forgot to install NoneSuch!\n\n" if $@; import NoneSuch ("ImportedFunc"); } my $None = NoneSuch->new("foo"); ImportedFunc("bar");

    --

    flounder