Hello,

we use Perl and the Win32::OLE module to do some automatic drawing modifications with AutoCAD. Several scripts have been created and they work well with AutoCAD up to 2009.

Starting with AutoCAD 2010 it unfortunately gets nearly impossible to get a stable communication between Perl and AutoCAD with Win32::OLE. I get errors like the following one:

| Win32::OLE(0.1709) error 0x8001010a: "Durch den Messagefilter wurde
| angezeigt, dass die Anwendung ausgelastet ist"
|     in METHOD/PROPERTYGET "" at C:\bin\test.pl line 20

Searching the net revealed, that such errors also occur with Excel, sometimes, but no solution.

I tried several things like catching the error from Perl to retry the call and even tried to implement some retry code in the OLE.xs file until I found the following from Autodesk:

<http://through-the-interface.typepad.com/through_the_interface/2010/02/handling-com-calls-rejected-by-autocad-from-an-external-net-application.html>

This C# and so I tried to port this over to C++ to be able to add this to the OLE.xs file. I've attached the patch file with my proof of concept code.

As you see in my patch, I commented out the code, initializing OLE in multi threading mode, to make the CoRegisterMessageFilter call succeed.

Problem with this patch: It doesn't work. Anything, it does, is crashing the Perl interpreter... :-(

Is someone here able to have a look at this and perhaps fix this code?

Thank you very much in advance.

Mit freundlichen Grüßen / Best regards

Manuel Reimer


Bosch Rexroth. The Drive & Control Company

Tel. 09352/18-1578

manuel.rei...@boschrexroth.de
www.boschrexroth.com

Bosch Rexroth AG
Maria-Theresien-Straße 23
97816 Lohr am Main
GERMANY

Firmensitz: Stuttgart, Registrierung: Amtsgericht Stuttgart HRB 23192
Vorstand: Dr. Karl Tragl (Vorsitzender), Dr. Georg Hanen; Reiner Leipold-Büttner; Dr. Stefan Spindler
Vorsitzender des Aufsichtsrats: Dr. Siegfried Dais

diff -U 6 -pr Win32-OLE-0.1709.org//OLE.xs Win32-OLE-0.1709/OLE.xs
--- Win32-OLE-0.1709.org//OLE.xs        2008-04-18 01:38:47.000000000 +0200
+++ Win32-OLE-0.1709/OLE.xs     2011-03-03 08:13:39.922118800 +0100
@@ -32,12 +32,13 @@
 #define MY_VERSION "Win32::OLE(" XS_VERSION ")"
 
 #include <math.h>      /* this hack gets around VC-5.0 brainmelt */
 #define _WIN32_DCOM
 #include <windows.h>
 #include <ocidl.h>
+#include <objidl.h>
 
 #ifdef _DEBUG
 #   include <crtdbg.h>
 #   define DEBUGBREAK _CrtDbgBreak()
 #else
 #   define DEBUGBREAK
@@ -250,12 +251,22 @@ typedef struct _tagOBJECTHEADER
 #endif
 }   OBJECTHEADER;
 
 #define OBJFLAG_DESTROYED 0x01
 #define OBJFLAG_UNIQUE    0x02
 
+class MsgFilter : public IMessageFilter {
+  public:
+       STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*);
+       STDMETHOD_(ULONG,AddRef)(THIS);
+       STDMETHOD_(ULONG,Release)(THIS);
+       STDMETHOD_(DWORD,HandleInComingCall)(THIS_ 
DWORD,HTASK,DWORD,LPINTERFACEINFO);
+       STDMETHOD_(DWORD,RetryRejectedCall)(THIS_ HTASK,DWORD,DWORD);
+       STDMETHOD_(DWORD,MessagePending)(THIS_ HTASK,DWORD,DWORD);
+};
+
 /* Win32::OLE object */
 class EventSink;
 typedef struct
 {
     OBJECTHEADER header;
 
@@ -1932,12 +1943,48 @@ NextEnumElement(pTHX_ IEnumVARIANT *pEnu
     return sv;
 
 }   /* NextEnumElement */
 
 //------------------------------------------------------------------------
 
+STDMETHODIMP MsgFilter::QueryInterface(REFIID iid, void **ppv)
+{
+    if (iid == IID_IUnknown || iid == IID_IMessageFilter)
+    {
+        *ppv = this;
+        return S_OK;
+    }
+    return E_NOINTERFACE;
+}
+
+ULONG MsgFilter::AddRef(void)
+{
+    return 1;
+}
+
+ULONG MsgFilter::Release(void)
+{
+    return 1;
+}
+
+DWORD MsgFilter::HandleInComingCall (DWORD dwCallType, HTASK htaskCaller, 
DWORD dwTickCount, LPINTERFACEINFO lpInterfaceInfo)
+{
+    return 0; // SERVERCALL_ISHANDLED
+}
+
+DWORD MsgFilter::RetryRejectedCall(HTASK htaskCallee, DWORD dwTickCount, DWORD 
dwRejectType)
+{
+    return 1000; // Retry in a second
+}
+
+DWORD MsgFilter::MessagePending(HTASK htaskCallee, DWORD dwTickCount, DWORD 
dwPendingType)
+{
+    return 1; // PENDINGMSG_WAITNOPROCESS
+}
+
+
 EventSink::EventSink(pTHX_ WINOLEOBJECT *pObj, SV *events,
                     REFIID riid, ITypeInfo *pTypeInfo)
 {
     DBG(("EventSink::EventSink\n"));
     m_pObj = pObj;
     m_events = newSVsv(events);
@@ -3229,33 +3276,40 @@ Initialize(pTHX_ HV *stash, DWORD dwCoIn
 
        g_pfnCoUninitialize = NULL;
        g_bInitialized = TRUE;
 
        DBG(("Initialize dwCoInit=%d\n", dwCoInit));
 
-       if (dwCoInit == COINIT_OLEINITIALIZE) {
+//     if (dwCoInit == COINIT_OLEINITIALIZE) {
            hr = OleInitialize(NULL);
            if (SUCCEEDED(hr))
                g_pfnCoUninitialize = &OleUninitialize;
-       }
-       else if (dwCoInit != COINIT_NO_INITIALIZE) {
-           if (g_pfnCoInitializeEx)
-               hr = g_pfnCoInitializeEx(NULL, dwCoInit);
-           else
-               hr = CoInitialize(NULL);
-
-           if (SUCCEEDED(hr))
-               g_pfnCoUninitialize = &CoUninitialize;
-       }
+//     }
+//     else if (dwCoInit != COINIT_NO_INITIALIZE) {
+//         if (g_pfnCoInitializeEx)
+//             hr = g_pfnCoInitializeEx(NULL, dwCoInit);
+//         else
+//             hr = CoInitialize(NULL);
+//
+//         if (SUCCEEDED(hr))
+//             g_pfnCoUninitialize = &CoUninitialize;
+//     }
 
        if (FAILED(hr) && hr != RPC_E_CHANGED_MODE)
            ReportOleError(aTHX_ stash, hr);
     }
 
     LeaveCriticalSection(&g_CriticalSection);
 
+    IMessageFilter *filter = new MsgFilter();
+    IMessageFilter **old;
+    HRESULT hr = CoRegisterMessageFilter(filter, old);
+    if(FAILED(hr)) {
+      printf("failed!\n");
+    }
+
 }   /* Initialize */
 
 void
 Uninitialize(pTHX_ PERINTERP *pInterp)
 {
     DBG(("Uninitialize\n"));
_______________________________________________
Perl-Win32-Users mailing list
Perl-Win32-Users@listserv.ActiveState.com
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs

Reply via email to