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.xs2008-04-18 01:38:47.0 +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_UNIQUE0x02
+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))
-