Launches executable with the path or paths as argument. @param p_Paths Path or paths to pass as arguments, pre-bundled in a single string. @param p_hWnd Parent window handle, if needed.
| 62 | // @param p_hWnd Parent window handle, if needed. |
| 63 | // |
| 64 | void LaunchExecutablePathAction::Act(const std::wstring& p_Paths, |
| 65 | HWND const p_hWnd) const |
| 66 | { |
| 67 | auto files{p_Paths}; |
| 68 | if (m_UseFilelist) { |
| 69 | // Get path to temp directory |
| 70 | std::wstring tempDirPath(MAX_PATH + 1, L'\0'); |
| 71 | if (::GetTempPathW(gsl::narrow<DWORD>(tempDirPath.size()), &*tempDirPath.begin()) == 0) { |
| 72 | throw LaunchExecutableException(); |
| 73 | } |
| 74 | |
| 75 | // Generate temp file for the paths |
| 76 | std::wstring tempFilePathBuffer(MAX_PATH + 1, L'\0'); |
| 77 | if (::GetTempFileNameW(tempDirPath.c_str(), L"pcc", 0, &*tempFilePathBuffer.begin()) == 0) { |
| 78 | throw LaunchExecutableException(); |
| 79 | } |
| 80 | const std::wstring tempFilePath = tempFilePathBuffer.c_str(); |
| 81 | |
| 82 | |
| 83 | // Convert paths to single-byte string |
| 84 | const ATL::CStringA mbPaths(p_Paths.c_str()); |
| 85 | |
| 86 | // Write paths to the temp file and use path to that file in arguments to executable |
| 87 | std::ofstream of(tempFilePath, std::ios::out | std::ios::binary); |
| 88 | of.write((LPCSTR) mbPaths, mbPaths.GetLength()); |
| 89 | files = tempFilePath; |
| 90 | |
| 91 | // If temp file path contains spaces, add quotes around the path to make sure |
| 92 | // it is passed correctly to the executable. |
| 93 | if (files.find(L" ") != std::wstring::npos) { |
| 94 | files = L"\"" + files + L"\""; |
| 95 | } |
| 96 | } |
| 97 | |
| 98 | // Look for files placeholder in arguments. If it's not there, append the files. |
| 99 | auto arguments{m_Arguments}; |
| 100 | std::wregex placeholderRegex(FILES_ARGUMENT_PLACEHOLDER, |
| 101 | std::regex_constants::ECMAScript | std::regex_constants::icase); |
| 102 | std::wsmatch match; |
| 103 | if (std::regex_search(arguments, match, placeholderRegex)) { |
| 104 | arguments = match.prefix().str() + files + match.suffix().str(); |
| 105 | } else { |
| 106 | if (arguments.empty() || arguments.back() != L' ') { |
| 107 | arguments += L' '; |
| 108 | } |
| 109 | arguments += files; |
| 110 | } |
| 111 | |
| 112 | // Need reinterpret_cast here because of legacy Win32 API |
| 113 | [[gsl::suppress(type.1)]] |
| 114 | { |
| 115 | const auto res = reinterpret_cast<size_t>(::ShellExecuteW(p_hWnd, |
| 116 | nullptr, |
| 117 | m_Executable.c_str(), |
| 118 | arguments.c_str(), |
| 119 | nullptr, |
| 120 | SW_SHOWDEFAULT)); |
| 121 | if (res <= 32) { |
nothing calls this directly
no test coverage detected