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

Ok i have a perl program LSEUI.pl and a Module for logging called CLUILogger.pm. inside the LSEUI.pl i have the following code
mylog = LogInit('LSEUI', 'UI', $thisloglevel); LogIT($mylog, '1', 'INFO', 'STARTUP', '', 'LSEUI Starting...User="'.$usercheck . '"' );
where LogInit and LogIT are functions inside CLUILogger.pm Inside CLUILogger.pm i have the following code
package CLUILogger; use Win32::OLE; use Exporter; @ISA = qw(Exporter); @EXPORT=qw(LogIT); #Example Logline with all things described #LogIT($mylog, # '5(loglevel def 5)', # 'INFO(category info/error/etc)', # 'TESTING(function)', # 'TESTING2(blank or further action inside function)', # "This is my logged line"); sub LogInit{ my $appname = $_[0]; my $module = $_[1]; my $apploglevel = $_[2]; $LogObj = Win32::OLE->new('LOGGERHELPER.UILogHelp'); $Log0bj->{LogLevel} = $apploglevel; $Log0bj->{AppName} = $appname; $Log0bj->{Module} = $module; Win32::MsgBox('my log is "'.$LogObj.'"'); return $LogObj; } sub LogIT { my $LogObj = $_[0]; my $loglevel = $_[1]; my $category = $_[2]; my $activity = $_[3]; my $subactivity = $_[4]; my $logstring = $_[5]; if ($LogObj->{LogLevel} < $loglevel) { $LogObj->LogMessage($LogObj->{AppName},$category,$activity,$subactiv +ity,$logstring); } } 1;
but when i run the program it tells me Can't call method "LogMessage" on unblessed reference at /PerlApp/CLUILogger.pm line 25. when the code was all inside the .pl file it worked fine its only when i pulled out the logging portion (so that all my programs can use it) that it started giving me this problem. Any ideas what im doing wrong here? -Mike

Replies are listed 'Best First'.
Re: Win32::OLE objects
by crashtest (Curate) on May 06, 2005 at 19:37 UTC
    I am surprised your first block of code makes it past the LogInit function. You only export LogIT, and not LogInit, in your module. Try changing the export to:
    @EXPORT=qw(LogInit LogIT);
    I am puzzled you don't get an error message about not being able to call a method on an undefined object, as opposed to a merely unblessed reference. Do you still have a spare version of LogInit lying around in your LSEUI.pl script / main package that might be returning something else? Hope this helps. If not, use strict and warnings in your code as a good first step to figuring out what's going wrong, as a previous poster suggests. Good luck!
      yes sorry i had to retype it all because this machine that has access to the Internet is not on the Intranet where im coding :( i finally FTP the files over and here is an exact copy and paste of what i had previously was messed up (added the prints from a previous reply as well
      package CLUILogger; use Win32::OLE; use Exporter; @ISA = qw(Exporter); @EXPORT=qw(LogInit LogIT); #Example Logline with all things described #LogIT($mylog, # '5(loglevel def 5)', # 'INFO(category info/error/etc)', # 'TESTING(function)', # 'TESTING2(blank or further action inside function)', # "This is my logged line"); sub LogInit{ my $appname = $_[0]; my $module = $_[1]; my $apploglevel = $_[2]; $NewLogObj = Win32::OLE->new('LOGGERHELPER.UILogHelp'); print "Ref is ", ref $NewLogObj, "\n"; print Win32::OLE->LastError(), "\n" unless ($NewLogObj); $NewLog0bj->{LogLevel} = $apploglevel; $NewLog0bj->{AppName} = $appname; $NewLog0bj->{Module} = $module; Win32::MsgBox('my log is "'.$NewLogObj.'"'); return $NewLogObj; } sub LogIT { my $LogObj = $_[0]; my $loglevel = $_[1]; my $category = $_[2]; my $activity = $_[3]; my $subactivity = $_[4]; my $logstring = $_[5]; #$LogObj = bless($LogObj, Win32::OLE); if ($LogObj->{LogLevel} < $loglevel) { $LogObj->LogMessage($LogObj->{AppName},$category,$activity,$subactivi +ty,$logstring); } } 1;


      and here is the code that is calling it from the perl file
      $mylog = LogInit('LSEUI', 'UI', $thisloglevel); LogIT($mylog, '1', 'INFO', 'STARTUP', '', 'LSEUI Starting...User="'.$usercheck . '"' );
        I tried running your updated code (with a different OLE object) under strict, and it immediately exposed a subtle typo you made. I assume you copy-and-pasted this from your "working" version, so this probably won't help you fix the unblessed reference, but it might have something to do with it after all.

        Depending on your font, you might not see it, but in line 25 and 33 of your module you refer to a variable named, logically enough, $NewLogObj. However, in lines 28, 29 and 30 you call it $NewLog0bj - thats $NewLog0bj, with a zero as the 7th character, not an "Oh".

        Are you posting the exact code that caused the error? I ask because the offending line number (25) in your error message has nothing to do with what's going on in the code you posted. And as far as I can see (and run), there are no unblessed references in what you're showing on PerlMonks.

        You really should run the complete code you have on your machine under strict and warnings. I would bet money that it'll expose the mistake.
Re: Win32::OLE objects
by chromatic (Archbishop) on May 06, 2005 at 19:22 UTC

    I'm not sure if the errors I see are from copying and pasting incorrectly, but your code above seems to be missing a few $ symbols.

    $LogObj->LogMessage($LogObj->{AppName}... $mylog = LogInit('LSEUI', 'UI', $thisloglevel);

    Using strict and warnings will alert you to similar errors.

    You should also check to see if the Win32::OLE call succeeds; if it returns an undefined object you'll have trouble.

      ya sorry i updated it so that LogMessage has the missing $ for $LogObj->{AppName} but my code already had it so that doesnt help me :(
Re: Win32::OLE objects
by jimbojones (Friar) on May 06, 2005 at 21:03 UTC
    Hi

    I ran the following code:
    use Win32::OLE; my $LogObj = Win32::OLE->new('LOGGERHELPER.UILogHelp'); print "REF IS: ", ref $LogObj, "\n"; print Win32::OLE->LastError(), "\n" unless ( $LogObj);
    the result is:
    REF IS: Win32::OLE(0.1702) error 0x800401f3: "Invalid class string"
    Then I searched the registry for "LOGGERHELPER" and "LOGGERHELPER.UILogHelp". I don't have that program id in my registry, hence the OLE new method doesn't work. Do you have the .dll for that class ID registered on your machine? Where can I find it?

    - j

      Thanks for all your help everyone :) 1. The zero's instead of OH's was def wrong but not causing the error i was getting.
      2. The dll is an internal app for my company so thats why you couldnt find it ;P
      3. The whole issue here is a combo of things
      Issue1: its a perlapp which is compiled into an exe so its harder to debug it seems (at least for me :P )
      Issue2: The reason it was saying an unblessed reference and quitting was because in the LINE BEFORE i called LogInit i called a function to read the logging level from the registry.. well guess what that function tried to call LogIT .. which obviously couldnt happen :(
      Again thanks everyone for all the suggestions and help i got it working now and its time for a beer :P Cya Monday!
Re: Win32::OLE objects
by jimbojones (Friar) on May 06, 2005 at 19:28 UTC
    Hi

    I ran your code and added the following:
    sub LogInit{ my $appname = $_[0]; my $module = $_[1]; my $apploglevel = $_[2]; $LogObj = Win32::OLE->new('LOGGERHELPER.UILogHelp'); print "Ref is ", ref $LogObj, "\n"; print Win32::OLE->LastError(), "\n" unless ($LogObj); $Log0bj->{LogLevel} = $apploglevel; $Log0bj->{AppName} = $appname; $Log0bj->{Module} = $module; Win32::MsgBox('my log is "'.$LogObj.'"'); return $LogObj;
    the Reference is null, and the last error is:

    Ref is Win32::OLE(0.1702) error 0x800401f3: "Invalid class string" Can't call method "LogMessage" on unblessed reference at CLUILogger.pm + line 42.
    Perhaps you need to import the LOGGERHELPER.UILogHelp constants in the Win32::OLE call?

    - j

      When all the code is in the same perl file it all works its only when i moved the logging code to a module that passing hte Win32::OLE object seems to get upset
      perl file --> calls LogInit
      pm file --> creates Win32::OLE object and passes back
      perl file --> calls LogIT passing in the Win32::OLE object that it got back
      pm file --> uses that object to pass it ARGS which logs things
      so basically im not passing Win32::OLE object correctly i guess i just dont know how to fix it :(
        Hi

        Right; is it possible that your 'use Win32::OLE' statement was/is different in your .pl file as opposed to the .pm file? Or had a use Win32::OLE::Const line?

        - j