Use std::filesystem in hostfxr utilities (#926)
This commit is contained in:
parent
17fdbf6514
commit
60711bfca1
|
|
@ -0,0 +1,6 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
#define EVENTLOG(log, name, ...) UTILITY::LogEventF(log, ASPNETCORE_EVENT_ ## name ## _LEVEL, ASPNETCORE_EVENT_ ## name, ASPNETCORE_EVENT_ ## name ## _MSG, __VA_ARGS__)
|
||||
|
|
@ -2,7 +2,6 @@
|
|||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <experimental/filesystem>
|
||||
|
||||
namespace fs = std::experimental::filesystem;
|
||||
|
||||
|
|
@ -96,7 +95,7 @@ GlobalVersionUtility::RemoveFileNameFromFolderPath(std::wstring fileName)
|
|||
return path.parent_path();
|
||||
}
|
||||
|
||||
std::wstring
|
||||
std::wstring
|
||||
GlobalVersionUtility::GetModuleName(HMODULE hModuleName)
|
||||
{
|
||||
DWORD dwSize = MAX_PATH;
|
||||
|
|
@ -126,6 +125,6 @@ GlobalVersionUtility::GetModuleName(HMODULE hModuleName)
|
|||
fDone = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,15 +8,15 @@ class GlobalVersionUtility
|
|||
{
|
||||
public:
|
||||
|
||||
static
|
||||
std::wstring
|
||||
static
|
||||
std::wstring
|
||||
GetGlobalRequestHandlerPath(PCWSTR pwzAspNetCoreFolderPath, PCWSTR pwzHandlerVersion, PCWSTR pwzHandlerName);
|
||||
|
||||
static
|
||||
std::wstring
|
||||
FindHighestGlobalVersion(PCWSTR pwzAspNetCoreFolderPath);
|
||||
|
||||
static
|
||||
static
|
||||
std::wstring
|
||||
RemoveFileNameFromFolderPath(std::wstring fileName);
|
||||
|
||||
|
|
|
|||
|
|
@ -212,6 +212,12 @@ Language=English
|
|||
%1
|
||||
.
|
||||
|
||||
Messageid=1031
|
||||
SymbolicName=ASPNETCORE_EVENT_INVALID_PROCESS_PATH
|
||||
Language=English
|
||||
%1
|
||||
.
|
||||
|
||||
;
|
||||
;#endif // _ASPNETCORE_MODULE_MSG_H_
|
||||
;
|
||||
|
|
|
|||
|
|
@ -2,14 +2,9 @@
|
|||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <string>
|
||||
|
||||
HOSTFXR_UTILITY::HOSTFXR_UTILITY()
|
||||
{
|
||||
}
|
||||
|
||||
HOSTFXR_UTILITY::~HOSTFXR_UTILITY()
|
||||
{
|
||||
}
|
||||
namespace fs = std::experimental::filesystem;
|
||||
|
||||
//
|
||||
// Runs a standalone appliction.
|
||||
|
|
@ -25,131 +20,72 @@ HOSTFXR_UTILITY::~HOSTFXR_UTILITY()
|
|||
//
|
||||
HRESULT
|
||||
HOSTFXR_UTILITY::GetStandaloneHostfxrParameters(
|
||||
PCWSTR pwzExeAbsolutePath, // includes .exe file extension.
|
||||
PCWSTR pcwzApplicationPhysicalPath,
|
||||
PCWSTR pcwzArguments,
|
||||
HANDLE hEventLog,
|
||||
_Inout_ STRU* pStruHostFxrDllLocation,
|
||||
_Out_ DWORD* pdwArgCount,
|
||||
_Out_ BSTR** ppwzArgv
|
||||
PCWSTR pwzExeAbsolutePath, // includes .exe file extension.
|
||||
PCWSTR pcwzApplicationPhysicalPath,
|
||||
PCWSTR pcwzArguments,
|
||||
HANDLE hEventLog,
|
||||
_Inout_ STRU* pStruHostFxrDllLocation,
|
||||
_Out_ DWORD* pdwArgCount,
|
||||
_Out_ BSTR** ppwzArgv
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
STRU struDllPath;
|
||||
STRU struArguments;
|
||||
STRU struHostFxrPath;
|
||||
STRU struRuntimeConfigLocation;
|
||||
DWORD dwPosition;
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
// Obtain the app name from the processPath section.
|
||||
if (FAILED(hr = struDllPath.Copy(pwzExeAbsolutePath)))
|
||||
const fs::path exePath(pwzExeAbsolutePath);
|
||||
|
||||
if (!exePath.has_extension())
|
||||
{
|
||||
goto Finished;
|
||||
return false;
|
||||
}
|
||||
|
||||
dwPosition = struDllPath.LastIndexOf(L'.', 0);
|
||||
if (dwPosition == -1)
|
||||
{
|
||||
hr = E_FAIL;
|
||||
goto Finished;
|
||||
}
|
||||
const fs::path physicalPath(pcwzApplicationPhysicalPath);
|
||||
const fs::path hostFxrLocation = physicalPath / "hostfxr.dll";
|
||||
|
||||
hr = UTILITY::ConvertPathToFullPath(L".\\hostfxr.dll", pcwzApplicationPhysicalPath, &struHostFxrPath);
|
||||
if (FAILED(hr))
|
||||
if (!is_regular_file(hostFxrLocation))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
fs::path runtimeConfigLocation = exePath;
|
||||
runtimeConfigLocation.replace_extension(L".runtimeconfig.json");
|
||||
|
||||
struDllPath.QueryStr()[dwPosition] = L'\0';
|
||||
if (FAILED(hr = struDllPath.SyncWithBuffer()))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (!UTILITY::CheckIfFileExists(struHostFxrPath.QueryStr()))
|
||||
{
|
||||
// Most likely a full framework app.
|
||||
// Check that the runtime config file doesn't exist in the folder as another heuristic.
|
||||
if (FAILED(hr = struRuntimeConfigLocation.Copy(struDllPath)) ||
|
||||
FAILED(hr = struRuntimeConfigLocation.Append(L".runtimeconfig.json")))
|
||||
if (!is_regular_file(runtimeConfigLocation))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
if (!UTILITY::CheckIfFileExists(struRuntimeConfigLocation.QueryStr()))
|
||||
{
|
||||
|
||||
hr = E_APPLICATION_ACTIVATION_EXEC_FAILURE;
|
||||
UTILITY::LogEventF(hEventLog,
|
||||
EVENTLOG_ERROR_TYPE,
|
||||
ASPNETCORE_EVENT_INPROCESS_FULL_FRAMEWORK_APP,
|
||||
ASPNETCORE_EVENT_INPROCESS_FULL_FRAMEWORK_APP_MSG,
|
||||
pcwzApplicationPhysicalPath,
|
||||
hr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If a runtime config file does exist, report a file not found on the app.exe
|
||||
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||
UTILITY::LogEventF(hEventLog,
|
||||
EVENTLOG_ERROR_TYPE,
|
||||
ASPNETCORE_EVENT_APPLICATION_EXE_NOT_FOUND,
|
||||
ASPNETCORE_EVENT_APPLICATION_EXE_NOT_FOUND_MSG,
|
||||
pcwzApplicationPhysicalPath,
|
||||
hr);
|
||||
EVENTLOG(hEventLog, INPROCESS_FULL_FRAMEWORK_APP, pcwzApplicationPhysicalPath, 0);
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
goto Finished;
|
||||
EVENTLOG(hEventLog, APPLICATION_EXE_NOT_FOUND, pcwzApplicationPhysicalPath, 0);
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
if (FAILED(hr = pStruHostFxrDllLocation->Copy(struHostFxrPath)))
|
||||
fs::path dllPath = exePath;
|
||||
dllPath.replace_extension(".dll");
|
||||
|
||||
if (!is_regular_file(dllPath))
|
||||
{
|
||||
goto Finished;
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
auto arguments = std::wstring(dllPath) + L" " + pcwzArguments;
|
||||
|
||||
if (FAILED(hr = struDllPath.Append(L".dll")))
|
||||
if (FAILED(hr = pStruHostFxrDllLocation->Copy(hostFxrLocation.c_str())))
|
||||
{
|
||||
goto Finished;
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (!UTILITY::CheckIfFileExists(struDllPath.QueryStr()))
|
||||
{
|
||||
// Treat access issue as File not found
|
||||
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (FAILED(hr = struArguments.Copy(struDllPath)) ||
|
||||
FAILED(hr = struArguments.Append(L" ")) ||
|
||||
FAILED(hr = struArguments.Append(pcwzArguments)))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (FAILED(hr = ParseHostfxrArguments(
|
||||
struArguments.QueryStr(),
|
||||
return ParseHostfxrArguments(
|
||||
arguments.c_str(),
|
||||
pwzExeAbsolutePath,
|
||||
pcwzApplicationPhysicalPath,
|
||||
hEventLog,
|
||||
pdwArgCount,
|
||||
ppwzArgv)))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
Finished:
|
||||
|
||||
return hr;
|
||||
ppwzArgv);
|
||||
}
|
||||
|
||||
BOOL
|
||||
HOSTFXR_UTILITY::IsDotnetExecutable(STRU *struExecutablePath)
|
||||
HOSTFXR_UTILITY::IsDotnetExecutable(const std::experimental::filesystem::path & dotnetPath)
|
||||
{
|
||||
if (struExecutablePath == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
return struExecutablePath->EndsWith(L"dotnet.exe") || struExecutablePath->EndsWith(L"dotnet");
|
||||
auto name = dotnetPath.filename();
|
||||
name.replace_extension("");
|
||||
return _wcsnicmp(name.c_str(), L"dotnet", 6) == 0;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
|
|
@ -165,70 +101,58 @@ HOSTFXR_UTILITY::GetHostFxrParameters(
|
|||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
STRU struSystemPathVariable;
|
||||
STRU struAbsolutePathToHostFxr;
|
||||
STRU struAbsolutePathToDotnet;
|
||||
STRU struEventMsg;
|
||||
STACK_STRU(struExpandedProcessPath, MAX_PATH);
|
||||
STACK_STRU(struExpandedArguments, MAX_PATH);
|
||||
|
||||
// Copy and Expand the processPath and Arguments.
|
||||
if (FAILED(hr = struExpandedProcessPath.CopyAndExpandEnvironmentStrings(pcwzProcessPath))
|
||||
|| FAILED(hr = struExpandedArguments.CopyAndExpandEnvironmentStrings(pcwzArguments)))
|
||||
const fs::path applicationPhysicalPath = pcwzApplicationPhysicalPath;
|
||||
fs::path processPath = ExpandEnvironmentVariables(pcwzProcessPath);
|
||||
std::wstring arguments = ExpandEnvironmentVariables(pcwzArguments);
|
||||
|
||||
if (processPath.is_relative())
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
// Convert the process path an absolute path to our current application directory.
|
||||
// If the path is already an absolute path, it will be unchanged.
|
||||
hr = UTILITY::ConvertPathToFullPath(
|
||||
struExpandedProcessPath.QueryStr(),
|
||||
pcwzApplicationPhysicalPath,
|
||||
&struAbsolutePathToDotnet
|
||||
);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
processPath = applicationPhysicalPath / processPath;
|
||||
}
|
||||
|
||||
// Check if the absolute path is to dotnet or not.
|
||||
if (HOSTFXR_UTILITY::IsDotnetExecutable(&struAbsolutePathToDotnet))
|
||||
if (IsDotnetExecutable(processPath))
|
||||
{
|
||||
//
|
||||
// The processPath ends with dotnet.exe or dotnet
|
||||
// like: C:\Program Files\dotnet\dotnet.exe, C:\Program Files\dotnet\dotnet, dotnet.exe, or dotnet.
|
||||
// Get the absolute path to dotnet. If the path is already an absolute path, it will return that path
|
||||
//
|
||||
if (FAILED(hr = HOSTFXR_UTILITY::GetAbsolutePathToDotnet(&struAbsolutePathToDotnet))) // Make sure to append the dotnet.exe path correctly here (pass in regular path)?
|
||||
// Make sure to append the dotnet.exe path correctly here (pass in regular path)?
|
||||
auto fullProcessPath = GetAbsolutePathToDotnet(processPath);
|
||||
if (!fullProcessPath.has_value())
|
||||
{
|
||||
goto Finished;
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
if (FAILED(hr = GetAbsolutePathToHostFxr(&struAbsolutePathToDotnet, hEventLog, &struAbsolutePathToHostFxr)))
|
||||
processPath = fullProcessPath.value();
|
||||
|
||||
auto hostFxrPath = GetAbsolutePathToHostFxr(processPath, hEventLog);
|
||||
if (!hostFxrPath.has_value())
|
||||
{
|
||||
goto Finished;
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
if (FAILED(hr = HOSTFXR_UTILITY::ParseHostfxrArguments(
|
||||
struExpandedArguments.QueryStr(),
|
||||
struAbsolutePathToDotnet.QueryStr(),
|
||||
arguments.c_str(),
|
||||
processPath.c_str(),
|
||||
pcwzApplicationPhysicalPath,
|
||||
hEventLog,
|
||||
pdwArgCount,
|
||||
pbstrArgv)))
|
||||
{
|
||||
goto Finished;
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (FAILED(hr = pStruHostFxrDllLocation->Copy(struAbsolutePathToHostFxr)))
|
||||
if (FAILED(hr = pStruHostFxrDllLocation->Copy(hostFxrPath->c_str())))
|
||||
{
|
||||
goto Finished;
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (FAILED(hr = pStruExeAbsolutePath->Copy(struAbsolutePathToDotnet)))
|
||||
if (FAILED(hr = pStruExeAbsolutePath->Copy(processPath.c_str())))
|
||||
{
|
||||
goto Finished;
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -238,25 +162,25 @@ HOSTFXR_UTILITY::GetHostFxrParameters(
|
|||
// 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 (UTILITY::CheckIfFileExists(struAbsolutePathToDotnet.QueryStr()))
|
||||
if (is_regular_file(processPath))
|
||||
{
|
||||
hr = HOSTFXR_UTILITY::GetStandaloneHostfxrParameters(
|
||||
struAbsolutePathToDotnet.QueryStr(),
|
||||
if (FAILED(hr = GetStandaloneHostfxrParameters(
|
||||
processPath.c_str(),
|
||||
pcwzApplicationPhysicalPath,
|
||||
struExpandedArguments.QueryStr(),
|
||||
arguments.c_str(),
|
||||
hEventLog,
|
||||
pStruHostFxrDllLocation,
|
||||
pdwArgCount,
|
||||
pbstrArgv);
|
||||
if (FAILED(hr))
|
||||
pbstrArgv)))
|
||||
{
|
||||
goto Finished;
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (FAILED(hr = pStruExeAbsolutePath->Copy(struAbsolutePathToDotnet)))
|
||||
if (FAILED(hr = pStruExeAbsolutePath->Copy(processPath.c_str())))
|
||||
{
|
||||
goto Finished;
|
||||
return hr;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -264,19 +188,13 @@ HOSTFXR_UTILITY::GetHostFxrParameters(
|
|||
// If the processPath file does not exist and it doesn't include dotnet.exe or dotnet
|
||||
// then it is an invalid argument.
|
||||
//
|
||||
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);;
|
||||
UTILITY::LogEventF(hEventLog,
|
||||
EVENTLOG_ERROR_TYPE,
|
||||
ASPNETCORE_EVENT_GENERAL_ERROR_MSG,
|
||||
ASPNETCORE_EVENT_INVALID_PROCESS_PATH_MSG,
|
||||
struExpandedProcessPath.QueryStr(),
|
||||
hr);
|
||||
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||
UTILITY::LogEventF(hEventLog, ASPNETCORE_EVENT_INVALID_PROCESS_PATH_LEVEL, ASPNETCORE_EVENT_INVALID_PROCESS_PATH, ASPNETCORE_EVENT_INVALID_PROCESS_PATH_MSG, processPath.c_str(), hr);
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
||||
Finished:
|
||||
|
||||
return hr;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -394,163 +312,82 @@ Finished:
|
|||
return hr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
std::optional<fs::path>
|
||||
HOSTFXR_UTILITY::GetAbsolutePathToDotnet(
|
||||
_Inout_ STRU* pStruAbsolutePathToDotnet
|
||||
const fs::path & requestedPath
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
//
|
||||
// If we are given an absolute path to dotnet.exe, we are done
|
||||
//
|
||||
if (UTILITY::CheckIfFileExists(pStruAbsolutePathToDotnet->QueryStr()))
|
||||
if (is_regular_file(requestedPath))
|
||||
{
|
||||
goto Finished;
|
||||
return std::make_optional(requestedPath);
|
||||
}
|
||||
|
||||
//
|
||||
// If the path was C:\Program Files\dotnet\dotnet
|
||||
// We need to try appending .exe and check if the file exists too.
|
||||
//
|
||||
if (FAILED(hr = pStruAbsolutePathToDotnet->Append(L".exe")))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
auto pathWithExe = requestedPath;
|
||||
pathWithExe.concat(L".exe");
|
||||
|
||||
if (UTILITY::CheckIfFileExists(pStruAbsolutePathToDotnet->QueryStr()))
|
||||
if (is_regular_file(pathWithExe))
|
||||
{
|
||||
goto Finished;
|
||||
return std::make_optional(pathWithExe);
|
||||
}
|
||||
|
||||
// At this point, we are calling where.exe to find dotnet.
|
||||
// If we encounter any failures, try getting dotnet.exe from the
|
||||
// backup location.
|
||||
if (!InvokeWhereToFindDotnet(pStruAbsolutePathToDotnet))
|
||||
// Only do it if no path is specified
|
||||
if (!requestedPath.has_parent_path())
|
||||
{
|
||||
hr = GetAbsolutePathToDotnetFromProgramFiles(pStruAbsolutePathToDotnet);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
Finished:
|
||||
const auto dotnetViaWhere = InvokeWhereToFindDotnet();
|
||||
if (dotnetViaWhere.has_value())
|
||||
{
|
||||
return dotnetViaWhere;
|
||||
}
|
||||
|
||||
return hr;
|
||||
return GetAbsolutePathToDotnetFromProgramFiles();
|
||||
}
|
||||
|
||||
HRESULT
|
||||
std::optional<fs::path>
|
||||
HOSTFXR_UTILITY::GetAbsolutePathToHostFxr(
|
||||
STRU* pStruAbsolutePathToDotnet,
|
||||
HANDLE hEventLog,
|
||||
STRU* pStruAbsolutePathToHostfxr
|
||||
const fs::path & dotnetPath,
|
||||
HANDLE hEventLog
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
STRU struHostFxrPath;
|
||||
STRU struHostFxrSearchExpression;
|
||||
STRU struHighestDotnetVersion;
|
||||
STRU struEventMsg;
|
||||
std::vector<std::wstring> vVersionFolders;
|
||||
DWORD dwPosition = 0;
|
||||
std::vector<std::wstring> versionFolders;
|
||||
const auto hostFxrBase = dotnetPath.parent_path() / "host" / "fxr";
|
||||
|
||||
if (FAILED(hr = struHostFxrPath.Copy(pStruAbsolutePathToDotnet)))
|
||||
if (!is_directory(hostFxrBase))
|
||||
{
|
||||
goto Finished;
|
||||
EVENTLOG(hEventLog, HOSTFXR_DIRECTORY_NOT_FOUND, hostFxrBase.c_str(), HRESULT_FROM_WIN32(ERROR_BAD_ENVIRONMENT));
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
dwPosition = struHostFxrPath.LastIndexOf(L'\\', 0);
|
||||
if (dwPosition == -1)
|
||||
auto searchPattern = std::wstring(hostFxrBase) + L"\\*";
|
||||
FindDotNetFolders(searchPattern.c_str(), versionFolders);
|
||||
|
||||
if (versionFolders.empty())
|
||||
{
|
||||
hr = E_FAIL;
|
||||
goto Finished;
|
||||
EVENTLOG(hEventLog, HOSTFXR_DIRECTORY_NOT_FOUND, hostFxrBase.c_str(), HRESULT_FROM_WIN32(ERROR_BAD_ENVIRONMENT));
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
struHostFxrPath.QueryStr()[dwPosition] = L'\0';
|
||||
const auto highestVersion = FindHighestDotNetVersion(versionFolders);
|
||||
const auto hostFxrPath = hostFxrBase / highestVersion / "hostfxr.dll";
|
||||
|
||||
if (FAILED(hr = struHostFxrPath.SyncWithBuffer()) ||
|
||||
FAILED(hr = struHostFxrPath.Append(L"\\")))
|
||||
if (!is_regular_file(hostFxrPath))
|
||||
{
|
||||
goto Finished;
|
||||
EVENTLOG(hEventLog, HOSTFXR_DLL_NOT_FOUND, hostFxrPath.c_str(), HRESULT_FROM_WIN32(ERROR_FILE_INVALID));
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
hr = struHostFxrPath.Append(L"host\\fxr");
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (!UTILITY::DirectoryExists(&struHostFxrPath))
|
||||
{
|
||||
hr = ERROR_BAD_ENVIRONMENT;
|
||||
UTILITY::LogEventF(hEventLog,
|
||||
EVENTLOG_ERROR_TYPE,
|
||||
ASPNETCORE_EVENT_HOSTFXR_DIRECTORY_NOT_FOUND,
|
||||
struEventMsg.QueryStr(),
|
||||
ASPNETCORE_EVENT_HOSTFXR_DIRECTORY_NOT_FOUND_MSG,
|
||||
struHostFxrPath.QueryStr(),
|
||||
hr);
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
// Find all folders under host\\fxr\\ for version numbers.
|
||||
hr = struHostFxrSearchExpression.Copy(struHostFxrPath);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = struHostFxrSearchExpression.Append(L"\\*");
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
// As we use the logic from core-setup, we are opting to use std here.
|
||||
HOSTFXR_UTILITY::FindDotNetFolders(struHostFxrSearchExpression.QueryStr(), &vVersionFolders);
|
||||
|
||||
if (vVersionFolders.size() == 0)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(ERROR_BAD_ENVIRONMENT);
|
||||
UTILITY::LogEventF(hEventLog,
|
||||
EVENTLOG_ERROR_TYPE,
|
||||
ASPNETCORE_EVENT_HOSTFXR_DIRECTORY_NOT_FOUND,
|
||||
ASPNETCORE_EVENT_HOSTFXR_DIRECTORY_NOT_FOUND_MSG,
|
||||
struHostFxrPath.QueryStr(),
|
||||
hr);
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = FindHighestDotNetVersion(vVersionFolders, &struHighestDotnetVersion);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (FAILED(hr = struHostFxrPath.Append(L"\\"))
|
||||
|| FAILED(hr = struHostFxrPath.Append(struHighestDotnetVersion.QueryStr()))
|
||||
|| FAILED(hr = struHostFxrPath.Append(L"\\hostfxr.dll")))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (!UTILITY::CheckIfFileExists(struHostFxrPath.QueryStr()))
|
||||
{
|
||||
// ASPNETCORE_EVENT_HOSTFXR_DLL_NOT_FOUND_MSG
|
||||
hr = HRESULT_FROM_WIN32(ERROR_FILE_INVALID);
|
||||
UTILITY::LogEventF(hEventLog,
|
||||
EVENTLOG_ERROR_TYPE,
|
||||
ASPNETCORE_EVENT_HOSTFXR_DLL_NOT_FOUND,
|
||||
ASPNETCORE_EVENT_HOSTFXR_DLL_NOT_FOUND_MSG,
|
||||
struHostFxrPath.QueryStr(),
|
||||
hr);
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (FAILED(hr = pStruAbsolutePathToHostfxr->Copy(struHostFxrPath)))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
Finished:
|
||||
return hr;
|
||||
return std::make_optional(hostFxrPath);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -559,10 +396,8 @@ Finished:
|
|||
// worker process bitness.
|
||||
// Returns true if a valid dotnet was found, else false.
|
||||
//
|
||||
BOOL
|
||||
HOSTFXR_UTILITY::InvokeWhereToFindDotnet(
|
||||
_Inout_ STRU* pStruAbsolutePathToDotnet
|
||||
)
|
||||
std::optional<fs::path>
|
||||
HOSTFXR_UTILITY::InvokeWhereToFindDotnet()
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
// Arguments to call where.exe
|
||||
|
|
@ -586,16 +421,13 @@ HOSTFXR_UTILITY::InvokeWhereToFindDotnet(
|
|||
INT prevIndex = 0;
|
||||
BOOL fProcessCreationResult = FALSE;
|
||||
BOOL fResult = FALSE;
|
||||
std::optional<fs::path> result;
|
||||
|
||||
// Set the security attributes for the read/write pipe
|
||||
securityAttributes.nLength = sizeof(securityAttributes);
|
||||
securityAttributes.lpSecurityDescriptor = NULL;
|
||||
securityAttributes.bInheritHandle = TRUE;
|
||||
|
||||
// Reset the path to dotnet as we will be using whether the string is
|
||||
// empty or not as state
|
||||
pStruAbsolutePathToDotnet->Reset();
|
||||
|
||||
// Create a read/write pipe that will be used for reading the result of where.exe
|
||||
if (!CreatePipe(&hStdOutReadPipe, &hStdOutWritePipe, &securityAttributes, 0))
|
||||
{
|
||||
|
|
@ -736,10 +568,7 @@ HOSTFXR_UTILITY::InvokeWhereToFindDotnet(
|
|||
fIsCurrentProcess64Bit == (dwBinaryType == SCS_64BIT_BINARY))
|
||||
{
|
||||
// The bitness of dotnet matched with the current worker process bitness.
|
||||
if (FAILED(hr = pStruAbsolutePathToDotnet->Copy(struDotnetSubstring)))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
result = std::make_optional(struDotnetSubstring.QueryStr());
|
||||
fResult = TRUE;
|
||||
break;
|
||||
}
|
||||
|
|
@ -768,71 +597,21 @@ Finished:
|
|||
SysFreeString(pwzDotnetName);
|
||||
}
|
||||
|
||||
return fResult;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
HRESULT
|
||||
HOSTFXR_UTILITY::GetAbsolutePathToDotnetFromProgramFiles(
|
||||
_Inout_ STRU* pStruAbsolutePathToDotnet
|
||||
)
|
||||
std::optional<fs::path>
|
||||
HOSTFXR_UTILITY::GetAbsolutePathToDotnetFromProgramFiles()
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
BOOL fFound = FALSE;
|
||||
DWORD dwNumBytesRead = 0;
|
||||
DWORD dwPathSize = MAX_PATH;
|
||||
STRU struDotnetSubstring;
|
||||
|
||||
while (!fFound)
|
||||
{
|
||||
if (FAILED(hr = struDotnetSubstring.Resize(dwPathSize)))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
dwNumBytesRead = GetEnvironmentVariable(L"ProgramFiles", struDotnetSubstring.QueryStr(), dwPathSize);
|
||||
if (dwNumBytesRead == 0)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
goto Finished;
|
||||
}
|
||||
else if (dwNumBytesRead >= dwPathSize)
|
||||
{
|
||||
//
|
||||
// The path to ProgramFiles should never be this long, but resize and try again.
|
||||
dwPathSize *= 2 + 30; // for dotnet substring
|
||||
}
|
||||
else
|
||||
{
|
||||
if (FAILED(hr = struDotnetSubstring.SyncWithBuffer()) ||
|
||||
FAILED(hr = struDotnetSubstring.Append(L"\\dotnet\\dotnet.exe")))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
if (!UTILITY::CheckIfFileExists(struDotnetSubstring.QueryStr()))
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
goto Finished;
|
||||
}
|
||||
if (FAILED(hr = pStruAbsolutePathToDotnet->Copy(struDotnetSubstring)))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
fFound = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
Finished:
|
||||
return hr;
|
||||
const auto programFilesDotnet = fs::path(ExpandEnvironmentVariables(L"%ProgramFiles%")) / "dotnet" / "dotnet.exe";
|
||||
return is_regular_file(programFilesDotnet) ? std::make_optional(programFilesDotnet) : std::nullopt;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
std::wstring
|
||||
HOSTFXR_UTILITY::FindHighestDotNetVersion(
|
||||
_In_ std::vector<std::wstring> vFolders,
|
||||
_Out_ STRU *pstrResult
|
||||
_In_ std::vector<std::wstring> & vFolders
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
fx_ver_t max_ver(-1, -1, -1);
|
||||
for (const auto& dir : vFolders)
|
||||
{
|
||||
|
|
@ -844,16 +623,13 @@ HOSTFXR_UTILITY::FindHighestDotNetVersion(
|
|||
}
|
||||
}
|
||||
|
||||
hr = pstrResult->Copy(max_ver.as_str().c_str());
|
||||
|
||||
// we check FAILED(hr) outside of function
|
||||
return hr;
|
||||
return max_ver.as_str();
|
||||
}
|
||||
|
||||
VOID
|
||||
HOSTFXR_UTILITY::FindDotNetFolders(
|
||||
_In_ PCWSTR pszPath,
|
||||
_Out_ std::vector<std::wstring> *pvFolders
|
||||
_Out_ std::vector<std::wstring> & pvFolders
|
||||
)
|
||||
{
|
||||
HANDLE handle = NULL;
|
||||
|
|
@ -868,8 +644,34 @@ HOSTFXR_UTILITY::FindDotNetFolders(
|
|||
do
|
||||
{
|
||||
std::wstring folder(data.cFileName);
|
||||
pvFolders->push_back(folder);
|
||||
pvFolders.push_back(folder);
|
||||
} while (FindNextFileW(handle, &data));
|
||||
|
||||
FindClose(handle);
|
||||
}
|
||||
|
||||
std::wstring
|
||||
HOSTFXR_UTILITY::ExpandEnvironmentVariables(const std::wstring & str)
|
||||
{
|
||||
DWORD requestedSize = ExpandEnvironmentStringsW(str.c_str(), nullptr, 0);
|
||||
if (requestedSize == 0)
|
||||
{
|
||||
throw std::system_error(GetLastError(), std::system_category(), "ExpandEnvironmentVariables");
|
||||
}
|
||||
|
||||
std::wstring expandedStr;
|
||||
do
|
||||
{
|
||||
expandedStr.resize(requestedSize);
|
||||
requestedSize = ExpandEnvironmentStringsW(str.c_str(), &expandedStr[0], requestedSize);
|
||||
if (requestedSize == 0)
|
||||
{
|
||||
throw std::system_error(GetLastError(), std::system_category(), "ExpandEnvironmentVariables");
|
||||
}
|
||||
} while (expandedStr.size() != requestedSize);
|
||||
|
||||
// trim null character as ExpandEnvironmentStringsW returns size including null character
|
||||
expandedStr.resize(requestedSize - 1);
|
||||
|
||||
return expandedStr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
#include "precomp.h"
|
||||
|
||||
#include <vector>
|
||||
#include <experimental/filesystem>
|
||||
#include <optional>
|
||||
|
||||
typedef INT(*hostfxr_get_native_search_directories_fn) (CONST INT argc, CONST PCWSTR* argv, PWSTR buffer, DWORD buffer_size, DWORD* required_buffer_size);
|
||||
typedef INT(*hostfxr_main_fn) (CONST DWORD argc, CONST PCWSTR argv[]);
|
||||
|
|
@ -42,7 +44,7 @@ public:
|
|||
static
|
||||
BOOL
|
||||
IsDotnetExecutable(
|
||||
STRU* struExecutablePath
|
||||
_In_ const std::experimental::filesystem::path & dotnetPath
|
||||
);
|
||||
|
||||
static
|
||||
|
|
@ -58,47 +60,41 @@ public:
|
|||
_Out_ BSTR **ppwzArgv
|
||||
);
|
||||
|
||||
static
|
||||
HRESULT
|
||||
GetAbsolutePathToDotnet(
|
||||
STRU* pStruAbsolutePathToDotnet
|
||||
);
|
||||
|
||||
static
|
||||
HRESULT
|
||||
GetAbsolutePathToHostFxr(
|
||||
_In_ STRU* pStruAbsolutePathToDotnet,
|
||||
_In_ HANDLE hEventLog,
|
||||
_Out_ STRU* pStruAbsolutePathToHostfxr
|
||||
);
|
||||
|
||||
static
|
||||
BOOL
|
||||
InvokeWhereToFindDotnet(
|
||||
_Inout_ STRU* pStruAbsolutePathToDotnet
|
||||
);
|
||||
|
||||
static
|
||||
HRESULT
|
||||
GetAbsolutePathToDotnetFromProgramFiles(
|
||||
_Inout_ STRU* pStruAbsolutePathToDotnet
|
||||
);
|
||||
|
||||
static
|
||||
HRESULT
|
||||
FindHighestDotNetVersion(
|
||||
_In_ std::vector<std::wstring> vFolders,
|
||||
_Out_ STRU *pstrResult
|
||||
);
|
||||
|
||||
static
|
||||
VOID
|
||||
FindDotNetFolders(
|
||||
_In_ PCWSTR pszPath,
|
||||
_Out_ std::vector<std::wstring> *pvFolders
|
||||
_Out_ std::vector<std::wstring> & pvFolders
|
||||
);
|
||||
|
||||
HOSTFXR_UTILITY();
|
||||
~HOSTFXR_UTILITY();
|
||||
static
|
||||
std::wstring
|
||||
FindHighestDotNetVersion(
|
||||
_In_ std::vector<std::wstring> & vFolders
|
||||
);
|
||||
|
||||
static
|
||||
std::optional<std::experimental::filesystem::path>
|
||||
GetAbsolutePathToHostFxr(
|
||||
_In_ const std::experimental::filesystem::path & dotnetPath,
|
||||
_In_ HANDLE hEventLog
|
||||
);
|
||||
|
||||
static
|
||||
std::optional<std::experimental::filesystem::path>
|
||||
GetAbsolutePathToDotnetFromProgramFiles();
|
||||
|
||||
static
|
||||
std::optional<std::experimental::filesystem::path>
|
||||
InvokeWhereToFindDotnet();
|
||||
|
||||
static
|
||||
std::optional<std::experimental::filesystem::path>
|
||||
GetAbsolutePathToDotnet(
|
||||
_In_ const std::experimental::filesystem::path & requestedPath
|
||||
);
|
||||
|
||||
static
|
||||
std::wstring ExpandEnvironmentVariables(const std::wstring & str);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ HRESULT HOSTFXR_OPTIONS::Create(
|
|||
goto Finished;
|
||||
}
|
||||
}
|
||||
else if (HOSTFXR_UTILITY::IsDotnetExecutable(&struExeLocation))
|
||||
else if (HOSTFXR_UTILITY::IsDotnetExecutable(struExeLocation.QueryStr()))
|
||||
{
|
||||
if (FAILED(hr = HOSTFXR_UTILITY::ParseHostfxrArguments(
|
||||
pcwzArguments,
|
||||
|
|
|
|||
|
|
@ -36,12 +36,17 @@
|
|||
#define ASPNETCORE_EVENT_RECYCLE_CONFIGURATION_MSG L"Application '%s' was recycled due to configuration change"
|
||||
#define ASPNETCORE_EVENT_RECYCLE_FAILURE_CONFIGURATION_MSG L"Failed to recycle application due to a configuration change at '%s'. Recycling worker process."
|
||||
#define ASPNETCORE_EVENT_MODULE_DISABLED_MSG L"AspNetCore Module is disabled"
|
||||
#define ASPNETCORE_EVENT_INPROCESS_FULL_FRAMEWORK_APP_LEVEL EVENTLOG_ERROR_TYPE
|
||||
#define ASPNETCORE_EVENT_INPROCESS_FULL_FRAMEWORK_APP_MSG L"Application '%s' was compiled for .NET Framework. Please compile for .NET core to run the inprocess application or change the process mode to out of process. ErrorCode = '0x%x'."
|
||||
#define ASPNETCORE_EVENT_PORTABLE_APP_DOTNET_MISSING_MSG L"Could not find dotnet.exe on the system PATH environment variable for portable application '%s'. Check that a valid path to dotnet is on the PATH and the bitness of dotnet matches the bitness of the IIS worker process. ErrorCode = '0x%x'."
|
||||
#define ASPNETCORE_EVENT_HOSTFXR_DIRECTORY_NOT_FOUND_LEVEL EVENTLOG_ERROR_TYPE
|
||||
#define ASPNETCORE_EVENT_HOSTFXR_DIRECTORY_NOT_FOUND_MSG L"Could not find the hostfxr directory '%s' in the dotnet directory. ErrorCode = '0x%x'."
|
||||
#define ASPNETCORE_EVENT_HOSTFXR_DLL_NOT_FOUND_LEVEL EVENTLOG_ERROR_TYPE
|
||||
#define ASPNETCORE_EVENT_HOSTFXR_DLL_NOT_FOUND_MSG L"Could not find hostfxr.dll in '%s'. ErrorCode = '0x%x'."
|
||||
#define ASPNETCORE_EVENT_APPLICATION_EXE_NOT_FOUND_LEVEL EVENTLOG_ERROR_TYPE
|
||||
#define ASPNETCORE_EVENT_APPLICATION_EXE_NOT_FOUND_MSG L"Could not find application executable in '%s'. ErrorCode = '0x%x'."
|
||||
#define ASPNETCORE_EVENT_INPROCESS_THREAD_EXCEPTION_MSG L"Application '%s' with physical root '%s' hit unexpected managed exception, ErrorCode = '0x%x. Please check the stderr logs for more information."
|
||||
#define ASPNETCORE_EVENT_INVALID_PROCESS_PATH_LEVEL EVENTLOG_ERROR_TYPE
|
||||
#define ASPNETCORE_EVENT_INVALID_PROCESS_PATH_MSG L"Invalid or unknown processPath provided in web.config: processPath = %s, ErrorCode = '0x%x'."
|
||||
#define ASPNETCORE_EVENT_INPROCESS_RH_MISSING_MSG L"Could not find the assembly '%s' for in-process application. Please confirm the Microsoft.AspNetCore.Server.IIS package is referenced in your application."
|
||||
#define ASPNETCORE_EVENT_OUT_OF_PROCESS_RH_MISSING_MSG L"Could not find the assembly '%s' for out-of-process application. Please confirm the assembly is installed correctly for IIS or IISExpress."
|
||||
|
|
|
|||
|
|
@ -38,5 +38,6 @@
|
|||
#include "resources.h"
|
||||
#include "aspnetcore_msg.h"
|
||||
#include "hostfxr_utility.h"
|
||||
#include "EventLog.h"
|
||||
#include "hostfxroptions.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "debugutil.h"
|
||||
|
||||
// static
|
||||
HRESULT
|
||||
|
|
@ -569,9 +570,12 @@ UTILITY::LogEvent(
|
|||
);
|
||||
}
|
||||
|
||||
if (dwEventInfoType == EVENTLOG_ERROR_TYPE)
|
||||
STACK_STRA(converted, 256);
|
||||
if (converted.CopyW(pstrMsg))
|
||||
{
|
||||
fwprintf(stderr, L"ERROR: %s\n", pstrMsg);
|
||||
DebugPrintf(
|
||||
dwEventInfoType == EVENTLOG_ERROR_TYPE ? ASPNETCORE_DEBUG_FLAG_ERROR : ASPNETCORE_DEBUG_FLAG_INFO,
|
||||
"Event Log: %s", converted.QueryStr());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,6 @@
|
|||
#include "debugutil.h"
|
||||
|
||||
// Common lib
|
||||
#include "hostfxr_utility.h"
|
||||
#include "requesthandler.h"
|
||||
#include "utility.h"
|
||||
#include "application.h"
|
||||
|
|
|
|||
|
|
@ -84,7 +84,6 @@ TEST(ParseHostFxrArguments, ProvideNoArgs_InvalidArgs)
|
|||
TEST(GetAbsolutePathToDotnetFromProgramFiles, BackupWorks)
|
||||
{
|
||||
STRU struAbsolutePathToDotnet;
|
||||
HRESULT hr = S_OK;
|
||||
BOOL fDotnetInProgramFiles;
|
||||
BOOL is64Bit;
|
||||
BOOL fIsWow64 = FALSE;
|
||||
|
|
@ -109,15 +108,14 @@ TEST(GetAbsolutePathToDotnetFromProgramFiles, BackupWorks)
|
|||
fDotnetInProgramFiles = UTILITY::CheckIfFileExists(L"C:/Program Files (x86)/dotnet/dotnet.exe");
|
||||
}
|
||||
|
||||
hr = HOSTFXR_UTILITY::GetAbsolutePathToDotnetFromProgramFiles(&struAbsolutePathToDotnet);
|
||||
auto dotnetPath = HOSTFXR_UTILITY::GetAbsolutePathToDotnetFromProgramFiles();
|
||||
if (fDotnetInProgramFiles)
|
||||
{
|
||||
EXPECT_EQ(hr, S_OK);
|
||||
EXPECT_TRUE(dotnetPath.has_value());
|
||||
}
|
||||
else
|
||||
{
|
||||
EXPECT_NE(hr, S_OK);
|
||||
EXPECT_TRUE(struAbsolutePathToDotnet.IsEmpty());
|
||||
EXPECT_FALSE(dotnetPath.has_value());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -138,5 +136,5 @@ TEST(GetHostFxrArguments, InvalidParams)
|
|||
&retVal, // arg count
|
||||
&bstrArray); // args array.
|
||||
|
||||
EXPECT_EQ(E_INVALIDARG, hr);
|
||||
}
|
||||
EXPECT_EQ(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), hr);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,9 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
using IISIntegration.FunctionalTests.Utilities;
|
||||
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
||||
using Microsoft.AspNetCore.Testing.xunit;
|
||||
|
|
@ -18,30 +17,22 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
|
|||
[SkipIfIISExpressSchemaMissingInProcess]
|
||||
public class StartupTests : IISFunctionalTestBase
|
||||
{
|
||||
private readonly string _dotnetLocation = DotNetMuxer.MuxerPathOrDefault();
|
||||
|
||||
public StartupTests(ITestOutputHelper output) : base(output)
|
||||
{
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[ConditionalFact]
|
||||
public async Task ExpandEnvironmentVariableInWebConfig()
|
||||
{
|
||||
var dotnetLocation = DotNetMuxer.MuxerPathOrDefault();
|
||||
var deploymentParameters = GetBaseDeploymentParameters();
|
||||
|
||||
// Point to dotnet installed in user profile.
|
||||
deploymentParameters.EnvironmentVariables["DotnetPath"] = dotnetLocation;
|
||||
|
||||
var deploymentResult = await DeployAsync(deploymentParameters);
|
||||
|
||||
Helpers.ModifyAspNetCoreSectionInWebConfig(deploymentResult, "processPath", "%DotnetPath%");
|
||||
|
||||
var response = await deploymentResult.RetryingHttpClient.GetAsync("HelloWorld");
|
||||
|
||||
var responseText = await response.Content.ReadAsStringAsync();
|
||||
Assert.Equal("Hello World", responseText);
|
||||
await AssertStarts(
|
||||
deploymentResult => Helpers.ModifyAspNetCoreSectionInWebConfig(deploymentResult, "processPath", "%DotnetPath%"),
|
||||
deploymentParameters => deploymentParameters.EnvironmentVariables["DotnetPath"] = _dotnetLocation);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[ConditionalFact]
|
||||
public async Task InvalidProcessPath_ExpectServerError()
|
||||
{
|
||||
var dotnetLocation = "bogus";
|
||||
|
|
@ -60,6 +51,51 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
|
|||
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
public async Task StartsWithDotnetLocationWithoutExe()
|
||||
{
|
||||
var dotnetLocationWithoutExtension = _dotnetLocation.Substring(0, _dotnetLocation.LastIndexOf("."));
|
||||
|
||||
await AssertStarts(
|
||||
deploymentResult => Helpers.ModifyAspNetCoreSectionInWebConfig(deploymentResult, "processPath", dotnetLocationWithoutExtension));
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
public async Task StartsWithDotnetLocationUppercase()
|
||||
{
|
||||
var dotnetLocationWithoutExtension = _dotnetLocation.Substring(0, _dotnetLocation.LastIndexOf(".")).ToUpperInvariant();
|
||||
|
||||
await AssertStarts(
|
||||
deploymentResult => Helpers.ModifyAspNetCoreSectionInWebConfig(deploymentResult, "processPath", dotnetLocationWithoutExtension));
|
||||
}
|
||||
|
||||
[ConditionalTheory]
|
||||
[InlineData("dotnet")]
|
||||
[InlineData("dotnet.EXE")]
|
||||
public async Task StartsWithDotnetOnThePath(string path)
|
||||
{
|
||||
await AssertStarts(
|
||||
deploymentResult => Helpers.ModifyAspNetCoreSectionInWebConfig(deploymentResult, "processPath", path),
|
||||
deploymentParameters => deploymentParameters.EnvironmentVariables["PATH"] = Path.GetDirectoryName(_dotnetLocation));
|
||||
}
|
||||
|
||||
private async Task AssertStarts(Action<IISDeploymentResult> postDeploy, Action<DeploymentParameters> preDeploy = null)
|
||||
{
|
||||
var deploymentParameters = GetBaseDeploymentParameters();
|
||||
|
||||
preDeploy?.Invoke(deploymentParameters);
|
||||
|
||||
var deploymentResult = await DeployAsync(deploymentParameters);
|
||||
|
||||
postDeploy?.Invoke(deploymentResult);
|
||||
|
||||
var response = await deploymentResult.RetryingHttpClient.GetAsync("HelloWorld");
|
||||
|
||||
var responseText = await response.Content.ReadAsStringAsync();
|
||||
Assert.Equal("Hello World", responseText);
|
||||
}
|
||||
|
||||
|
||||
public static TestMatrix TestVariants
|
||||
=> TestMatrix.ForServers(ServerType.IISExpress)
|
||||
.WithTfms(Tfm.NetCoreApp22)
|
||||
|
|
|
|||
Loading…
Reference in New Issue