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

Hi,

I am trying to pass a win32:OLE application handle to another thread but the memory location printed is incorrect. I have tried various methods such as using shared module and getactiveobject method but nothing worked. Any help is greatly appreciated. Please see the code below:

use Win32::OLE; use Win32::OLE::Variant; use Win32::OLE qw(EVENTS); #reuired to capture the events use Thread qw(:DEFAULT async yield); my $RQCC = Win32::OLE->new("Excel.Application") || die "CreateObject: +$!"; print "MainProcess = $RQCC\n"; # Starting to monitor event queue my $EventQueueTread = Thread->new(\&MonitorEventQueue); system "pause"; return 1; sub MonitorEventQueue { my $Devicehandle=Win32::OLE->GetActiveObject('Excel.Application'); print "MonitorEventQueue = $Devicehandle\n"; system "pause"; }

I have the following PERL installed on my systems:
This is perl, v5.10.1 built for MSWin32-x86-multi-thread (with 4 registered patches, see perl -V for more detail)

Copyright 1987-2009, Larry Wall

Binary build 1008 294165 provided by ActiveState http://www.ActiveState.com Built Dec 9 2010 06:00:35

Replies are listed 'Best First'.
Re: Passing win32::0LE object handle to another thread
by BrowserUk (Patriarch) on Mar 17, 2011 at 02:21 UTC
    I am trying to pass a win32:OLE application handle to another thread ...

    Don't! For reasons that have nothing to do with Perl, it will not work.

    If you need to access OLE from different threads, you'll need to create new handles in each thread. This pretty much excludes any possibility of accessing the same OLE object from more than one thread at a time.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      Hi, Thanks for the reply. I am creating a new object to WIN32::OLE in the thread and I am consistently getting the following here:

      Win32::OLE(0.1709) error 0x800401f0: "CoInitialize has not been called" at test.pl line 63 thread 1

      use strict; use Win32::OLE; use Win32::OLE::Variant; use Win32::OLE qw(EVENTS); #reuired to capture the events use Thread qw(:DEFAULT async yield); Win32::OLE->Initialize(); my $RQCC; my $modemPort = 32; my $ret; my $deviceId; my $EventQueueTread = Thread->new(\&MonitorEventQueue); system "pause"; RQCCExtension::RQCCSreenMsg("INFO", "EXIT TEST CASE" ); sub MonitorEventQueue { Win32::OLE->Initialize(); my $Devicehandle = win32::OLE->new("rqccdriver.ExternalInterface.1" +) || die "CreateObject: $!"; if(!$Devicehandle) { print ("ERROR", "Could not create instance of RQCC" ); exit(1); } print "Should be Devicehandle = $Devicehandle\n"; my $Version = $Devicehandle->GetVersion(); print "Version = $Version\n"; }

        I am creating a new object to WIN32::OLE in the thread and I am consistently getting the following here:

        Win32::OLE(0.1709) error 0x800401f0: "CoInitialize has not been called" at test.pl

        From the briefest of looks at the docs for ->Initialize(), I find the optional COINIT argument:

        Win32::OLE->Initialize(COINIT)

        The Initialize() class method can be used to specify an alternative apartment model for the Perl thread. It must be called before the first OLE object is created. If the Win32::OLE::Const module is used then the call to the Initialize() method must be made from a BEGIN block before the first use statement for the Win32::OLE::Const module.

        Valid values for COINIT are:

        • Win32::OLE::COINIT_APARTMENTTHREADED - single threaded
        • Win32::OLE::COINIT_MULTITHREADED - the default
        • Win32::OLE::COINIT_OLEINITIALIZE - single threaded, additional OLE stuff

        COINIT_OLEINITIALIZE is sometimes needed when an OLE object uses additional OLE compound document technologies not available from the normal COM subsystem (for example MAPI.Session seems to require it). Both COINIT_OLEINITIALIZE and COINIT_APARTMENTTHREADED create a hidden top level window and a message queue for the Perl process. This may create problems with other application, because Perl normally doesn't process its message queue. This means programs using synchronous communication between applications (such as DDE initiation), may hang until Perl makes another OLE method call/property access or terminates. This applies to InstallShield setups and many things started to shell associations. Please try to utilize the Win32::OLE->SpinMessageLoop and Win32::OLE->Uninitialize methods if you can not use the default COINIT_MULTITHREADED model.

        My interpretation of that is that you will need to pass one of those constants when you initialise this object. Which of those will depend upon the threading model chosen by the authors for the particular DCOM library you are trying to use. Ie. It is up to you to read the docs for that library and discover that information. No one here can do that for you.

        Please note. I have little knowledge, and no interest, in Win32::OLE. I do have some knowledge of threads, and considerable reservations that using the former from multiple iThreads will ever work. If you succeed in getting beyond the initialisation problem, I foresee that you will encounter other problems, and I will be unable to help you with them.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.