Запуск правил iLogic из внешнего приложения
При работе с объектами iLogic из Inventor AddIn доступ к ним можно реализовать в режиме раннего связывания. Если же требуется получить к ним доступ из внешнего приложения, приходится пользоваться поздним связыванием. Причина кроется в том, что объекты iLogic не являются истинными COM объектами, они в действительности представляют собой обертки для .NET объектов.
В случае VB .NET всегда легко было работать с поздним связыванием, для этого достаточно было декларировать переменные как тип Object вместо использования конкретного типа. В четвертой версии C# для той же цели можно воспользоваться ключевым словом dynamic.
Ниже приведен фрагмент кода внешнего приложения, эквивалентного in-process приложению из поста http://adndevblog.typepad.com/manufacturing/2013/04/call-ilogic-from-net.html.
- static void test_iLogic()
- {
- Inventor.Application oApp =
- System.Runtime.InteropServices.Marshal.
- GetActiveObject("Inventor.Application") as Inventor.Application;
- //iLogic is also an addin which has its guid
- string iLogicAddinGuid = "{3BDD8D79-2179-4B11-8A5A-257B1C0263AC}";
- Inventor.ApplicationAddIn addin = null;
- try
- {
- // try to get iLogic addin
- addin = oApp.ApplicationAddIns.get_ItemById(iLogicAddinGuid);
- }
- catch
- {
- // any error...
- }
- if (addin != null)
- {
- // activate the addin
- if (!addin.Activated)
- addin.Activate();
- // entrance of iLogic
- dynamic _iLogicAutomation = addin.Automation;
- Document oCurrentDoc = oApp.ActiveDocument;
- dynamic myRule = null;
- //dump all rules
- foreach (dynamic eachRule in _iLogicAutomation.Rules(oCurrentDoc))
- {
- if (eachRule.Name == "MyRule")
- {
- myRule = eachRule;
- //list the code of rule to the list box
- MessageBox.Show(myRule.Text);
- break;
- }
- }
- if (myRule != null)
- _iLogicAutomation.RunRule(oCurrentDoc, "MyRule");
- }
- }
В случае C++ дело обстоит несколько сложнее. В MSDN по этой теме есть хорошая обзорная статься «How To Use Visual C++ to Access DocumentProperties with Automation» http://support.microsoft.com/kb/238393.
- // http://support.microsoft.com/kb/238393
- //
- // AutoWrap() - Automation helper function...
- //
- HRESULT AutoWrap(int autoType, VARIANT *pvResult, IDispatch *pDisp,
- LPOLESTR ptName, int cArgs...)
- {
- // Begin variable-argument list...
- va_list marker;
- va_start(marker, cArgs);
- if(!pDisp) {
- MessageBox(NULL, _T("NULL IDispatch passed to AutoWrap()"),
- _T("Error"), 0x10010);
- _exit(0);
- }
- // Variables used...
- DISPPARAMS dp = { NULL, NULL, 0, 0 };
- DISPID dispidNamed = DISPID_PROPERTYPUT;
- DISPID dispID;
- HRESULT hr;
- TCHAR buf[200];
- // Get DISPID for name passed...
- hr = pDisp->GetIDsOfNames(
- IID_NULL, &ptName, 1, LOCALE_USER_DEFAULT, &dispID);
- if(FAILED(hr)) {
- _stprintf(buf,
- _T("IDispatch::GetIDsOfNames(\"%s\") failed w/err0x%08lx"),
- ptName, hr);
- MessageBox(NULL, buf, _T("AutoWrap()"), 0x10010);
- _exit(0);
- return hr;
- }
- // Allocate memory for arguments...
- VARIANT *pArgs = new VARIANT[cArgs+1];
- // Extract arguments...
- for(int i=0; i<cArgs; i++) {
- pArgs[i] = va_arg(marker, VARIANT);
- }
- // Build DISPPARAMS
- dp.cArgs = cArgs;
- dp.rgvarg = pArgs;
- // Handle special-case for property-puts!
- if(autoType & DISPATCH_PROPERTYPUT) {
- dp.cNamedArgs = 1;
- dp.rgdispidNamedArgs = &dispidNamed;
- }
- // Make the call!
- hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT,
- autoType, &dp, pvResult, NULL, NULL);
- if(FAILED(hr)) {
- _stprintf(buf,
- _T("IDispatch::Invoke(\"%s\"=%08lx) failed w/err 0x%08lx"),
- ptName, dispID, hr);
- MessageBox(NULL, buf, _T("AutoWrap()"), 0x10010);
- _exit(0);
- return hr;
- }
- // End variable-argument section...
- va_end(marker);
- delete [] pArgs;
- return hr;
- }
- int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
- {
- int nRetCode = 0;
- HRESULT Result = NOERROR;
- ::CoInitialize(NULL);
- // Access Inventor
- {
- CLSID InvAppClsid;
- Result = CLSIDFromProgID (
- _T("Inventor.Application"), &InvAppClsid);
- if (FAILED(Result)) return Result;
- CComPtr<IUnknown> pInvAppUnk;
- Result = ::GetActiveObject (InvAppClsid, NULL, &pInvAppUnk);
- if (FAILED (Result))
- _tprintf_s(_T("Could not get the active Inventor instance\n"));
- if (FAILED(Result)) return Result;
- CComPtr<Application> pInvApp;
- Result = pInvAppUnk->QueryInterface(
- __uuidof(Application), (void **) &pInvApp);
- if (FAILED(Result)) return Result;
- CComPtr<ApplicationAddIn> pAddIn =
- pInvApp->ApplicationAddIns->ItemById[
- _T("{3BDD8D79-2179-4B11-8A5A-257B1C0263AC}")];
- // Calling iLogic functions
- {
- CComPtr<IDispatch> pAuto = pAddIn->Automation;
- CComPtr<Document> pDoc = pInvApp->ActiveDocument;
- VARIANT ret;
- VARIANT param1;
- param1.vt = VT_DISPATCH;
- param1.pdispVal = pDoc;
- Result = AutoWrap(
- DISPATCH_PROPERTYGET, &ret, pAuto, _T("Rules"), 1, param1);
- // Rules() returns an IEnumarator - it will be wrapped as
- // IEnumVARIANT returned by GetEnumerator()
- // http://stackoverflow.com/questions/7399447/com-use-ienumerable-in-atl-c-project
- CComPtr<IDispatch> pRules = ret.pdispVal;
- Result = AutoWrap(
- DISPATCH_METHOD, &ret, pRules, _T("GetEnumerator"), 0);
- CComQIPtr<IEnumVARIANT> pRulesEnum = ret.punkVal;
- VARIANT rule;
- ULONG celt = 1, celtFetched;
- while (pRulesEnum->Next(celt, &rule, &celtFetched) == S_OK)
- {
- CComPtr<IDispatch> pRule = rule.pdispVal;
- Result = AutoWrap(
- DISPATCH_PROPERTYGET, &ret, pRule, _T("Name"), 0);
- BSTR name = ret.bstrVal;
- if (_tcscmp(name, _T("MyRule")) == 0)
- {
- Result = AutoWrap(
- DISPATCH_PROPERTYGET, &ret, pRule, _T("Text"), 0);
- BSTR text = ret.bstrVal;
- MessageBox(NULL, text, _T("Rule Text"), MB_OK);
- VARIANT param2;
- param2.vt = VT_BSTR;
- param2.bstrVal = name;
- // Parameters need to be added in reverse order.
- // In the C# code you'd call it like
- // _iLogicAutomation.RunRule(oCurrentDoc, "MyRule");
- Result = AutoWrap(
- DISPATCH_METHOD, &ret, pAuto, _T("RunRule"),
- 2, param2, param1);
- }
- }
- }
- }
- ::CoUninitialize();
- return nRetCode;
- }
Оригинал: http://adndevblog.typepad.com/manufacturing/2013/09/run-ilogic-rule-from-external-application.html
Обсуждение: http://adn-cis.org/forum/index.php?topic=233
Опубликовано 27.09.2013Отредактировано 05.11.2013 в 14:53:15