RE: [OLE] Controlling AutoCAD = 2010 fails with Win32::OLE. Error 0x8001010a.

2011-03-07 Thread Jan Dubois
On Thu, 03 Mar 2011, Manuel Reimer wrote:

Hi Manuel,

[...]
 
 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.

The way to tell Win32::OLE to use OleInitialize() is to call

Win32::OLE-Initialize(Win32::OLE::COINIT_OLEINITIALIZE());

right after you use Win32::OLE.  Put it inside a BEGIN block if you
may call any OLE functionality at compile time (e.g. while loading other
code).
 
 Problem with this patch: It doesn't work. Anything, it does, is crashing
 the Perl interpreter... :-(

It is not crashing for me just running the bundled test suite.  Do you have
some sample script that crashes that doesn't involve AutoCAD, as I don't
have a copy of that application available.

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

I haven't really looked at your code; just applied the patch, built the
module and ran the tests, with no crash in sight.

So I assume the crash only happens when the MessageFilter is actually
being invoked.  I'll try to look at your implementation to see if I can
find anything that could go wrong, but having a reproducible crash would
make this easier.

Cheers,
-Jan


___
Perl-Win32-Users mailing list
Perl-Win32-Users@listserv.ActiveState.com
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs


[OLE] Controlling AutoCAD = 2010 fails with Win32::OLE. Error 0x8001010a.

2011-03-03 Thread Manuel Reimer

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))
-