c++ 读取修改xml文件,程序控制其他软件的打开关闭
继续这个软件开发,接收到指令后启动、关闭或者部署软件。
关闭软件,我这里是执行一个批处理文件,
void OnStop() { char* killPath = "softwarePath"; ShellExecute(NULL, "open", _T("softwareName.bat"), NULL, killPath, SW_SHOWNA); printf("kill all. err code:%d\n", GetLastError()); }
打开软件,根据需要,先改几个xml配置文件,再创建几个进程,再执行一个批处理文件。
读取xml文件获取进程列表,将列表中每个进程名称取出来, XML 解析器之一 :MSXML使用教程(转)_mannhello的博客-CSDN博客_msxml.h
还不能修改xml内容,另外发现读到的进程名称有的不带后缀名,没有后缀的名称启动进程不成功,还得加后缀名。。
头文件#include <msxml6.h>
void CommandRespond::getProcessList(std::string name, std::string value) { // const char* 转 char* char *tmpStr, *token, *strc = const_cast<char*>(value.c_str()); std::vector<std::string> resVec; // 分解字符串 token = strtok_s(strc, "/", &tmpStr); while (token) { std::string tokenStr = token; tokenStr.erase(tokenStr.find_last_not_of(" .") + 1); if (tokenStr.size() > 0) { // 查看文件名是否包含exe后缀 std::string::size_type idx = tokenStr.find("."); if (idx == std::string::npos) tokenStr = tokenStr + ".exe"; resVec.push_back(tokenStr); } token = strtok_s(NULL, "/", &tmpStr); } m_ProcessMap[name] = resVec; } //读取xml文件 void CommandRespond::readXml(OLECHAR* xmlFileName, OLECHAR* queryStr, OLECHAR* attributeName) { IXMLDOMDocument2 *pXmlDoc = NULL; VARIANT vSrc; VARIANT_BOOL status; IXMLDOMParseError *pObjError = NULL; BSTR bstr = NULL, BStr, BStrValue; IXMLDOMNodeList *pNodeList = NULL; long Length, I; IXMLDOMNode *Node, *IDNode; IXMLDOMNamedNodeMap *NodeMap; CoInitialize(NULL); HRESULT hr = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, __uuidof(IXMLDOMDocument2), (void**)&pXmlDoc); if (FAILED(hr)) printf("failed to CoCreate an instance of an XML DOM. err code: %d", hr); hr = pXmlDoc->put_async(VARIANT_FALSE); //加载方式不为“同步” if (FAILED(hr)) printf("failed to set async property. err code: %d", hr); hr = pXmlDoc->put_validateOnParse(VARIANT_FALSE); //文档结构有错误时,停止解析 if (FAILED(hr)) printf("failed to set validateOnParse. err code: %d", hr); hr = pXmlDoc->put_resolveExternals(VARIANT_FALSE); if (FAILED(hr)) printf("failed to disable resolving externals. err code: %d", hr); VariantInit(&vSrc); V_BSTR(&vSrc) = SysAllocString(xmlFileName); V_VT(&vSrc) = VT_BSTR; hr = pXmlDoc->load(vSrc, &status); if (status != VARIANT_TRUE) { hr = pXmlDoc->get_parseError(&pObjError); hr = pObjError->get_reason(&bstr); printf("failed to load DOM from xml. err code: %S", bstr); } if (bstr) SysFreeString(bstr); if (&vSrc) VariantClear(&vSrc); //清理一个VARIANT对象 if (pObjError) pObjError->Release(); if (pXmlDoc == NULL) printf("loadXML ProcessControllerConfig.xml failed. err code: %d", GetLastError()); if (pXmlDoc->selectNodes(queryStr, &pNodeList) != S_OK) printf("no nodes like //Application. err code: %d", GetLastError()); hr = pNodeList->get_length(&Length); if (FAILED(hr)) printf("no length. err code: %d", hr); for (I = 0; I < Length; I++) { if (pNodeList->get_item(I, &Node) == S_OK) { char IDBuffer[512]; char Buffer[1024]; if (Node->get_attributes(&NodeMap) == S_OK) { if (NodeMap->getNamedItem(attributeName, &IDNode) == S_OK) { if (IDNode->get_text(&BStrValue) == S_OK) { WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, BStrValue, -1, IDBuffer, sizeof(IDBuffer), NULL, NULL); puts(IDBuffer); puts(""); SysFreeString(BStrValue); } IDNode->Release(); } NodeMap->Release(); } if (Node->get_text(&BStr) == S_OK) { WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, BStr, -1, Buffer, sizeof(Buffer), NULL, NULL); puts(Buffer); } getProcessList(IDBuffer, Buffer); SysFreeString(BStr); Node->Release(); } } pXmlDoc->Release(); CoUninitialize(); }
创建进程,C++ 创建进程的方法 - 积跬步---行千里 - 博客园 (cnblogs.com)
void CommandRespond::OnStart() { char* filePath = "D:/"; // Process.xml OLECHAR* xmlFileName = L"D:/Process.xml"; OLECHAR* queryStr = L"//Application/Process/Mode"; OLECHAR* attributeName = L"ID";// 取到xml readXml(xmlFileName, queryStr, attributeName); std::string runName = "Stand"; std::map<std::string, std::vector<std::string> >::iterator iter; iter = m_ProcessMap.find(runName); std::vector<std::string> proList = iter->second; for (int i=0; i<proList.size(); i++) { std::string dirPath = "D:/"; dirPath = dirPath + proList[i]; LPCSTR PATH = dirPath.c_str(); // 创建进程 STARTUPINFO startupInfo = { 0 }; PROCESS_INFORMATION processInformation = { 0 }; BOOL bSuc = CreateProcess(PATH, NULL, NULL, NULL, FALSE, NULL, NULL, filePath, &startupInfo, &processInformation); //TEXT("D:/MAXSim7.1.1/Applications/SSGProduct/bin/x64/release/BalloonMotion.exe") if (bSuc) printf("process started. processID:%d", processInformation.dwProcessId); else printf("process started failed. err code: %d", GetLastError()); } // 执行启动的批处理软件 ShellExecute(NULL, "open", _T("Process.bat"), NULL, filePath, SW_SHOWNA); }
为了查看怎么修改xml内容,又发现了这篇文章C++ DOM读写xml(msxml6)_gdizcm的博客-CSDN博客_c++ dom
然后重新写了读取xml的方法,并实现了修改内容,根据自己的业务需要将读和改都写进去了,代码更短些。
加头文件
#include <atlbase.h>
#pragma comment(lib, "msxml6.lib")
另外把#include<windows.h>写进了#include "stdafx.h"文件里
void CommandRespond::readXml(LPCSTR filenName, BSTR queryStr, BSTR attriName, BSTR attriValue, BOOL UPDATEMARK) { CoInitialize(NULL); CComPtr<IXMLDOMDocument> spXmldoc; HRESULT hr = spXmldoc.CoCreateInstance(CLSID_DOMDocument60); if (SUCCEEDED(hr)) { VARIANT_BOOL isSuccessful; spXmldoc->load(CComVariant(filenName), &isSuccessful); if (VARIANT_TRUE == isSuccessful) { CComBSTR bstrXml; CComPtr<IXMLDOMElement> spRoot = NULL; CComPtr<IXMLDOMElement> spElement = NULL; hr = spXmldoc->get_documentElement(&spRoot); spRoot->get_xml(&bstrXml); if (hr == S_OK) { CComPtr<IXMLDOMNode> spNode; CComPtr<IXMLDOMNodeList> pNodeList = NULL; LONG length; // 通过xpath寻找节点 //hr = spRoot->selectSingleNode(L"/SSU/General", &spNode); hr = spRoot->selectNodes(queryStr, &pNodeList); hr = pNodeList->get_length(&length); if (hr == S_OK) { for (LONG i = 0; i < length; i++) { if (pNodeList->get_item(i, &spNode) == S_OK) { if (UPDATEMARK == TRUE) { spNode->get_xml(&bstrXml); //<General GBBConfig="BC31" Mission="Basic Demo5"/> spElement = spNode; CComVariant varID(attriValue); spElement->setAttribute(attriName, varID); //spElement->setAttribute(L"ID", varID); spXmldoc->save(CComVariant(filenName));
VariantClear(&varID); } else { char IDBuffer[512]; char Buffer[1024]; spElement = spNode; CComVariant varID; hr = spElement->getAttribute(L"ID", &varID); //spRoot->get_xml(&bstrXml); WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, varID.bstrVal, -1, IDBuffer, sizeof(IDBuffer), NULL, NULL); hr = spNode->get_text(&bstrXml); WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, bstrXml, -1, Buffer, sizeof(Buffer), NULL, NULL); getProcessList(IDBuffer, Buffer);
VariantClear(&varID); } } } } spNode.Release();
pNodeList.Release(); }
SysFreeString(bstrXml);
spElement.Release();
spRoot.Release();
}
}
spXmldoc.Release();
CoUninitialize();
}
这样把onstart函数也改下就可以实现启动了!
void CommandRespond::OnStart(std::string missionName, int mode) { // 可能从ini文件读到的引擎配置文件目录 std::string path = "D:/"; //// 从指令获取 //std::string missionName = "test"; // 想定名称 //int mode = -1; // 运行模式mode: - 1:单机, - 2:回放, - 3:态势,0~n:分布式 node:“129.168.1.1” // 改 xxx.xml,设置想定名称 std::string ssuPath = path + "xxx.xml"; LPCSTR filenName = ssuPath.c_str(); BSTR queryStr = L"/xxx/xxxx"; BSTR attriName = L"xx"; BSTR attriValue = _com_util::ConvertStringToBSTR(missionName.c_str()); BOOL UPDATEMARK = TRUE; readXml(filenName, queryStr, attriName, attriValue, UPDATEMARK); // 改 xxxx.xml,设置运行模式 std::string sysPath = path + "xxxx.xml"; filenName = sysPath.c_str(); queryStr = L"/xxxx/xxxx"; attriName = L"xx"; if (mode == -1) attriValue = L"xx"; else if (mode == -2) attriValue = L"xxx"; else if (mode == -3) { }else if (mode >= 0) attriValue = L"xxxx"; UPDATEMARK = TRUE; readXml(filenName, queryStr, attriName, attriValue, UPDATEMARK); // 读 xxxxx.xml,获取进程列表存储 m_ProcessMap std::string processPath = path + "xxxxx.xml"; filenName = processPath.c_str(); queryStr = L"/xxxxx/xxxxx/xxxxx"; UPDATEMARK = FALSE; readXml(filenName, queryStr, attriName, attriValue, UPDATEMARK); //std::string runName = "StandAlone"; std::string runName = _com_util::ConvertBSTRToString(attriValue); std::map<std::string, std::vector<std::string> >::iterator iter; iter = m_ProcessMap.find(runName); std::vector<std::string> proList = iter->second; // 应用程序所在目录 char* filePath = "D:/"; for (int i = 0; i < proList.size(); i++) { std::string dirPath = "D:/"; dirPath = dirPath + proList[i]; LPCSTR PATH = dirPath.c_str(); // 创建进程 STARTUPINFO startupInfo = { 0 }; PROCESS_INFORMATION processInformation = { 0 }; BOOL bSuc = CreateProcess(PATH, NULL, NULL, NULL, FALSE, NULL, NULL, filePath, &startupInfo, &processInformation); //TEXT("D:/xxx.exe") if (!bSuc) //printf("process started. processID:%d", processInformation.dwProcessId); //else printf("process started failed. err code: %d", GetLastError()); } // 执行启动的批处理软件 bool a=ShellExecute(NULL, "open", _T("xxx.bat"), NULL, filePath, SW_SHOWNA); if (!a) printf("start xxx. err code:%d\n", GetLastError()); }