CCmd.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. #include "CCmd.h"
  2. #pragma region cmd指令说明
  3. // 【/k】:调用cmd进程时,必须调用此参数
  4. // // 【x:】:x为x盘符,cd到不同盘符下的文件夹路径之前,必须要要调用此参数,否则cd指令不生效;
  5. // 【cd xxx】:切换到指定的文件夹xxx路径
  6. // 【start/wait】:start启动进程,wait等待指令调用结束
  7. //【APPDIR】: 安装路径
  8. // 【qb】:cmd后台静默执行
  9. //【qn】:无安装界面运行,静默安装指令参数
  10. //【norestart】:安装后不启动App,默认为不启动(目前已经去掉该参数)
  11. //vba不支持带空格路径安装,即便用路径标识符也不行,例如%cd%
  12. #pragma endregion
  13. CCmd::CCmd()
  14. {
  15. }
  16. BOOL CCmd::Installcmd()
  17. {
  18. std::wstring cmd = L"";
  19. //防止目标路径与当前进程所在盘符不一致,所以在cd之前,要指定目标路径的盘符cdDisk
  20. auto cdDisk = PathCore::smPath_Install.substr(0, 1) + L": & ";
  21. cmd = L"/k " + cdDisk + L"cd \"" + PathCore::smPath_Install + L"\"" + L" & start/wait " + Product::smName_InstallPackage + L" APPDIR=\"" + PathCore::smPath_Install + L"\" /qb /qn";
  22. LogIni::GetLogToIni("Install cmd", cmd);
  23. TCHAR* tc = (TCHAR*)(&cmd[0]);
  24. return Executecmd(tc);
  25. }
  26. //环境检测,如果没有就安装NET Framework
  27. BOOL CCmd::InstallNetcmd()
  28. {
  29. wstring systemLetter = DiskCore::GetSystemDriveLetter();//获取系统盘符
  30. SYSTEM_INFO si;
  31. GetNativeSystemInfo(&si);//获取系统信息
  32. std::wstring netframe;
  33. bool isSystem64 = true;
  34. if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 ||
  35. si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64)
  36. {
  37. isSystem64 = true;
  38. }
  39. else
  40. {
  41. isSystem64 = false;
  42. }
  43. if (systemLetter == L"")
  44. {
  45. systemLetter = L"C";
  46. }
  47. //安装NET Framework工具所在路径是固定的
  48. if (isSystem64)
  49. {
  50. netframe = systemLetter + L":\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319";
  51. }
  52. else
  53. {
  54. netframe = systemLetter + L":\\Windows\\Microsoft.NET\\Framework\\v4.0.30319";
  55. }
  56. std::wstring cmd = L"";
  57. //cmd = L"dism /online /enable-feature /featurename:IIS-ASPNET45 /all";//win8需要启动ASPNET4.5服务,目前暂时没用到;
  58. //检测当前系统为win8或更高版本
  59. if (IsWindows8OrGreater())
  60. {
  61. cmd = L"/k " + systemLetter + L": & cd " + netframe + L" & aspnet_regiis.exe -i /qb /qn";
  62. std::map<wstring, wstring> map{ {L"InstallNetFramwork", cmd}, { L"WindowsVersion", L"Win8,10.." }};
  63. LogIni::GetLogToIniMaps(map);
  64. m_IsWin8InstallNet = true;
  65. }
  66. else
  67. {
  68. cmd = L"/k " + systemLetter + L": & cd " + netframe + L" & aspnet_regiis.exe -i /qb /qn";
  69. std::map<wstring, wstring> map{ {L"InstallNetFramwork", cmd}, { L"WindowsVersion", L"Win7" } };
  70. LogIni::GetLogToIniMaps(map);
  71. }
  72. TCHAR* tc = (TCHAR*)(&cmd[0]);
  73. return Executecmd(tc);
  74. }
  75. BOOL CCmd::InstallVcPlusPluscmd() {
  76. std::wstring cmd = L"";
  77. wchar_t downloadsPath[MAX_PATH];
  78. DWORD bufferSize = ::GetEnvironmentVariable(L"USERPROFILE", downloadsPath, MAX_PATH);
  79. std::wstring wstrPath_Install(downloadsPath);
  80. wstrPath_Install += L"\\Downloads";
  81. //防止目标路径与当前进程所在盘符不一致,所以在cd之前,要指定目标路径的盘符cdDisk
  82. auto cdDisk = wstrPath_Install.substr(0, 1) + L": & ";
  83. cmd = L"/k " + cdDisk + L"cd \"" + wstrPath_Install + L"\"" + L" & curl -o vc_redist.x64.exe https://download.visualstudio.microsoft.com/download/pr/eaab1f82-787d-4fd7-8c73-f782341a0c63/917C37D816488545B70AFFD77D6E486E4DD27E2ECE63F6BBAAF486B178B2B888/VC_redist.x64.exe && start /wait vc_redist.x64.exe /install /quiet /norestart && del vc_redist.x64.exe";
  84. //LogIni::GetLogToIni("Install cmd", cmd);
  85. TCHAR* tc = (TCHAR*)(&cmd[0]);
  86. return Executecmd(tc);
  87. }
  88. BOOL CCmd::OpenAppcmd()
  89. {
  90. //Todo:目前不使用该函数
  91. std::wstring cmd = L"";
  92. auto cdDisk = PathCore::smPath_Install.substr(0, 1) + L": & ";
  93. cmd = L"/k " + cdDisk + L"cd \"" + PathCore::smPath_Install + L"\"" + L" & start/wait " + Product::smName_Application;
  94. LogIni::GetLogToIni("Start App cmd", cmd);
  95. TCHAR* tc = (TCHAR*)(&cmd[0]);
  96. return Executecmd(tc);
  97. }
  98. BOOL CCmd::Executecmd(TCHAR pszCmdLine[], bool isVBA)
  99. {
  100. char Buffer[4096];
  101. STARTUPINFO sInfo;//新进程的主窗口特性
  102. PROCESS_INFORMATION pInfo;
  103. SECURITY_ATTRIBUTES sa;
  104. HANDLE hRead, hWrite;
  105. DWORD bytesRead; //读取代码的长度
  106. sa.nLength = sizeof(SECURITY_ATTRIBUTES); //结构体的大小,可用SIZEOF取得
  107. sa.lpSecurityDescriptor = NULL;//安全描述符
  108. sa.bInheritHandle = TRUE;; //安全描述的对象能否被新创建ÆÆ的进程继承
  109. if (!CreatePipe(&hRead, &hWrite, &sa, 0))
  110. {
  111. return GetLastError();
  112. }
  113. GetStartupInfo(&sInfo);
  114. sInfo.cb = sizeof(sInfo);
  115. sInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
  116. sInfo.wShowWindow = SW_HIDE;
  117. sInfo.hStdError = hWrite; //将管道的写端交给子进程
  118. sInfo.hStdOutput = hWrite;
  119. memset(&pInfo, 0, sizeof(pInfo));
  120. wstring cmdPath = L"";
  121. if (isVBA == false)
  122. {
  123. cmdPath = L"c:\\windows\\system32\\cmd.exe";
  124. }
  125. else
  126. {
  127. wstring Installpath = PathCore::smPath_Install + L"\\install.bat";
  128. cmdPath = Installpath;
  129. }
  130. if (!CreateProcessW(cmdPath.c_str(), pszCmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &sInfo, &pInfo))
  131. {
  132. CloseHandle(hWrite);
  133. CloseHandle(hRead);
  134. return GetLastError();
  135. }
  136. for (int i = 0;; ++i)
  137. {
  138. //执行cmd结束之后,则读取文件结束
  139. if (!ReadFile(hRead, Buffer, sizeof(Buffer) - 1, &bytesRead, NULL))
  140. {
  141. break;
  142. Buffer[bytesRead] = 0;
  143. }
  144. else
  145. {
  146. WaitForSingleObject(pInfo.hProcess, 1000);
  147. CloseHandle(hWrite);
  148. CloseHandle(hRead);
  149. return TRUE;
  150. }
  151. }
  152. CloseHandle(hWrite);
  153. CloseHandle(hRead);
  154. return TRUE;
  155. }
  156. #pragma region VBA脚本指令(备用方案)
  157. //编辑vba脚本内容-》生成文件vba文件到安装路径-》执行vba文件
  158. //
  159. //
  160. //因时间有限,暂时不进行排查修复UTF-16的vba脚本执行没反应的问题
  161. bool CCmd::GetVBA_UTF16()
  162. {
  163. std::wstring cmdd = L"";
  164. std::wstring echoc = L"ECHO.";
  165. //vba脚本内容
  166. cmdd = L"@echo off\n" +
  167. echoc + L"\n" +
  168. PathCore::smPath_Install.substr(0, 1) + L": & " + L"cd " + L"%~dp0" + L"\n" +
  169. echoc + L"\n" +
  170. echoc + L"\n" +
  171. L"start/wait " + Product::smName_InstallPackage + L" APPDIR=\"" + PathCore::smPath_Install + L"\" /qb /qn" + L"\n" +
  172. echoc + L"\n" +
  173. L"EXIT";
  174. wstring Installpath = PathCore::smPath_Install + L"\\install.bat";
  175. HANDLE hDevice = CreateFileW(Installpath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0,
  176. OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  177. if (hDevice == INVALID_HANDLE_VALUE)
  178. {
  179. DWORD errorCode = GetLastError();
  180. return false;
  181. }
  182. DWORD dwWriteSize = 0;
  183. auto chBuffer = cmdd.c_str();
  184. DWORD nBytes;
  185. WORD a = 0xFEFF;
  186. WriteFile(hDevice, &a, sizeof(a), &nBytes, NULL);
  187. BOOL bRet = WriteFile(hDevice, chBuffer, lstrlen(chBuffer) * sizeof(wchar_t), &nBytes, NULL);
  188. //BOOL bRet = WriteFile(hDevice, chBuffer, cmdd.length(), &dwWriteSize, NULL);
  189. //BOOL bRet = WriteFile(hDevice, chBuffer, cmdd.length(), &dwWriteSize, NULL);
  190. if (bRet)
  191. {
  192. }
  193. FlushFileBuffers(hDevice); //将缓冲区数据写入磁盘
  194. LONG IDistance = 0;
  195. DWORD dwPtr = SetFilePointer(hDevice, IDistance, NULL, FILE_BEGIN); //调整文件指针到文件开头
  196. DWORD dwSize = GetFileSize(hDevice, NULL);
  197. //bRet = ReadFile(hDevice, chBuffer, dwSize, &dwSize, NULL);
  198. //if (bRet)
  199. //{
  200. // //printf("chbuffer is %s /n", chBuffer);
  201. //}
  202. CloseHandle(hDevice);
  203. Executecmd(nullptr, true);
  204. }
  205. //含有中文空格的路径,调用UTF8 VBA脚本会失败(安装到一半,就自动回退到安装前状态)
  206. bool CCmd::GetVBA_UTF8()
  207. {
  208. wstring Installpath = PathCore::smPath_Install + L"\\install.bat";
  209. LPCWSTR Installpathstr = Installpath.c_str();
  210. wchar_t* rootptr = _wcsdup(PathCore::smPath_Install.substr(0, 1).c_str());
  211. auto rootch = CharConvert::GetMultiByteW(rootptr);
  212. wchar_t* rootptr22 = _wcsdup(PathCore::smPath_Install.c_str());
  213. auto rootch22 = CharConvert::GetMultiByteW(rootptr22);
  214. wchar_t* ptrInstallPackage = _wcsdup(Product::smName_InstallPackage.c_str()/*.substr(0, 1).c_str()*/);
  215. auto InstallPackagech = CharConvert::GetMultiByteW(ptrInstallPackage);
  216. std::string cmdd = "";
  217. std::string echoc = "ECHO.";
  218. cmdd = "@echo off\n" +
  219. echoc + "\n" +
  220. rootch + ": & " + "cd " + "%~dp0" + "\n" +
  221. echoc + "\n" +
  222. echoc + "\n" +
  223. "start/wait " + InstallPackagech + " APPDIR=%cd%" + +" /qb /qn" + "\n" +
  224. echoc + "\n" +
  225. "EXIT";
  226. char* chBuffer = &cmdd[0];
  227. HANDLE hDevice = CreateFile(Installpathstr, GENERIC_READ | GENERIC_WRITE, 0, 0,
  228. OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  229. if (hDevice == INVALID_HANDLE_VALUE)
  230. {
  231. DWORD errorCode = GetLastError();
  232. return false;
  233. }
  234. DWORD dwSize = GetFileSize(hDevice, NULL);
  235. DWORD dwWriteSize = 0;
  236. WORD a = 0xFEFF;
  237. WriteFile(hDevice, &a, sizeof(a), &dwWriteSize, NULL);
  238. BOOL bRet = WriteFile(hDevice, chBuffer, lstrlenA(chBuffer) * sizeof(char), &dwWriteSize, NULL);
  239. //BOOL bRet = WriteFile(hDevice, chBuffer, cmdd.length(), &dwWriteSize, NULL);
  240. if (bRet)
  241. {
  242. return false;
  243. }
  244. FlushFileBuffers(hDevice);
  245. LONG IDistance = 0;
  246. DWORD dwPtr = SetFilePointer(hDevice, IDistance, NULL, FILE_BEGIN);
  247. DWORD dwReadSize = 0;
  248. /*bRet = ReadFile(hDevice, chBuffer, 10, &dwReadSize, NULL);
  249. if (bRet)
  250. {
  251. printf("chbuffer is %s /n", chBuffer);
  252. }*/
  253. CloseHandle(hDevice);
  254. return Executecmd(nullptr, true);;
  255. }
  256. #pragma endregion