65 #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
92 #include <epicsGuard.h>
93 #include <cantProceed.h>
114 std::string res(str);
123 #define MAX_PATH_LEN 256
125 static epicsThreadOnceId
onceId = EPICS_THREAD_ONCE_INIT;
130 _com_error com_error(hr, perrinfo);
132 _bstr_t desc = com_error.Description();
133 std::string message = (desc.GetBSTR() != NULL ? desc :
"");
139 CoInitializeEx(NULL, COINIT_MULTITHREADED);
147 long destCapacity = 128;
157 dest =
static_cast<char*
>(mallocMustSucceed(destCapacity,
"lvDCOMInterface::envExpand"));
158 n = macExpandString(
m_mac_env, str, dest, destCapacity);
159 }
while (n >= (destCapacity - 1));
164 size_t unused = destCapacity - ++n;
167 dest =
static_cast<char*
>(realloc(dest, n));
177 throw std::runtime_error(
"m_pxmldom is NULL");
179 epicsGuard<epicsMutex> _lock(
m_lock);
180 std::map<std::string,std::string>::const_iterator it =
m_xpath_map.find(xpath);
185 IXMLDOMNode *pNode = NULL;
187 BSTR bstrValue = NULL;
188 HRESULT hr =
m_pxmldom->selectSingleNode(_bstr_t(xpath.c_str()), &pNode);
189 if (SUCCEEDED(hr) && pNode != NULL)
191 hr=pNode->get_text(&bstrValue);
195 SysFreeString(bstrValue);
211 throw std::runtime_error(
"m_pxmldom is NULL");
213 epicsGuard<epicsMutex> _lock(
m_lock);
214 std::map<std::string,bool>::const_iterator it =
m_xpath_bool_map.find(xpath);
219 IXMLDOMNode *pNode = NULL;
221 BSTR bstrValue = NULL;
222 std::string bool_str;
223 HRESULT hr =
m_pxmldom->selectSingleNode(_bstr_t(xpath.c_str()), &pNode);
224 if (SUCCEEDED(hr) && pNode != NULL)
226 hr=pNode->get_text(&bstrValue);
230 if (bool_str.size() == 0)
236 else if ( (bool_str[0] ==
't') || (bool_str[0] ==
'T') || (bool_str[0] ==
'y') || (bool_str[0] ==
'Y') || (atol(bool_str.c_str()) != 0) )
244 SysFreeString(bstrValue);
258 std::string lvDCOMInterface::doXPATH_old(
const std::string& xpath)
262 throw std::runtime_error(
"m_cfg is NULL");
264 std::map<std::string,std::string>::const_iterator it =
m_xpath_map.find(xpath);
270 TinyXPath::xpath_processor xp_proc(m_root, xpath.c_str());
272 std::string S_res = xp_proc.S_compute_xpath().c_str();
278 bool lvDCOMInterface::doXPATHbool_old(
const std::string& xpath)
282 throw std::runtime_error(
"m_cfg is NULL");
284 std::map<std::string,bool>::const_iterator it =
m_xpath_bool_map.find(xpath);
290 TinyXPath::xpath_processor xp_proc(m_root, xpath.c_str());
291 bool res = xp_proc.o_compute_xpath();
301 std::string S_res =
doXPATH(xpath);
302 std::replace(S_res.begin(), S_res.end(),
'/',
'\\');
309 HRESULT hr=CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_SERVER,
310 IID_IXMLDOMDocument2, (
void**)&
m_pxmldom);
313 throw std::runtime_error(
"Cannot load DomFromCom");
318 m_pxmldom->put_validateOnParse(VARIANT_FALSE);
319 m_pxmldom->put_resolveExternals(VARIANT_FALSE);
323 throw std::runtime_error(
"Cannot load DomFromCom");
335 lvDCOMInterface::lvDCOMInterface(
const char *configSection,
const char* configFile,
const char* host,
int options,
const char* progid,
const char* username,
const char* password) :
336 m_configSection(configSection), m_pidentity(NULL), m_pxmldom(NULL), m_options(options),
337 m_progid(progid != NULL? progid :
""), m_username(username != NULL? username :
""), m_password(password != NULL ? password :
""),
342 if (host != NULL && host[0] !=
'\0')
360 if (macCreateHandle(&
m_mac_env, NULL) != 0)
362 throw std::runtime_error(
"Cannot create mac handle");
367 for(
char** cp = environ; *cp != NULL; ++cp)
369 char* str_tmp = strdup(*cp);
370 char* equals_loc = strchr(str_tmp,
'=');
371 if (equals_loc != NULL)
374 macPutValue(
m_mac_env, str_tmp, equals_loc + 1);
386 if (configFile != NULL && *configFile !=
'\0')
389 short sResult = FALSE;
390 char* configFile_expanded =
envExpand(configFile);
392 HRESULT hr =
m_pxmldom->load(_variant_t(configFile_expanded), &sResult);
393 free(configFile_expanded);
396 throw std::runtime_error(
"Cannot load XML \"" +
m_configFile +
"\" (expanded from \"" + std::string(configFile) +
"\"): load failure");
398 if (sResult != VARIANT_TRUE)
400 throw std::runtime_error(
"Cannot load XML \"" +
m_configFile +
"\" (expanded from \"" + std::string(configFile) +
"\"): load failure");
402 std::cerr <<
"Loaded XML config file \"" <<
m_configFile <<
"\" (expanded from \"" << configFile <<
"\")" << std::endl;
410 throw std::runtime_error(
"Cannot find progId " +
m_progid);
416 wchar_t* progid_str = NULL;
417 if ( ProgIDFromCLSID(
m_clsid, &progid_str) == S_OK )
420 CoTaskMemFree(progid_str);
427 wchar_t* clsid_str = NULL;
428 if ( StringFromCLSID(
m_clsid, &clsid_str) == S_OK )
430 std::cerr <<
"Using ProgID \"" <<
m_progid <<
"\" CLSID " << CW2CT(clsid_str) << std::endl;
431 CoTaskMemFree(clsid_str);
435 std::cerr <<
"Using ProgID \"" <<
m_progid <<
"\" but StringFromCLSID() failed" << std::endl;
466 errlogSevPrintf(errlogMinor,
"LabVIEW not currently running - waiting for LabVIEW uptime of %.1f seconds...\n",
m_minLVUptime);
469 epicsThreadSleep(5.0);
477 CComBSTR vi_name(
"c:\\LabVIEW Modules\\dae\\monitor\\dae_monitor.vi");
478 CComBSTR control_name(
"Parameter details");
484 epicsThreadSleep(5.0);
487 if ( v.vt != (VT_ARRAY | VT_BSTR) )
489 throw std::runtime_error(
"GetBlockDetails failed (type mismatch)");
493 CComSafeArray<BSTR> sa;
495 if (sa.GetDimensions() == 2)
504 for(
int i=0; i<nr; ++i)
507 values[i].reserve(nc);
508 for(
int j=0; j<nc; ++j)
511 LONG dims[2] = { i, j };
512 if (sa.MultiDimGetAt(dims, t) == S_OK)
514 values[i].push_back(static_cast<const char*>(CW2CT(t)));
522 }
while ( (nr * nc) == 0 || (nr * nc) != n || values[0][0].size() == 0 );
531 std::vector< std::vector<std::string> > values;
540 errlogSevPrintf(errlogInfo,
"LabVIEW has been running for %.1f seconds\n", lvuptime);
541 std::cerr <<
"Waiting for block details to appear in dae_monitor.vi ..." << std::endl;
544 std::cerr <<
"Found " << nr <<
" potential SECI blocks" << std::endl;
547 macParseDefns(
m_mac_env, macros, &pairs);
550 std::fstream fs, fsdb;
551 fs.open(configFile, std::ios::out);
552 fsdb.open(dbSubFile, std::ios::out);
553 fs <<
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
554 fs <<
"<lvinput xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://epics.isis.rl.ac.uk/lvDCOMinput/1.0\" xsi:schemaLocation=\"http://epics.isis.rl.ac.uk/lvDCOMinput/1.0 lvDCOMinput.xsd\">\n";
557 fs <<
" <extint path=\"c:/labview modules/Common/External Interface/External Interface.llb/External Interface - Set Value.vi\"/>\n";
558 fs <<
" <section name=\"" << configSection <<
"\">\n";
559 if (blocks_match == NULL || *blocks_match ==
'\0')
565 for(
int i=0; i<nr; ++i)
567 std::string rsuffix, ssuffix, pv_type;
572 std::cerr <<
"Processing block \"" << name <<
"\"" << std::endl;
577 std::cerr <<
"Skipping block \"" << name <<
"\" as not matched by regular expression" << std::endl;
580 std::string read_type(
"unknown"), set_type(
"unknown");
589 std::replace(vi_path.begin(), vi_path.end(),
'\\',
'/');
591 if (set_type !=
"unknown")
593 fs <<
" <param name=\"" << name <<
"_set\" type=\"" << set_type <<
"\">\n";
606 if (read_type !=
"unknown")
608 fs <<
" <param name=\"" << name <<
"_read\" type=\"" << read_type <<
"\">\n";
613 if (ssuffix.size() == 0)
622 if (rsuffix.size() > 0 && ssuffix.size() > 0)
624 fsdb <<
"file \"${LVDCOM}/db/lvDCOM_" << pv_type <<
".template\" {\n";
625 fsdb <<
" { P=\"" <<
envExpand(
"$(P=)") <<
"\",PORT=\"" << portName <<
"\",SCAN=\""
626 <<
envExpand(
"$(SCAN=1 second)") <<
"\",PARAM=\"" << name
627 <<
"\",NOSET=\"" << (no_setter ?
"#" :
" ")
628 <<
"\",RPARAM=\"" << name << rsuffix <<
"\",SPARAM=\"" << name << ssuffix <<
"\" }\n";
633 std::cerr <<
"Skipping DB for block \"" << name <<
"\" (unknown type)" << std::endl;
637 fs <<
" </section>\n";
638 fs <<
"</lvinput>\n";
647 for(vi_map_t::const_iterator it =
m_vimap.begin(); it !=
m_vimap.end(); ++it)
649 LabVIEW::VirtualInstrumentPtr vi_ref = it->second.vi_ref;
650 if ( (!only_ones_we_started || it->second.started) && (vi_ref != NULL) )
654 std::cerr <<
"stopping \"" << CW2CT(it->first.c_str()) <<
"\" as it was auto-started and is still running" << std::endl;
659 catch(
const std::exception& ex)
661 std::cerr <<
"error stopping vi: " << ex.what() << std::endl;
665 std::cerr <<
"error stopping vi: unknown" << std::endl;
676 _snprintf(control_name_xpath,
sizeof(control_name_xpath),
"/lvinput/section[@name='%s']/vi/param",
m_configSection.c_str());
677 IXMLDOMNodeList* pXMLDomNodeList = NULL;
678 HRESULT hr =
m_pxmldom->selectNodes(_bstr_t(control_name_xpath), &pXMLDomNodeList);
679 if (SUCCEEDED(hr) && pXMLDomNodeList != NULL)
681 pXMLDomNodeList->get_length(&n);
682 pXMLDomNodeList->Release();
691 _snprintf(control_name_xpath,
sizeof(control_name_xpath),
"/lvinput/section[@name='%s']/vi/param",
m_configSection.c_str());
692 IXMLDOMNodeList* pXMLDomNodeList = NULL;
693 HRESULT hr =
m_pxmldom->selectNodes(_bstr_t(control_name_xpath), &pXMLDomNodeList);
694 if (FAILED(hr) || pXMLDomNodeList == NULL)
698 IXMLDOMNode *pNode, *pAttrNode1, *pAttrNode2;
700 pXMLDomNodeList->get_length(&n);
701 for(
long i=0; i<n; ++i)
704 hr = pXMLDomNodeList->get_item(i, &pNode);
705 if (SUCCEEDED(hr) && pNode != NULL)
707 IXMLDOMNamedNodeMap *attributeMap = NULL;
708 pAttrNode1 = pAttrNode2 = NULL;
709 pNode->get_attributes(&attributeMap);
710 hr = attributeMap->getNamedItem(_bstr_t(
"name"), &pAttrNode1);
711 hr = attributeMap->getNamedItem(_bstr_t(
"type"), &pAttrNode2);
712 BSTR bstrValue1 = NULL, bstrValue2 = NULL;
713 hr=pAttrNode1->get_text(&bstrValue1);
714 hr=pAttrNode2->get_text(&bstrValue2);
715 res[std::string(COLE2CT(bstrValue1))] = COLE2CT(bstrValue2);
716 SysFreeString(bstrValue1);
717 SysFreeString(bstrValue2);
718 pAttrNode1->Release();
719 pAttrNode2->Release();
720 attributeMap->Release();
724 pXMLDomNodeList->Release();
729 if (user.size() == 0)
733 COAUTHIDENTITY* pidentity =
new COAUTHIDENTITY;
734 pidentity->Domain = (USHORT*)strdup(domain.c_str());
735 pidentity->DomainLength =
static_cast<ULONG
>(strlen((
const char*)pidentity->Domain));
736 pidentity->Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
737 pidentity->Password = (USHORT*)strdup(pass.c_str());
738 pidentity->PasswordLength =
static_cast<ULONG
>(strlen((
const char*)pidentity->Password));
739 pidentity->User = (USHORT*)strdup(user.c_str());
740 pidentity->UserLength =
static_cast<ULONG
>(strlen((
const char*)pidentity->User));
747 if (pidentity != NULL)
749 hr = CoSetProxyBlanket(pUnk, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
750 RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, pidentity, EOAC_NONE);
753 std::cerr <<
"setIdentity failed" << std::endl;
763 UINT len = SysStringLen(vi_name);
764 std::wstring ws(vi_name, SysStringLen(vi_name));
766 epicsGuard<epicsMutex> _lock(
m_lock);
767 vi_map_t::iterator it =
m_vimap.find(ws);
770 vi = it->second.vi_ref;
791 double lvUptime = -1.0;
794 FILETIME lvCreationTime, lvExitTime, lvKernelTime, lvUserTime, sysTime;
795 epicsGuard<epicsMutex> _lock(
m_lock);
796 HANDLE hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
797 if( hProcessSnap == INVALID_HANDLE_VALUE )
801 pe32.dwSize =
sizeof( PROCESSENTRY32 );
802 if( !Process32First( hProcessSnap, &pe32 ) )
804 CloseHandle( hProcessSnap );
809 if ( !stricmp(pe32.szExeFile,
"LabVIEW.exe") )
812 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pe32.th32ProcessID);
813 if( hProcess != NULL )
815 if (GetProcessTimes(hProcess, &lvCreationTime, &lvExitTime, &lvKernelTime, &lvUserTime) != 0)
817 GetSystemTimeAsFileTime(&sysTime);
820 CloseHandle( hProcess );
823 }
while( Process32Next( hProcessSnap, &pe32 ) );
824 CloseHandle( hProcessSnap );
832 ULARGE_INTEGER u1, u2;
833 u1.LowPart = f1.dwLowDateTime;
834 u1.HighPart = f1.dwHighDateTime;
835 u2.LowPart = f2.dwLowDateTime;
836 u2.HighPart = f2.dwHighDateTime;
837 return static_cast<double>(u1.QuadPart - u2.QuadPart) / 1e7;
849 std::cerr <<
"Terminating as in SECI mode and no LabVIEW" << std::endl;
865 std::wstring ws(vi_name, SysStringLen(vi_name));
873 hr =
m_lv->CheckConnection();
875 catch(
const std::exception&)
881 epicsThreadSleep(5.0);
889 else if (
m_host.size() > 0)
891 std::cerr <<
"(Re)Making connection to LabVIEW on " <<
m_host << std::endl;
892 CComBSTR host(
m_host.c_str());
894 COAUTHINFO* pauth =
new COAUTHINFO;
895 COSERVERINFO csi = { 0, NULL, NULL, 0 };
896 pauth->dwAuthnSvc = RPC_C_AUTHN_WINNT;
897 pauth->dwAuthnLevel = RPC_C_AUTHN_LEVEL_DEFAULT;
898 pauth->dwAuthzSvc = RPC_C_AUTHZ_NONE;
899 pauth->dwCapabilities = EOAC_NONE;
900 pauth->dwImpersonationLevel = RPC_C_IMP_LEVEL_IMPERSONATE;
902 pauth->pwszServerPrincName = NULL;
904 csi.pAuthInfo = pauth;
905 MULTI_QI mq[ 1 ] = { 0 };
906 mq[ 0 ].pIID = &IID_IDispatch;
909 hr = CoCreateInstanceEx(
m_clsid, NULL, CLSCTX_REMOTE_SERVER | CLSCTX_LOCAL_SERVER, &csi, 1, mq );
912 hr = CoCreateInstanceEx(
m_clsid, NULL, CLSCTX_ALL, &csi, 1, mq );
916 throw COMexception(
"CoCreateInstanceEx (LabVIEW) ", hr);
918 if( S_OK != mq[ 0 ].hr || NULL == mq[ 0 ].pItf )
920 throw COMexception(
"CoCreateInstanceEx (LabVIEW)(mq) ", mq[ 0 ].hr);
924 m_lv.Attach( reinterpret_cast< LabVIEW::_Application* >( mq[ 0 ].pItf ) );
925 std::cerr <<
"Successfully connected to LabVIEW on " <<
m_host << std::endl;
929 std::cerr <<
"(Re)Making local connection to LabVIEW" << std::endl;
932 hr =
m_lv.CoCreateInstance(
m_clsid, NULL, CLSCTX_LOCAL_SERVER);
937 std::cerr <<
"Successfully connected to local LabVIEW" << std::endl;
941 vi =
m_lv->GetVIReference(vi_name,
"", 1, 8);
947 vi =
m_lv->GetVIReference(vi_name,
"", 0, 0);
951 vi =
m_lv->GetVIReference(vi_name,
"", 1, 8);
956 ViRef viref(vi, reentrant,
false);
963 std::cerr <<
"Starting \"" << CW2CT(vi_name) <<
"\" on " << (
m_host.size() > 0 ?
m_host :
"localhost") << std::endl;
969 std::cerr <<
"\"" << CW2CT(vi_name) <<
"\" is not running on " << (
m_host.size() > 0 ?
m_host :
"localhost") <<
" and autostart is disabled" << std::endl;
981 throw std::runtime_error(
"getLabviewValue failed (NULL)");
983 if (param == NULL || *param ==
'\0')
985 throw std::runtime_error(
"getLabviewValue: param is NULL");
989 _snprintf(vi_name_xpath,
sizeof(vi_name_xpath),
"/lvinput/section[@name='%s']/vi[param[@name='%s']]/@path",
m_configSection.c_str(), param);
990 _snprintf(control_name_xpath,
sizeof(control_name_xpath),
"/lvinput/section[@name='%s']/vi/param[@name='%s']/read/@target",
m_configSection.c_str(), param);
991 CComBSTR vi_name(
doPath(vi_name_xpath).c_str());
992 CComBSTR control_name(
doXPATH(control_name_xpath).c_str());
993 if (vi_name.Length() == 0 || control_name.Length() == 0)
995 throw std::runtime_error(
"getLabviewValue: vi or control is NULL");
998 if ( v.ChangeType(VT_BSTR) == S_OK )
1000 *value = CW2CT(v.bstrVal);
1004 throw std::runtime_error(
"getLabviewValue failed (ChangeType BSTR)");
1008 template<
typename T>
1013 throw std::runtime_error(
"getLabviewValue failed (NULL)");
1015 if (param == NULL || *param ==
'\0')
1017 throw std::runtime_error(
"getLabviewValue: param is NULL");
1021 _snprintf(vi_name_xpath,
sizeof(vi_name_xpath),
"/lvinput/section[@name='%s']/vi[param[@name='%s']]/@path",
m_configSection.c_str(), param);
1022 _snprintf(control_name_xpath,
sizeof(control_name_xpath),
"/lvinput/section[@name='%s']/vi/param[@name='%s']/read/@target",
m_configSection.c_str(), param);
1023 CComBSTR vi_name(
doPath(vi_name_xpath).c_str());
1024 CComBSTR control_name(
doXPATH(control_name_xpath).c_str());
1025 if (vi_name.Length() == 0 || control_name.Length() == 0)
1027 throw std::runtime_error(
"getLabviewValue: vi or control is NULL");
1030 if ( v.vt != (VT_ARRAY | CVarTypeInfo<T>::VT) )
1032 throw std::runtime_error(
"getLabviewValue failed (type mismatch)");
1034 CComSafeArray<T> sa;
1035 sa.Attach(v.parray);
1036 nIn = ( sa.GetCount() > nElements ? nElements : sa.GetCount() );
1037 for(LONG i=0; i<nIn; ++i)
1039 value[i] = sa.GetAt(i);
1044 template <
typename T>
1049 throw std::runtime_error(
"getLabviewValue failed (NULL)");
1051 if (param == NULL || *param ==
'\0')
1053 throw std::runtime_error(
"getLabviewValue: param is NULL");
1057 _snprintf(vi_name_xpath,
sizeof(vi_name_xpath),
"/lvinput/section[@name='%s']/vi[param[@name='%s']]/@path",
m_configSection.c_str(), param);
1058 _snprintf(control_name_xpath,
sizeof(control_name_xpath),
"/lvinput/section[@name='%s']/vi/param[@name='%s']/read/@target",
m_configSection.c_str(), param);
1059 CComBSTR vi_name(
doPath(vi_name_xpath).c_str());
1060 CComBSTR control_name(
doXPATH(control_name_xpath).c_str());
1061 if (vi_name.Length() == 0 || control_name.Length() == 0)
1063 throw std::runtime_error(
"getLabviewValue: vi or control is NULL");
1066 if ( v.ChangeType(CVarTypeInfo<T>::VT) == S_OK )
1068 *value = v.*(CVarTypeInfo<T>::pmField);
1072 throw std::runtime_error(
"getLabviewValue failed (ChangeType)");
1079 LabVIEW::VirtualInstrumentPtr vi;
1081 *value = vi->GetControlValue(control_name).Detach();
1085 throw std::runtime_error(
"getLabviewValue failed");
1098 catch (
const std::exception& ex)
1100 std::cerr <<
"getLabviewValueType: Unable to read \"" << COLE2CT(control_name) <<
"\" on \"" << COLE2CT(vi_name) <<
"\": " << ex.what() << std::endl;
1103 VARTYPE vt = (&v)->vt;
1125 if ( v.ChangeType(VT_R8) == S_OK )
1142 _snprintf(base_xpath,
sizeof(base_xpath), xpath, config_section, param);
1164 _snprintf(base_xpath,
sizeof(base_xpath), xpath, config_section, param);
1173 CComVariant v(value.c_str()), results, button_value(
true);
1174 if (param == NULL || *param ==
'\0')
1176 throw std::runtime_error(
"setLabviewValue: param is NULL");
1179 StringItem control_name(
this,
"/lvinput/section[@name='%s']/vi/param[@name='%s']/set/@target",
m_configSection.c_str(), param);
1180 StringItem post_button(
this,
"/lvinput/section[@name='%s']/vi/param[@name='%s']/set/@post_button",
m_configSection.c_str(), param);
1181 BoolItem post_button_wait(
this,
"/lvinput/section[@name='%s']/vi/param[@name='%s']/set/@post_button_wait",
m_configSection.c_str(), param);
1182 BoolItem use_ext(
this,
"/lvinput/section[@name='%s']/vi/param[@name='%s']/set/@extint",
m_configSection.c_str(), param);
1183 if (vi_name.size() == 0 || control_name.size() == 0)
1185 throw std::runtime_error(
"setLabviewValue: vi or control is NULL");
1190 if (post_button.size() > 0)
1198 if (post_button.size() > 0)
1203 if (post_button_wait && (post_button.size() > 0) )
1216 if ( v.ChangeType(VT_BOOL) == S_OK )
1218 done = ( v.boolVal == (value ? VARIANT_TRUE : VARIANT_FALSE) );
1221 epicsThreadSleep(0.1);
1225 template <
typename T>
1228 CComVariant v(value), results, button_value(
true);
1229 if (param == NULL || *param ==
'\0')
1231 throw std::runtime_error(
"setLabviewValue: param is NULL");
1234 StringItem control_name(
this,
"/lvinput/section[@name='%s']/vi/param[@name='%s']/set/@target",
m_configSection.c_str(), param);
1235 StringItem post_button(
this,
"/lvinput/section[@name='%s']/vi/param[@name='%s']/set/@post_button",
m_configSection.c_str(), param);
1236 BoolItem post_button_wait(
this,
"/lvinput/section[@name='%s']/vi/param[@name='%s']/set/@post_button_wait",
m_configSection.c_str(), param);
1237 BoolItem use_ext(
this,
"/lvinput/section[@name='%s']/vi/param[@name='%s']/set/@extint",
m_configSection.c_str(), param);
1238 if (vi_name.size() == 0 || control_name.size() == 0)
1240 throw std::runtime_error(
"setLabviewValue: vi or control is NULL");
1245 if (post_button.size() > 0)
1253 if (post_button.size() > 0)
1258 if (post_button_wait && (post_button.size() > 0) )
1267 LabVIEW::VirtualInstrumentPtr vi;
1269 hr = vi->SetControlValue(control_name, value);
1273 throw std::runtime_error(
"SetLabviewValue failed");
1280 CComSafeArray<BSTR> names(6);
1281 names[0].AssignBSTR(_bstr_t(L
"VI Name"));
1282 names[1].AssignBSTR(_bstr_t(L
"Control Name"));
1283 names[2].AssignBSTR(_bstr_t(L
"String Control Value"));
1284 names[3].AssignBSTR(_bstr_t(L
"Variant Control Value"));
1285 names[4].AssignBSTR(_bstr_t(L
"Machine Name"));
1286 names[5].AssignBSTR(_bstr_t(L
"Return Message"));
1289 n.vt = VT_ARRAY | VT_BSTR;
1290 n.parray = names.Detach();
1292 CComSafeArray<VARIANT> values(6);
1293 values[0] = vi_name;
1294 values[1] = control_name;
1301 v.vt = VT_ARRAY | VT_VARIANT;
1302 v.parray = values.Detach();
1310 LabVIEW::VirtualInstrumentPtr vi;
1319 hr = vi->Call(&names, &values);
1321 CComVariant var(values);
1322 var.Detach(results);
1325 throw std::runtime_error(
"CallLabviewValue failed");
1332 fprintf(fp,
"XML ConfigFile: \"%s\"\n",
m_configFile.c_str());
1333 fprintf(fp,
"XML ConfigFile section: \"%s\"\n",
m_configSection.c_str());
1334 fprintf(fp,
"lvDCOMConfigure() Options: %d\n",
m_options);
1335 fprintf(fp,
"DCOM Target ProgID: \"%s\"\n",
m_progid.c_str());
1336 fprintf(fp,
"DCOM Target Host: \"%s\"\n",
m_host.c_str());
1337 fprintf(fp,
"DCOM Target Username: \"%s\"\n",
m_username.c_str());
1339 std::string vi_name;
1340 for(vi_map_t::const_iterator it =
m_vimap.begin(); it !=
m_vimap.end(); ++it)
1342 vi_name = CW2CT(it->first.c_str());
1343 fprintf(fp,
"LabVIEW VI: \"%s\"\n", vi_name.c_str());
1347 for(std::map<std::string,std::string>::const_iterator it =
m_xpath_map.begin(); it !=
m_xpath_map.end(); ++it)
1349 fprintf(fp,
"Config XPath: \"%s\" = \"%s\"\n", it->first.c_str(), it->second.c_str());
1353 fprintf(fp,
"Config XPath: \"%s\" = %s\n", it->first.c_str(), (it->second ?
"true" :
"false") );
1363 #ifndef DOXYGEN_SHOULD_SKIP_THIS
static void initCOM(void *)
create an C++ exception from a COM HRESULT.
static std::string replaceWithEntities(const std::string &str)
COAUTHIDENTITY * m_pidentity
std::string m_configSection
section of configFile to load information from
(4) On IOC exit, stop any LabVIEW VIs that we started due to viStartIfIdle being specified ...
CComPtr< LabVIEW::_Application > m_lv
BoolItem(lvDCOMInterface *dcom, const char *xpath, const char *config_section, const char *param)
bool FullMatch(const char *)
bool checkForNewBlockDetails()
Header file for various COM utilities.
bool started
did we start this vi because it was idle and viStartIfIdle was specified
void waitForLabviewBoolean(BSTR vi_name, BSTR control_name, bool value)
static void __stdcall my_com_raise_error(HRESULT hr, IErrorInfo *perrinfo)
The Microsoft ATL _com_error is not derived from std::exception hence this bit of code to throw our o...
(8) On IOC exit, stop any LabVIEW VIs that we have connected to
std::string doPath(const std::string &xpath)
IXMLDOMDocument2 * m_pxmldom
void callLabview(BSTR vi_name, VARIANT &names, VARIANT &values, VARIANT_BOOL reentrant, VARIANT *results)
static std::vector< std::vector< std::string > > m_seci_values
horrible - do properly some time
void report(FILE *fp, int details)
Helper for EPICS driver report function.
(16) Do not start LabVIEW, connect to existing instance otherwise fail. As loading a Vi starts labvie...
header for lvDCOMInterface class.
double waitForLabVIEW()
wait for LabVIEW to have been running for m_minLVUptime seconds
int m_options
the various lvDCOMOptions currently in use
std::map< std::string, bool > m_xpath_bool_map
void getParams(std::map< std::string, std::string > &res)
(32) Automatically set if lvDCOMSECIConfigure() has been used
std::string doXPATH(const std::string &xpath)
std::map< std::string, std::string > m_xpath_map
void getBlockDetails(std::vector< std::vector< std::string > > &values)
double getLabviewUptime()
returns -1.0 if labview not running, else labview uptime in seconds
static void epicsExitFunc(void *arg)
void stopVis(bool only_ones_we_started)
int generateFilesFromSECI(const char *portName, const char *macros, const char *configSection, const char *configFile, const char *dbSubFile, const char *blocks_match, bool no_setter)
generate XML and DB files for SECI blocks
void maybeWaitForLabVIEWOrExit()
static double m_minLVUptime
minimum time labview must be running before connection made in "lvNoStart" mode
Manager class for LabVIEW DCOM Interaction. Parses an lvinput.xml file and provides access to the Lab...
void setLabviewValue(const char *param, const T &value)
HRESULT setIdentity(COAUTHIDENTITY *pidentity, IUnknown *pUnk)
(1) If the LabVIEW VI is idle when we connect to it, issue a warning message
Hold a reference to a LabVIEW VI.
void getLabviewValue(const char *param, T *value)
bool GlobalReplace(const std::string, std::string *)
std::string getLabviewValueType(BSTR vi_name, BSTR control_name)
determine best epics type for a labvier variable, this will be used to choose the appropriate EPICS r...
(2) If the LabVIEW VI is idle when we connect to it, attempt to start it
static double diffFileTimes(const FILETIME &f1, const FILETIME &f2)
filetime uses 100ns units, returns difference in seconds
static epicsThreadOnceId onceId
COAUTHIDENTITY * createIdentity(const std::string &user, const std::string &domain, const std::string &pass)
bool checkOption(lvDCOMOptions option)
void createViRef(BSTR vi_name, bool reentrant, LabVIEW::VirtualInstrumentPtr &vi)
void setLabviewValueExt(BSTR vi_name, BSTR control_name, const VARIANT &value, VARIANT *results)
char * envExpand(const char *str)
expand epics environment strings using previously saved environment based on EPICS macEnvExpand() ...
bool doXPATHbool(const std::string &xpath)
lvDCOMInterface(const char *configSection, const char *configFile, const char *host, int options, const char *progid, const char *username, const char *password)
section name of configFile we will load settings from
void getViRef(BSTR vi_name, bool reentrant, LabVIEW::VirtualInstrumentPtr &vi)
StringItem(lvDCOMInterface *dcom, const char *xpath, const char *config_section, const char *param, bool filepath=false)
const GUID CLSID_Application