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

I once again appeal to the Monks for enlightenment.

I am a relative newbie to Perl, but have been learning for a few months. I have written a fair amount of Perl code thus far, and have now attacked the most ambitious project yet. I am on the verge of admitting defeat and going over to the dark side and using VB.

I have installed the OLE PPM and tested many examples for controlling Word and Excel without problems. I thought I had this OLE stuff groked and could write automation code.

I have this non-Microsoft application with a brand new, beta OCX interface, with VB examples of controlling it. I have translated many calls from the VB examples to Perl, to no avail.

I have posted many detail questions here, and received valuable answers. I can now create my obj server, query object type and get the proper response, and destroy the object. But no calls to any function or method succeeds. I have spent many hours on the web studying tutorials and sample code for Microsoft and lotus applications.

I am starting to suspect that there is some significant deficit wrt support for OCX's vs. VB that I am somehow missing. This morning while surfing the web yet again for samples and documentation I came across a statement to the effect that Perl OLE does not support OCX. This threw me into panic.

The statement was without further elaboration, but caused me to think that the reason all my calls are failing is not that I am doing something wrong, but rather that there is something about the objects and methods I am calling that makes them different from similar appearing calls to, for example, Excel.

Perhaps there is some aspect of this that Win32::OLE isn't supporting, or perhaps there is something fundamentally broken in the application itself that locks it in to being called from VB.

I need enlightenment from the Monks, show me the error of my ways. I have used OLEView and the perl Browser-OLE to examine the objects. I have looked at them in the machines registry. I am at a loss as to why my calls fail.

For example: The file is HALi.OCX. The library is HALiCnt. There is a class CModes, which contains a property Count as a readonly Long. There is a Class HALi which contains a property Modes as _CModes. My server is HALiCnt.HALi. By everything I have read, the statement:

$HALi = Win32::OLE->new('HALiCnt.HALi')
my $c = $HALi->Modes->Count();
should return the number of Modes defined, which is in actuality known by me to be 5. Instead I get "Can't call method Count on undefined value".

I have experimented for hours with many variations of the call, and with many other calls of a similar nature in the library. Nothing! Nada!

Am I overlooking something fundamental in Perl's support of OLE automation?? Must I tuck my tail and move with the masses to VB to access this application?

Please enlighten me.

Nathan

Replies are listed 'Best First'.
Re: Perl for OLE & OCX
by Ninthwave (Chaplain) on Jun 16, 2004 at 16:58 UTC

    Short for OLE Control Extension, an independent program module that can be accessed by other programs in a Windows environment. OCX controls end with a .ocx extension. OCX controls represent Microsoft's second generation of control architecture, the first being VBX controls written in Visual Basic.

    Both VBX and OCX controls have now been superseded by ActiveX controls. However, ActiveX is backward compatible with OCX controls, which means that ActiveX containers, such as Microsoft's Internet Explorer, can execute OCX components.

    From: http://216.239.59.104/search?q=cache:ZeIpZRTRifMJ:www.webopedia.com/TERM/O/OCX.html+ocx&hl=en

    An ocx is just a component control, without having a container object perl has no way to access them.

    "Perl for Win32 cannot currently use OCX controls, which require additional OLE support."
    From Learning Perl on Win32 Chapter 19

    "The Win32::OLE module uses the IDispatch interface exclusively. It is not possible to access a custom OLE interface. OLE events and OCX's are currently not supported.

    Actually, that's no longer strictly true. This module now contains ALPHA level support for OLE events. This is largely untested and the specific interface might still change in the future." from the Active State docs on Win32::OLE

    update:
    I wouldn't say that not supporting an ocx is defective of perl. OCX's are designed to compile with a vb project. Which is different from OLE, you can add OLE support into an OCX but the application that compiles the OCX does the automation the functions for the OCX are added to the applications. From further reading of Win32 Perl Programming bvy Dave Roth, and MSDN it appears that ActiveX (.ocx files) can be built to include an IDispatch interface. If this ocx lacks that it needs the container object.

    "No matter where you go, there you are." BB

        It would depend on how the OCX was written. My guess is from the above description, this is just a control set meant to be embedded in a VB app.

        "No matter where you go, there you are." BB
        I dunno. Is it???

        I guess I will look into it, but I am becoming convinced that Perl is the wrong tool for this job, I guess. Unless some kind soul can show me a way......

        Nathan

      I guess some of the subtlties are lost on me.

      Sounds like my quest is quixotic and I should abandon Perl for this project until some future point.

      Unless someone can show me a way to embed my code in an ActiveX container???

      Live and learn.

        I would say it is not you, it is Microsoft. As I remember and anyone can correct me if I am wrong as the subject was introduced to me in an almost backwards order. OCX were originally just toolsetas, that were used to give vb apps more tools. You would use OCX controls to add widgets and functions not available directly from the os or vb. ActiveX became the preferred means of doing this and I believe kept the same extension name. So ActiveX is OCX. It is up to the developer of the OCX on what functionality the component has. From the descript of the above, and the reference to VB calls to the OCX I believe it was meant to be embedded in a VB application and has no means of OLE automation on its own. I can not say that positively without seeing the documentation for the object in question.

        I think this has a good overview of the technology from Microsoft's point of view The Component Object Model (COM) and its related COM-based technologies:

        "No matter where you go, there you are." BB
Re: Perl for OLE & OCX
by meetraz (Hermit) on Jun 16, 2004 at 16:59 UTC
    If "Modes" is a property (and not a method), then it may help to reference it like one. Something like this may work:

    my $HALi = Win32::OLE->new('HALiCnt.HALi'); my $c = $HALi->{'Modes'}->Count();
      Thanks, but nope. Tried it, same result.
Re: Perl for OLE & OCX
by NetWallah (Canon) on Jun 16, 2004 at 17:24 UTC
    How about doing some error-checking on the value returned from
    $HALi = Win32::OLE->new('HALiCnt.HALi')
    You should probably have something like
    $HALi = Win32::OLE->new('HALiCnt.HALi') or die "$!";

    The other thing to check is to use the perl OLE browser that comes with Activestate , to verify the methods/properties of the object.

    Offense, like beauty, is in the eye of the beholder, and a fantasy.
    By guaranteeing freedom of expression, the First Amendment also guarantees offense.

      Yes, my code does use the || die function to ensure the object is actually open. I also use Query Object type to verify it, and then LastError on closing to verify no errors. Actual code is:
      use strict;
      use Win32::OLE;
      use Win32::OLE::Const;
      my $HALi;
      
      # Create a new OLE object using the Root Name of HALiCnt.HALi
        $HALi = Win32::OLE->new('HALiCnt.HALi') ||
        die "Cannot create COM server HALiCnt.HALi";
      
      if (Win32::OLE->QueryObjectType($HALi) eq "_HALi"){
      print "Successful Com Server creation\n";
      }
      
      my $c = $HALi->{'Modes'}->Count();
      print $c;
      
      $HALi->DESTROY(); # Call DESTROY to free memory and release the HALi Objects
      
      print "Last OLE Error detected.. ";
      print Win32::OLE->LastError();
      
      I have also spent hours with the OLE Browser and OLEView. The object is created successfully, verified, and destroyed all with no errors. But when I try to retrieve Count, it croaks. I have tried many, many variations on the call to Modes.Count. The VB example is simply HALi.Modes.Count but I can't make the Perl translation work. If I had VB I'd try it to verify *IT* works, but I think the proper answer is the lack of IDispatch interface, which I guess means I'm dead.

      Thanks for the help

      Nathan

             class CModes, which contains a property Count as a readonly Long

        <Lightbulb>
        OK so if Count is really a property, is should be accessed thus:

        my $c = $HALi->{'Modes'}{Count}; # or, my preference my $c = $HALi->{Modes}->{Count};
        </Lightbulb>

        Update: Just noticed that meetraz had the same idea, but his access method is slightly different.

        Offense, like beauty, is in the eye of the beholder, and a fantasy.
        By guaranteeing freedom of expression, the First Amendment also guarantees offense.