void CommandLineBuilder::AppendArguments (/*[in]*/ const Argv & argv) { if (argv.GetArgc() > 0) { AppendArguments (argv.GetArgc() - 1, argv.GetArgv() + 1); } }
void HOSTFXR_UTILITY::GetHostFxrParameters( const fs::path &processPath, const fs::path &applicationPhysicalPath, const std::wstring &applicationArguments, fs::path &hostFxrDllPath, fs::path &dotnetExePath, std::vector<std::wstring> &arguments ) { LOG_INFOF(L"Resolving hostfxr parameters for application: '%ls' arguments: '%ls' path: '%ls'", processPath.c_str(), applicationArguments.c_str(), applicationPhysicalPath.c_str()); arguments = std::vector<std::wstring>(); fs::path expandedProcessPath = Environment::ExpandEnvironmentVariables(processPath); const auto expandedApplicationArguments = Environment::ExpandEnvironmentVariables(applicationArguments); LOG_INFOF(L"Known dotnet.exe location: '%ls'", dotnetExePath.c_str()); if (!expandedProcessPath.has_extension()) { // The only executable extension inprocess supports expandedProcessPath.replace_extension(".exe"); } else if (!ends_with(expandedProcessPath, L".exe", true)) { throw InvalidOperationException(format(L"Process path '%s' doesn't have '.exe' extension.", expandedProcessPath.c_str())); } // Check if the absolute path is to dotnet or not. if (IsDotnetExecutable(expandedProcessPath)) { LOG_INFOF(L"Process path '%ls' is dotnet, treating application as portable", expandedProcessPath.c_str()); if (applicationArguments.empty()) { throw InvalidOperationException(L"Application arguments are empty."); } if (dotnetExePath.empty()) { dotnetExePath = GetAbsolutePathToDotnet(applicationPhysicalPath, expandedProcessPath); } hostFxrDllPath = GetAbsolutePathToHostFxr(dotnetExePath); arguments.push_back(dotnetExePath); AppendArguments( expandedApplicationArguments, applicationPhysicalPath, arguments, true); } else { LOG_INFOF(L"Process path '%ls' is not dotnet, treating application as standalone or portable with bootstrapper", expandedProcessPath.c_str()); auto executablePath = expandedProcessPath; if (executablePath.is_relative()) { executablePath = applicationPhysicalPath / expandedProcessPath; } // // The processPath is a path to the application executable // like: C:\test\MyApp.Exe or MyApp.Exe // Check if the file exists, and if it does, get the parameters for a standalone application // if (is_regular_file(executablePath)) { auto applicationDllPath = executablePath; applicationDllPath.replace_extension(".dll"); LOG_INFOF(L"Checking application.dll at '%ls'", applicationDllPath.c_str()); if (!is_regular_file(applicationDllPath)) { throw InvalidOperationException(format(L"Application .dll was not found at %s", applicationDllPath.c_str())); } hostFxrDllPath = executablePath.parent_path() / "hostfxr.dll"; LOG_INFOF(L"Checking hostfxr.dll at '%ls'", hostFxrDllPath.c_str()); if (is_regular_file(hostFxrDllPath)) { LOG_INFOF(L"hostfxr.dll found app local at '%ls', treating application as standalone", hostFxrDllPath.c_str()); // For standalone apps we need .exe to be argv[0], dll would be discovered next to it arguments.push_back(executablePath); } else { LOG_INFOF(L"hostfxr.dll found app local at '%ls', treating application as portable with launcher", hostFxrDllPath.c_str()); // passing "dotnet" here because we don't know where dotnet.exe should come from // so trying all fallbacks is appropriate if (dotnetExePath.empty()) { dotnetExePath = GetAbsolutePathToDotnet(applicationPhysicalPath, L"dotnet"); } hostFxrDllPath = GetAbsolutePathToHostFxr(dotnetExePath); // For portable with launcher apps we need dotnet.exe to be argv[0] and .dll be argv[1] arguments.push_back(dotnetExePath); arguments.push_back(applicationDllPath); } AppendArguments( expandedApplicationArguments, applicationPhysicalPath, arguments); } else { // // If the processPath file does not exist and it doesn't include dotnet.exe or dotnet // then it is an invalid argument. // throw InvalidOperationException(format(L"Executable was not found at '%s'", executablePath.c_str())); } } }