Merge pull request #1335 from dotnet-maestro-bot/merge/release/2.2-to-master

[automated] Merge branch 'release/2.2' => 'master'
This commit is contained in:
Pavel Krymets 2018-08-27 12:31:41 -07:00 committed by GitHub
commit 9f82ec3c18
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 394 additions and 172 deletions

View File

@ -108,7 +108,7 @@ HandlerResolver::LoadRequestHandlerAssembly(IHttpApplication &pApplication, Shim
}
}
LOG_INFOF("Loading request handler: %S", handlerDllPath.c_str());
LOG_INFOF(L"Loading request handler: '%ls'", handlerDllPath.c_str());
hRequestHandlerDll = LoadLibrary(handlerDllPath.c_str());
if (preventUnload)

View File

@ -34,7 +34,7 @@ APPLICATION_INFO::GetOrCreateApplication(
{
if (m_pApplication->QueryStatus() == RECYCLED)
{
LOG_INFO("Application went offline");
LOG_INFO(L"Application went offline");
// Call to wait for application to complete stopping
m_pApplication->Stop(/* fServerInitiated */ false);
@ -50,14 +50,14 @@ APPLICATION_INFO::GetOrCreateApplication(
if (AppOfflineApplication::ShouldBeStarted(httpApplication))
{
LOG_INFO("Detected app_offline file, creating polling application");
LOG_INFO(L"Detected app_offline file, creating polling application");
m_pApplication.reset(new AppOfflineApplication(httpApplication));
}
else
{
FINISHED_IF_FAILED(m_handlerResolver.GetApplicationFactory(httpApplication, m_pApplicationFactory));
LOG_INFO("Creating handler application");
LOG_INFO(L"Creating handler application");
IAPPLICATION * newApplication;
FINISHED_IF_FAILED(m_pApplicationFactory->Execute(
&m_pServer,
@ -97,7 +97,7 @@ APPLICATION_INFO::ShutDownApplication(bool fServerInitiated)
if (m_pApplication)
{
LOG_ERRORF("Stopping application %S", QueryApplicationInfoKey().c_str());
LOG_ERRORF(L"Stopping application '%ls'", QueryApplicationInfoKey().c_str());
m_pApplication ->Stop(fServerInitiated);
m_pApplication = nullptr;
m_pApplicationFactory = nullptr;

View File

@ -142,7 +142,7 @@ APPLICATION_MANAGER::RecycleApplicationFromManager(
}
catch (...)
{
LOG_ERRORF("Failed to stop application %S", application->QueryApplicationInfoKey().c_str());
LOG_ERRORF(L"Failed to stop application '%ls'", application->QueryApplicationInfoKey().c_str());
OBSERVE_CAUGHT_EXCEPTION();
// Failed to recycle an application. Log an event

View File

@ -22,7 +22,7 @@ ASPNET_CORE_GLOBAL_MODULE::OnGlobalStopListening(
{
UNREFERENCED_PARAMETER(pProvider);
LOG_INFO("ASPNET_CORE_GLOBAL_MODULE::OnGlobalStopListening");
LOG_INFO(L"ASPNET_CORE_GLOBAL_MODULE::OnGlobalStopListening");
if (g_fInShutdown)
{
@ -56,7 +56,7 @@ ASPNET_CORE_GLOBAL_MODULE::OnGlobalConfigurationChange(
// Retrieve the path that has changed.
PCWSTR pwszChangePath = pProvider->GetChangePath();
LOG_INFOF("ASPNET_CORE_GLOBAL_MODULE::OnGlobalConfigurationChange %S", pwszChangePath);
LOG_INFOF(L"ASPNET_CORE_GLOBAL_MODULE::OnGlobalConfigurationChange '%ls'", pwszChangePath);
// Test for an error.
if (NULL != pwszChangePath &&

View File

@ -20,7 +20,7 @@ public:
VOID Terminate()
{
LOG_INFO("ASPNET_CORE_GLOBAL_MODULE::Terminate");
LOG_INFO(L"ASPNET_CORE_GLOBAL_MODULE::Terminate");
// Remove the class from memory.
delete this;
}

View File

@ -42,7 +42,7 @@ EventLog::LogEvent(
);
}
DebugPrintf(dwEventInfoType == EVENTLOG_ERROR_TYPE ? ASPNETCORE_DEBUG_FLAG_ERROR : ASPNETCORE_DEBUG_FLAG_INFO, "Event Log: %S \r\nEnd Event Log Message.", pstrMsg);
DebugPrintfW(dwEventInfoType == EVENTLOG_ERROR_TYPE ? ASPNETCORE_DEBUG_FLAG_ERROR : ASPNETCORE_DEBUG_FLAG_INFO, L"Event Log: '%ls' \r\nEnd Event Log Message.", pstrMsg);
}
VOID

View File

@ -132,7 +132,7 @@ HRESULT PipeOutputManager::Stop()
if (!LOG_LAST_ERROR_IF(GetExitCodeThread(m_hErrThread, &dwThreadStatus) == 0) &&
dwThreadStatus == STILL_ACTIVE)
{
LOG_WARN("Thread reading stdout/err hit timeout, forcibly closing thread.");
LOG_WARN(L"Thread reading stdout/err hit timeout, forcibly closing thread.");
TerminateThread(m_hErrThread, STATUS_CONTROL_C_EXIT);
}
}

View File

@ -23,7 +23,7 @@ HRESULT
PrintDebugHeader()
{
// Major, minor are stored in dwFileVersionMS field and patch, build in dwFileVersionLS field as pair of 32 bit numbers
DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO, "Initializing logs for %S. %S. %S.",
DebugPrintfW(ASPNETCORE_DEBUG_FLAG_INFO, L"Initializing logs for '%ls'. %ls. %ls.",
GetModuleName().c_str(),
GetProcessIdString().c_str(),
GetVersionInfoString().c_str()
@ -86,7 +86,7 @@ std::wstring
GetModuleName()
{
WCHAR path[MAX_PATH];
LOG_LAST_ERROR_IF(GetModuleFileName(g_hModule, path, sizeof(path)));
LOG_LAST_ERROR_IF(!GetModuleFileName(g_hModule, path, sizeof(path)));
return path;
}
@ -146,7 +146,7 @@ bool CreateDebugLogFile(const std::wstring &debugOutputFile)
{
if (g_logFile != INVALID_HANDLE_VALUE)
{
LOG_INFOF("Switching debug log files to %S", debugOutputFile.c_str());
LOG_INFOF(L"Switching debug log files to '%ls'", debugOutputFile.c_str());
}
SRWExclusiveLock lock(g_logFileLock);
@ -296,19 +296,29 @@ IsEnabled(
return ( dwFlag & DEBUG_FLAGS_VAR );
}
void WriteFileEncoded(UINT codePage, HANDLE hFile, const LPCWSTR szString)
{
DWORD nBytesWritten = 0;
auto const encodedByteCount = WideCharToMultiByte(codePage, 0, szString, -1, nullptr, 0, nullptr, nullptr);
auto encodedBytes = std::shared_ptr<CHAR[]>(new CHAR[encodedByteCount]);
WideCharToMultiByte(codePage, 0, szString, -1, encodedBytes.get(), encodedByteCount, nullptr, nullptr);
WriteFile(hFile, encodedBytes.get(), encodedByteCount - 1, &nBytesWritten, nullptr);
}
VOID
DebugPrint(
DebugPrintW(
DWORD dwFlag,
const LPCSTR szString
const LPCWSTR szString
)
{
STACK_STRA (strOutput, 256);
STACK_STRU (strOutput, 256);
HRESULT hr = S_OK;
if ( IsEnabled( dwFlag ) )
{
hr = strOutput.SafeSnprintf(
"[%s] %s\r\n",
hr = strOutput.SafeSnwprintf(
L"[%S] %s\r\n",
DEBUG_LABEL_VAR, szString );
if (FAILED (hr))
@ -316,22 +326,68 @@ DebugPrint(
return;
}
OutputDebugStringA( strOutput.QueryStr() );
DWORD nBytesWritten = 0;
if (IsEnabled(ASPNETCORE_DEBUG_FLAG_CONSOLE))
OutputDebugString( strOutput.QueryStr() );
if (IsEnabled(ASPNETCORE_DEBUG_FLAG_CONSOLE) || g_logFile != INVALID_HANDLE_VALUE)
{
auto outputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
WriteFile(outputHandle, strOutput.QueryStr(), strOutput.QueryCB(), &nBytesWritten, nullptr);
if (IsEnabled(ASPNETCORE_DEBUG_FLAG_CONSOLE))
{
WriteFileEncoded(GetConsoleOutputCP(), GetStdHandle(STD_OUTPUT_HANDLE), strOutput.QueryStr());
}
if (g_logFile != INVALID_HANDLE_VALUE)
{
SRWExclusiveLock lock(g_logFileLock);
SetFilePointer(g_logFile, 0, nullptr, FILE_END);
WriteFileEncoded(CP_UTF8, g_logFile, strOutput.QueryStr());
FlushFileBuffers(g_logFile);
}
}
}
}
VOID
DebugPrintfW(
DWORD dwFlag,
const LPCWSTR szFormat,
...
)
{
STACK_STRU (strCooked,256);
va_list args;
HRESULT hr = S_OK;
if ( IsEnabled( dwFlag ) )
{
va_start( args, szFormat );
hr = strCooked.SafeVsnwprintf(szFormat, args );
va_end( args );
if (FAILED (hr))
{
return;
}
if (g_logFile != INVALID_HANDLE_VALUE)
{
SRWExclusiveLock lock(g_logFileLock);
DebugPrintW( dwFlag, strCooked.QueryStr() );
}
}
SetFilePointer(g_logFile, 0, nullptr, FILE_END);
WriteFile(g_logFile, strOutput.QueryStr(), strOutput.QueryCB(), &nBytesWritten, nullptr);
FlushFileBuffers(g_logFile);
}
VOID
DebugPrint(
DWORD dwFlag,
const LPCSTR szString
)
{
STACK_STRU (strOutput, 256);
if ( IsEnabled( dwFlag ) )
{
strOutput.CopyA(szString);
DebugPrintW(dwFlag, strOutput.QueryStr());
}
}

View File

@ -14,14 +14,14 @@
#define ASPNETCORE_DEBUG_FLAG_CONSOLE 0x00000008
#define ASPNETCORE_DEBUG_FLAG_FILE 0x00000010
#define LOG_INFO(...) DebugPrint(ASPNETCORE_DEBUG_FLAG_INFO, __VA_ARGS__)
#define LOG_INFOF(...) DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO, __VA_ARGS__)
#define LOG_INFO(...) DebugPrintW(ASPNETCORE_DEBUG_FLAG_INFO, __VA_ARGS__)
#define LOG_INFOF(...) DebugPrintfW(ASPNETCORE_DEBUG_FLAG_INFO, __VA_ARGS__)
#define LOG_WARN(...) DebugPrint(ASPNETCORE_DEBUG_FLAG_WARNING, __VA_ARGS__)
#define LOG_WARNF(...) DebugPrintf(ASPNETCORE_DEBUG_FLAG_WARNING, __VA_ARGS__)
#define LOG_WARN(...) DebugPrintW(ASPNETCORE_DEBUG_FLAG_WARNING, __VA_ARGS__)
#define LOG_WARNF(...) DebugPrintfW(ASPNETCORE_DEBUG_FLAG_WARNING, __VA_ARGS__)
#define LOG_ERROR(...) DebugPrint(ASPNETCORE_DEBUG_FLAG_ERROR, __VA_ARGS__)
#define LOG_ERRORF(...) DebugPrintf(ASPNETCORE_DEBUG_FLAG_ERROR, __VA_ARGS__)
#define LOG_ERROR(...) DebugPrintW(ASPNETCORE_DEBUG_FLAG_ERROR, __VA_ARGS__)
#define LOG_ERRORF(...) DebugPrintfW(ASPNETCORE_DEBUG_FLAG_ERROR, __VA_ARGS__)
VOID
DebugInitialize(HMODULE hModule);
@ -37,6 +37,20 @@ IsEnabled(
DWORD dwFlag
);
VOID
DebugPrintW(
DWORD dwFlag,
LPCWSTR szString
);
VOID
DebugPrintfW(
DWORD dwFlag,
LPCWSTR szFormat,
...
);
VOID
DebugPrint(
DWORD dwFlag,

View File

@ -23,19 +23,16 @@ HOSTFXR_UTILITY::GetHostFxrParameters(
std::vector<std::wstring> &arguments
)
{
LOG_INFOF("Resolving hostfxr parameters for application: '%S' arguments: '%S' path: '%S'",
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("Expanded hostfxr parameters for application: '%S' arguments: '%S'",
expandedProcessPath.c_str(),
expandedApplicationArguments.c_str());
LOG_INFOF("Known dotnet.exe location: '%S'", dotnetExePath.c_str());
LOG_INFOF(L"Known dotnet.exe location: '%ls'", dotnetExePath.c_str());
if (!expandedProcessPath.has_extension())
{
@ -50,7 +47,12 @@ HOSTFXR_UTILITY::GetHostFxrParameters(
// Check if the absolute path is to dotnet or not.
if (IsDotnetExecutable(expandedProcessPath))
{
LOG_INFOF("Process path '%S' is dotnet, treating application as portable", expandedProcessPath.c_str());
LOG_INFOF(L"Process path '%ls' is dotnet, treating application as portable", expandedProcessPath.c_str());
if (applicationArguments.empty())
{
throw StartupParametersResolutionException(L"Application arguments are empty.");
}
if (dotnetExePath.empty())
{
@ -59,16 +61,16 @@ HOSTFXR_UTILITY::GetHostFxrParameters(
hostFxrDllPath = GetAbsolutePathToHostFxr(dotnetExePath);
ParseHostfxrArguments(
arguments.push_back(dotnetExePath);
AppendArguments(
expandedApplicationArguments,
dotnetExePath,
applicationPhysicalPath,
arguments,
true);
}
else
{
LOG_INFOF("Process path '%S' is not dotnet, treating application as standalone or portable with bootstrapper", expandedProcessPath.c_str());
LOG_INFOF(L"Process path '%ls' is not dotnet, treating application as standalone or portable with bootstrapper", expandedProcessPath.c_str());
auto executablePath = expandedProcessPath;
@ -87,21 +89,23 @@ HOSTFXR_UTILITY::GetHostFxrParameters(
auto applicationDllPath = executablePath;
applicationDllPath.replace_extension(".dll");
LOG_INFOF("Checking application.dll at %S", applicationDllPath.c_str());
LOG_INFOF(L"Checking application.dll at '%ls'", applicationDllPath.c_str());
if (!is_regular_file(applicationDllPath))
{
throw StartupParametersResolutionException(format(L"Application .dll was not found at %s", applicationDllPath.c_str()));
}
hostFxrDllPath = executablePath.parent_path() / "hostfxr.dll";
LOG_INFOF("Checking hostfxr.dll at %S", hostFxrDllPath.c_str());
LOG_INFOF(L"Checking hostfxr.dll at '%ls'", hostFxrDllPath.c_str());
if (is_regular_file(hostFxrDllPath))
{
LOG_INFOF("hostfxr.dll found app local at '%S', treating application as standalone", hostFxrDllPath.c_str());
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("hostfxr.dll found app local at '%S', treating application as portable with launcher", hostFxrDllPath.c_str());
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
@ -109,13 +113,15 @@ HOSTFXR_UTILITY::GetHostFxrParameters(
{
dotnetExePath = GetAbsolutePathToDotnet(applicationPhysicalPath, L"dotnet");
}
executablePath = dotnetExePath;
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);
}
ParseHostfxrArguments(
applicationDllPath.generic_wstring() + L" " + expandedApplicationArguments,
executablePath,
AppendArguments(
expandedApplicationArguments,
applicationPhysicalPath,
arguments);
}
@ -137,29 +143,49 @@ HOSTFXR_UTILITY::IsDotnetExecutable(const std::filesystem::path & dotnetPath)
}
void
HOSTFXR_UTILITY::ParseHostfxrArguments(
HOSTFXR_UTILITY::AppendArguments(
const std::wstring &applicationArguments,
const fs::path &applicationExePath,
const fs::path &applicationPhysicalPath,
std::vector<std::wstring> &arguments,
bool expandDllPaths
)
{
LOG_INFOF("Resolving hostfxr_main arguments application: '%S' arguments: '%S' path: %S", applicationExePath.c_str(), applicationArguments.c_str(), applicationPhysicalPath.c_str());
arguments = std::vector<std::wstring>();
arguments.push_back(applicationExePath);
if (applicationArguments.empty())
{
throw StartupParametersResolutionException(L"Application arguments are empty.");
return;
}
// don't throw while trying to expand arguments
std::error_code ec;
// Try to treat entire arguments section as a single path
if (expandDllPaths)
{
fs::path argumentAsPath = applicationArguments;
if (is_regular_file(argumentAsPath, ec))
{
LOG_INFOF(L"Treating '%ls' as a single path argument", applicationArguments.c_str());
arguments.push_back(argumentAsPath);
return;
}
if (argumentAsPath.is_relative())
{
argumentAsPath = applicationPhysicalPath / argumentAsPath;
if (is_regular_file(argumentAsPath, ec))
{
LOG_INFOF(L"Converted argument '%ls' to '%ls'", applicationArguments.c_str(), argumentAsPath.c_str());
arguments.push_back(argumentAsPath);
return;
}
}
}
int argc = 0;
auto pwzArgs = std::unique_ptr<LPWSTR[], LocalFreeDeleter>(CommandLineToArgvW(applicationArguments.c_str(), &argc));
if (!pwzArgs)
{
throw StartupParametersResolutionException(format(L"Unable parse command line arguments '%s' or '%s'", applicationArguments.c_str()));
throw StartupParametersResolutionException(format(L"Unable parse command line arguments '%s'", applicationArguments.c_str()));
}
for (int intArgsProcessed = 0; intArgsProcessed < argc; intArgsProcessed++)
@ -173,9 +199,9 @@ HOSTFXR_UTILITY::ParseHostfxrArguments(
if (argumentAsPath.is_relative())
{
argumentAsPath = applicationPhysicalPath / argumentAsPath;
if (exists(argumentAsPath))
if (is_regular_file(argumentAsPath, ec))
{
LOG_INFOF("Converted argument '%S' to %S", argument.c_str(), argumentAsPath.c_str());
LOG_INFOF(L"Converted argument '%ls' to '%ls'", argument.c_str(), argumentAsPath.c_str());
argument = argumentAsPath;
}
}
@ -183,11 +209,6 @@ HOSTFXR_UTILITY::ParseHostfxrArguments(
arguments.push_back(argument);
}
for (size_t i = 0; i < arguments.size(); i++)
{
LOG_INFOF("Argument[%d] = %S", i, arguments[i].c_str());
}
}
// The processPath ends with dotnet.exe or dotnet
@ -199,7 +220,7 @@ HOSTFXR_UTILITY::GetAbsolutePathToDotnet(
const fs::path & requestedPath
)
{
LOG_INFOF("Resolving absolute path to dotnet.exe from %S", requestedPath.c_str());
LOG_INFOF(L"Resolving absolute path to dotnet.exe from '%ls'", requestedPath.c_str());
auto processPath = requestedPath;
if (processPath.is_relative())
@ -212,7 +233,7 @@ HOSTFXR_UTILITY::GetAbsolutePathToDotnet(
//
if (is_regular_file(processPath))
{
LOG_INFOF("Found dotnet.exe at %S", processPath.c_str());
LOG_INFOF(L"Found dotnet.exe at '%ls'", processPath.c_str());
return processPath;
}
@ -223,7 +244,7 @@ HOSTFXR_UTILITY::GetAbsolutePathToDotnet(
// Only do it if no path is specified
if (requestedPath.has_parent_path())
{
LOG_INFOF("Absolute path to dotnet.exe was not found at %S", requestedPath.c_str());
LOG_INFOF(L"Absolute path to dotnet.exe was not found at '%ls'", requestedPath.c_str());
throw StartupParametersResolutionException(format(L"Could not find dotnet.exe at '%s'", processPath.c_str()));
}
@ -231,7 +252,7 @@ HOSTFXR_UTILITY::GetAbsolutePathToDotnet(
const auto dotnetViaWhere = InvokeWhereToFindDotnet();
if (dotnetViaWhere.has_value())
{
LOG_INFOF("Found dotnet.exe via where.exe invocation at %S", dotnetViaWhere.value().c_str());
LOG_INFOF(L"Found dotnet.exe via where.exe invocation at '%ls'", dotnetViaWhere.value().c_str());
return dotnetViaWhere.value();
}
@ -239,12 +260,12 @@ HOSTFXR_UTILITY::GetAbsolutePathToDotnet(
const auto programFilesLocation = GetAbsolutePathToDotnetFromProgramFiles();
if (programFilesLocation.has_value())
{
LOG_INFOF("Found dotnet.exe in Program Files at %S", programFilesLocation.value().c_str());
LOG_INFOF(L"Found dotnet.exe in Program Files at '%ls'", programFilesLocation.value().c_str());
return programFilesLocation.value();
}
LOG_INFOF("dotnet.exe not found");
LOG_INFOF(L"dotnet.exe not found");
throw StartupParametersResolutionException(format(
L"Could not find dotnet.exe at '%s' or using the system PATH environment variable."
" Check that a valid path to dotnet is on the PATH and the bitness of dotnet matches the bitness of the IIS worker process.",
@ -259,7 +280,7 @@ HOSTFXR_UTILITY::GetAbsolutePathToHostFxr(
std::vector<std::wstring> versionFolders;
const auto hostFxrBase = dotnetPath.parent_path() / "host" / "fxr";
LOG_INFOF("Resolving absolute path to hostfxr.dll from %S", dotnetPath.c_str());
LOG_INFOF(L"Resolving absolute path to hostfxr.dll from '%ls'", dotnetPath.c_str());
if (!is_directory(hostFxrBase))
{
@ -281,7 +302,7 @@ HOSTFXR_UTILITY::GetAbsolutePathToHostFxr(
throw StartupParametersResolutionException(format(L"hostfxr.dll not found at '%s'", hostFxrPath.c_str()));
}
LOG_INFOF("hostfxr.dll located at %S", hostFxrPath.c_str());
LOG_INFOF(L"hostfxr.dll located at '%ls'", hostFxrPath.c_str());
return hostFxrPath;
}
@ -323,7 +344,7 @@ HOSTFXR_UTILITY::InvokeWhereToFindDotnet()
securityAttributes.lpSecurityDescriptor = NULL;
securityAttributes.bInheritHandle = TRUE;
LOG_INFO("Invoking where.exe to find dotnet.exe");
LOG_INFO(L"Invoking where.exe to find dotnet.exe");
// Create a read/write pipe that will be used for reading the result of where.exe
FINISHED_LAST_ERROR_IF(!CreatePipe(&hStdOutReadPipe, &hStdOutWritePipe, &securityAttributes, 0));
@ -398,7 +419,7 @@ HOSTFXR_UTILITY::InvokeWhereToFindDotnet()
FINISHED_IF_FAILED(struDotnetLocationsString.CopyA(pzFileContents, dwNumBytesRead));
LOG_INFOF("where.exe invocation returned: %S", struDotnetLocationsString.QueryStr());
LOG_INFOF(L"where.exe invocation returned: '%ls'", struDotnetLocationsString.QueryStr());
// Check the bitness of the currently running process
// matches the dotnet.exe found.
@ -417,7 +438,7 @@ HOSTFXR_UTILITY::InvokeWhereToFindDotnet()
fIsCurrentProcess64Bit = systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64;
}
LOG_INFOF("Current process bitness type detected as isX64=%d", fIsCurrentProcess64Bit);
LOG_INFOF(L"Current process bitness type detected as isX64=%d", fIsCurrentProcess64Bit);
while (TRUE)
{
@ -431,14 +452,14 @@ HOSTFXR_UTILITY::InvokeWhereToFindDotnet()
// \r\n is two wchars, so add 2 here.
prevIndex = index + 2;
LOG_INFOF("Processing entry %S", struDotnetSubstring.QueryStr());
LOG_INFOF(L"Processing entry '%ls'", struDotnetSubstring.QueryStr());
if (LOG_LAST_ERROR_IF(!GetBinaryTypeW(struDotnetSubstring.QueryStr(), &dwBinaryType)))
{
continue;
}
LOG_INFOF("Binary type %d", dwBinaryType);
LOG_INFOF(L"Binary type %d", dwBinaryType);
if (fIsCurrentProcess64Bit == (dwBinaryType == SCS_64BIT_BINARY))
{

View File

@ -45,9 +45,8 @@ public:
static
void
ParseHostfxrArguments(
AppendArguments(
const std::wstring &arugments,
const std::filesystem::path &exePath,
const std::filesystem::path &applicationPhysicalPath,
std::vector<std::wstring> &arguments,
bool expandDllPaths = false

View File

@ -33,6 +33,11 @@ HRESULT HOSTFXR_OPTIONS::Create(
knownDotnetLocation,
arguments);
LOG_INFOF(L"Parsed hostfxr options: dotnet location: '%ls' hostfxr path: '%ls' arguments:", knownDotnetLocation.c_str(), hostFxrDllPath.c_str());
for (size_t i = 0; i < arguments.size(); i++)
{
LOG_INFOF(L"Argument[%d] = '%ls'", i, arguments[i].c_str());
}
ppWrapper = std::make_unique<HOSTFXR_OPTIONS>(knownDotnetLocation, hostFxrDllPath, arguments);
}
catch (HOSTFXR_UTILITY::StartupParametersResolutionException &resolutionException)

View File

@ -443,7 +443,7 @@ IN_PROCESS_APPLICATION::ExecuteApplication(
FINISHED_IF_FAILED(SetEnvironementVariablesOnWorkerProcess());
}
LOG_INFO("Starting managed application");
LOG_INFO(L"Starting managed application");
if (m_pLoggerProvider == NULL)
{
@ -547,12 +547,12 @@ IN_PROCESS_APPLICATION::RunDotnetApplication(DWORD argc, CONST PCWSTR* argv, hos
hr = HRESULT_FROM_WIN32(GetLastError());
}
LOG_INFOF("Managed application exited with code %d", m_ProcessExitCode);
LOG_INFOF(L"Managed application exited with code %d", m_ProcessExitCode);
}
__except(GetExceptionCode() != 0)
{
LOG_INFOF("Managed threw an exception %d", GetExceptionCode());
LOG_INFOF(L"Managed threw an exception %d", GetExceptionCode());
hr = HRESULT_FROM_WIN32(GetLastError());
}

View File

@ -8,7 +8,7 @@
HRESULT AppOfflineTrackingApplication::StartMonitoringAppOffline()
{
LOG_INFOF("Starting app_offline monitoring in application %S", m_applicationPath.c_str());
LOG_INFOF(L"Starting app_offline monitoring in application '%ls'", m_applicationPath.c_str());
HRESULT hr = StartMonitoringAppOflineImpl();
if (FAILED_LOG(hr))
@ -56,7 +56,7 @@ void AppOfflineTrackingApplication::OnAppOffline()
return;
}
LOG_INFOF("Received app_offline notification in application %S", m_applicationPath.c_str());
LOG_INFOF(L"Received app_offline notification in application '%ls'", m_applicationPath.c_str());
EventLog::Info(
ASPNETCORE_EVENT_RECYCLE_APPOFFLINE,
ASPNETCORE_EVENT_RECYCLE_APPOFFLINE_MSG,

View File

@ -137,7 +137,7 @@ Win32 error
DWORD dwErrorStatus;
ULONG_PTR completionKey;
LOG_INFO("Starting file watcher thread");
LOG_INFO(L"Starting file watcher thread");
pFileMonitor = (FILE_WATCHER*)pvArg;
DBG_ASSERT(pFileMonitor != NULL);
@ -177,7 +177,7 @@ Win32 error
pFileMonitor->m_fThreadExit = TRUE;
LOG_INFO("Stopping file watcher thread");
LOG_INFO(L"Stopping file watcher thread");
ExitThread(0);
}

View File

@ -4,6 +4,7 @@
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests;
using Microsoft.AspNetCore.Server.IntegrationTesting.IIS;
using Microsoft.Extensions.Logging.Testing;
using Xunit.Abstractions;
@ -37,6 +38,13 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
return (IISDeploymentResult)await _deployer.DeployAsync();
}
protected virtual async Task<IISDeploymentResult> StartAsync(IISDeploymentParameters parameters)
{
var result = await DeployAsync(parameters);
await result.AssertStarts();
return result;
}
public override void Dispose()
{
StopServer(false);

View File

@ -65,12 +65,15 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
{
foreach (DirectoryInfo directoryInfo in source.GetDirectories())
{
CopyFiles(directoryInfo, target.CreateSubdirectory(directoryInfo.Name), logger);
if (directoryInfo.FullName != target.FullName)
{
CopyFiles(directoryInfo, target.CreateSubdirectory(directoryInfo.Name), logger);
}
}
logger.LogDebug($"Processing {target.FullName}");
logger?.LogDebug($"Processing {target.FullName}");
foreach (FileInfo fileInfo in source.GetFiles())
{
logger.LogDebug($" Copying {fileInfo.Name}");
logger?.LogDebug($" Copying {fileInfo.Name}");
var destFileName = Path.Combine(target.FullName, fileInfo.Name);
fileInfo.CopyTo(destFileName);
}

View File

@ -11,64 +11,58 @@
TEST(ParseHostFxrArguments, BasicHostFxrArguments)
{
std::vector<std::wstring> bstrArray;
PCWSTR exeStr = L"C:/Program Files/dotnet.exe";
HOSTFXR_UTILITY::ParseHostfxrArguments(
HOSTFXR_UTILITY::AppendArguments(
L"exec \"test.dll\"", // args
exeStr, // exe path
L"invalid", // physical path to application
bstrArray); // args array.
EXPECT_EQ(3, bstrArray.size());
ASSERT_STREQ(exeStr, bstrArray[0].c_str());
ASSERT_STREQ(L"exec", bstrArray[1].c_str());
ASSERT_STREQ(L"test.dll", bstrArray[2].c_str());
EXPECT_EQ(2, bstrArray.size());
ASSERT_STREQ(L"exec", bstrArray[0].c_str());
ASSERT_STREQ(L"test.dll", bstrArray[1].c_str());
}
TEST(ParseHostFxrArguments, NoExecProvided)
{
std::vector<std::wstring> bstrArray;
PCWSTR exeStr = L"C:/Program Files/dotnet.exe";
HOSTFXR_UTILITY::ParseHostfxrArguments(
HOSTFXR_UTILITY::AppendArguments(
L"test.dll", // args
exeStr, // exe path
L"ignored", // physical path to application
bstrArray); // args array.
EXPECT_EQ(DWORD(2), bstrArray.size());
ASSERT_STREQ(exeStr, bstrArray[0].c_str());
ASSERT_STREQ(L"test.dll", bstrArray[1].c_str());
EXPECT_EQ(1, bstrArray.size());
ASSERT_STREQ(L"test.dll", bstrArray[0].c_str());
}
TEST(ParseHostFxrArguments, ConvertDllToAbsolutePath)
{
std::vector<std::wstring> bstrArray;
PCWSTR exeStr = L"C:/Program Files/dotnet.exe";
// we need to use existing dll so let's use ntdll that we know exists everywhere
auto system32 = Environment::ExpandEnvironmentVariables(L"%WINDIR%\\System32");
HOSTFXR_UTILITY::ParseHostfxrArguments(
HOSTFXR_UTILITY::AppendArguments(
L"exec \"ntdll.dll\"", // args
exeStr, // exe path
system32, // physical path to application
bstrArray, // args array.
true); // expandDllPaths
EXPECT_EQ(DWORD(3), bstrArray.size());
ASSERT_STREQ(exeStr, bstrArray[0].c_str());
ASSERT_STREQ(L"exec", bstrArray[1].c_str());
ASSERT_STREQ((system32 + L"\\ntdll.dll").c_str(), bstrArray[2].c_str());
EXPECT_EQ(2, bstrArray.size());
ASSERT_STREQ(L"exec", bstrArray[0].c_str());
ASSERT_STREQ((system32 + L"\\ntdll.dll").c_str(), bstrArray[1].c_str());
}
TEST(ParseHostFxrArguments, ProvideNoArgs_InvalidArgs)
{
std::vector<std::wstring> bstrArray;
PCWSTR exeStr = L"C:/Program Files/dotnet.exe";
std::filesystem::path struHostFxrDllLocation;
std::filesystem::path struExeLocation;
ASSERT_THROW(HOSTFXR_UTILITY::ParseHostfxrArguments(
L"", // args
exeStr, // exe path
L"ignored", // physical path to application
EXPECT_THROW(HOSTFXR_UTILITY::GetHostFxrParameters(
L"dotnet", // processPath
L"some\\path", // application physical path, ignored.
L"", //arguments
struHostFxrDllLocation,
struExeLocation,
bstrArray), // args array.
HOSTFXR_UTILITY::StartupParametersResolutionException);
}

View File

@ -33,13 +33,10 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
public async Task ExpandEnvironmentVariableInWebConfig()
{
// Point to dotnet installed in user profile.
await AssertStarts(
deploymentParameters =>
{
deploymentParameters.EnvironmentVariables["DotnetPath"] = _dotnetLocation;
deploymentParameters.WebConfigActionList.Add(WebConfigHelpers.AddOrModifyAspNetCoreSection("processPath", "%DotnetPath%"));
}
);
var deploymentParameters = _fixture.GetBaseDeploymentParameters(publish: true);
deploymentParameters.EnvironmentVariables["DotnetPath"] = _dotnetLocation;
deploymentParameters.WebConfigActionList.Add(WebConfigHelpers.AddOrModifyAspNetCoreSection("processPath", "%DotnetPath%"));
await StartAsync(deploymentParameters);
}
[ConditionalTheory]
@ -68,26 +65,23 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
[ConditionalFact]
public async Task StartsWithDotnetLocationWithoutExe()
{
var dotnetLocationWithoutExtension = _dotnetLocation.Substring(0, _dotnetLocation.LastIndexOf("."));
var deploymentParameters = _fixture.GetBaseDeploymentParameters(publish: true);
await AssertStarts(
deploymentParameters =>
{
deploymentParameters.WebConfigActionList.Add(WebConfigHelpers.AddOrModifyAspNetCoreSection("processPath", dotnetLocationWithoutExtension));
}
);
var dotnetLocationWithoutExtension = _dotnetLocation.Substring(0, _dotnetLocation.LastIndexOf("."));
deploymentParameters.WebConfigActionList.Add(WebConfigHelpers.AddOrModifyAspNetCoreSection("processPath", dotnetLocationWithoutExtension));
await StartAsync(deploymentParameters);
}
[ConditionalFact]
public async Task StartsWithDotnetLocationUppercase()
{
var deploymentParameters = _fixture.GetBaseDeploymentParameters(publish: true);
var dotnetLocationWithoutExtension = _dotnetLocation.Substring(0, _dotnetLocation.LastIndexOf(".")).ToUpperInvariant();
await AssertStarts(
deploymentParameters =>
{
deploymentParameters.WebConfigActionList.Add(WebConfigHelpers.AddOrModifyAspNetCoreSection("processPath", dotnetLocationWithoutExtension));
}
);
deploymentParameters.WebConfigActionList.Add(WebConfigHelpers.AddOrModifyAspNetCoreSection("processPath", dotnetLocationWithoutExtension));
await StartAsync(deploymentParameters);
}
[ConditionalTheory]
@ -95,32 +89,18 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
[InlineData("dotnet.EXE")]
public async Task StartsWithDotnetOnThePath(string path)
{
await AssertStarts(
deploymentParameters =>
{
deploymentParameters.EnvironmentVariables["PATH"] = Path.GetDirectoryName(_dotnetLocation);
deploymentParameters.WebConfigActionList.Add(WebConfigHelpers.AddOrModifyAspNetCoreSection("processPath", path));
}
);
var deploymentParameters = _fixture.GetBaseDeploymentParameters(publish: true);
deploymentParameters.EnvironmentVariables["PATH"] = Path.GetDirectoryName(_dotnetLocation);
deploymentParameters.WebConfigActionList.Add(WebConfigHelpers.AddOrModifyAspNetCoreSection("processPath", path));
var deploymentResult = await DeployAsync(deploymentParameters);
await deploymentResult.AssertStarts();
// Verify that in this scenario where.exe was invoked only once by shim and request handler uses cached value
Assert.Equal(1, TestSink.Writes.Count(w => w.Message.Contains("Invoking where.exe to find dotnet.exe")));
}
private async Task AssertStarts(Action<IISDeploymentParameters> preDeploy = null)
{
var deploymentParameters = _fixture.GetBaseDeploymentParameters(publish: true);
preDeploy?.Invoke(deploymentParameters);
var deploymentResult = await DeployAsync(deploymentParameters);
var response = await deploymentResult.HttpClient.GetAsync("HelloWorld");
var responseText = await response.Content.ReadAsStringAsync();
Assert.Equal("Hello World", responseText);
}
public static TestMatrix TestVariants
=> TestMatrix.ForServers(DeployerSelector.ServerType)
.WithTfms(Tfm.NetCoreApp22)
@ -132,13 +112,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
public async Task HelloWorld(TestVariant variant)
{
var deploymentParameters = _fixture.GetBaseDeploymentParameters(variant, publish: true);
var deploymentResult = await DeployAsync(deploymentParameters);
var response = await deploymentResult.HttpClient.GetAsync("/HelloWorld");
var responseText = await response.Content.ReadAsStringAsync();
Assert.Equal("Hello World", responseText);
await StartAsync(deploymentParameters);
}
[ConditionalFact]
@ -149,7 +123,6 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
deploymentParameters.ApplicationPublisher = null;
// ReferenceTestTasks is workaround for https://github.com/dotnet/sdk/issues/2482
deploymentParameters.AdditionalPublishParameters = "-p:RuntimeIdentifier=win7-x64 -p:UseAppHost=true -p:SelfContained=false -p:ReferenceTestTasks=false";
deploymentParameters.RestoreOnPublish = true;
var deploymentResult = await DeployAsync(deploymentParameters);
Assert.True(File.Exists(Path.Combine(deploymentResult.ContentRoot, "InProcessWebSite.exe")));
@ -194,7 +167,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
[ConditionalTheory]
[MemberData(nameof(InvalidConfigTransformationsScenarios))]
public async Task StartsWithWebConfigVariationsPortable(string scenario)
public async Task ReportsWebConfigAuthoringErrors(string scenario)
{
var (expectedError, action) = InvalidConfigTransformations[scenario];
var iisDeploymentParameters = _fixture.GetBaseDeploymentParameters(publish: true);
@ -227,5 +200,148 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
));
return dictionary;
}
private static Dictionary<string, Func<IISDeploymentParameters, string>> PortableConfigTransformations = InitPortableWebConfigTransformations();
public static IEnumerable<object[]> PortableConfigTransformationsScenarios => PortableConfigTransformations.ToTheoryData();
[ConditionalTheory]
[MemberData(nameof(PortableConfigTransformationsScenarios))]
public async Task StartsWithWebConfigVariationsPortable(string scenario)
{
var action = PortableConfigTransformations[scenario];
var iisDeploymentParameters = _fixture.GetBaseDeploymentParameters(publish: true);
var expectedArguments = action(iisDeploymentParameters);
var result = await DeployAsync(iisDeploymentParameters);
Assert.Equal(expectedArguments, await result.HttpClient.GetStringAsync("/CommandLineArgs"));
}
public static Dictionary<string, Func<IISDeploymentParameters, string>> InitPortableWebConfigTransformations()
{
var dictionary = new Dictionary<string, Func<IISDeploymentParameters, string>>();
var pathWithSpace = "\u03c0 \u2260 3\u00b714";
dictionary.Add("App in bin subdirectory full path to dll using exec and quotes",
parameters => {
MoveApplication(parameters, "bin");
TransformArguments(parameters, (arguments, root) => "exec " + Path.Combine(root, "bin", arguments));
return "";
});
dictionary.Add("App in subdirectory with space",
parameters => {
MoveApplication(parameters, pathWithSpace);
TransformArguments(parameters, (arguments, root) => Path.Combine(pathWithSpace, arguments));
return "";
});
dictionary.Add("App in subdirectory with space and full path to dll",
parameters => {
MoveApplication(parameters, pathWithSpace);
TransformArguments(parameters, (arguments, root) => Path.Combine(root, pathWithSpace, arguments));
return "";
});
dictionary.Add("App in bin subdirectory with space full path to dll using exec and quotes",
parameters => {
MoveApplication(parameters, pathWithSpace);
TransformArguments(parameters, (arguments, root) => "exec \"" + Path.Combine(root, pathWithSpace, arguments) + "\" extra arguments");
return "extra|arguments";
});
dictionary.Add("App in bin subdirectory and quoted argument",
parameters => {
MoveApplication(parameters, "bin");
TransformArguments(parameters, (arguments, root) => Path.Combine("bin", arguments) + " \"extra argument\"");
return "extra argument";
});
dictionary.Add("App in bin subdirectory full path to dll",
parameters => {
MoveApplication(parameters, "bin");
TransformArguments(parameters, (arguments, root) => Path.Combine(root, "bin", arguments) + " extra arguments");
return "extra|arguments";
});
return dictionary;
}
private static Dictionary<string, Func<IISDeploymentParameters, string>> StandaloneConfigTransformations = InitStandaloneConfigTransformations();
public static IEnumerable<object[]> StandaloneConfigTransformationsScenarios => StandaloneConfigTransformations.ToTheoryData();
[ConditionalTheory]
[MemberData(nameof(StandaloneConfigTransformationsScenarios))]
public async Task StartsWithWebConfigVariationsStandalone(string scenario)
{
var action = StandaloneConfigTransformations[scenario];
var iisDeploymentParameters = _fixture.GetBaseDeploymentParameters(publish: true);
iisDeploymentParameters.ApplicationType = ApplicationType.Standalone;
var expectedArguments = action(iisDeploymentParameters);
var result = await DeployAsync(iisDeploymentParameters);
Assert.Equal(expectedArguments, await result.HttpClient.GetStringAsync("/CommandLineArgs"));
}
public static Dictionary<string, Func<IISDeploymentParameters, string>> InitStandaloneConfigTransformations()
{
var dictionary = new Dictionary<string, Func<IISDeploymentParameters, string>>();
var pathWithSpace = "\u03c0 \u2260 3\u00b714";
dictionary.Add("App in subdirectory",
parameters => {
MoveApplication(parameters, pathWithSpace);
TransformPath(parameters, (path, root) => Path.Combine(pathWithSpace, path));
TransformArguments(parameters, (arguments, root) => "\"additional argument\"");
return "additional argument";
});
dictionary.Add("App in bin subdirectory full path",
parameters => {
MoveApplication(parameters, pathWithSpace);
TransformPath(parameters, (path, root) => Path.Combine(root, pathWithSpace, path));
TransformArguments(parameters, (arguments, root) => "additional arguments");
return "additional|arguments";
});
return dictionary;
}
private static void MoveApplication(
IISDeploymentParameters parameters,
string subdirectory)
{
parameters.WebConfigActionList.Add((config, contentRoot) =>
{
var source = new DirectoryInfo(contentRoot);
var subDirectoryPath = source.CreateSubdirectory(subdirectory);
// Copy everything into a subfolder
Helpers.CopyFiles(source, subDirectoryPath, null);
// Cleanup files
foreach (var fileSystemInfo in source.GetFiles())
{
fileSystemInfo.Delete();
}
});
}
private static void TransformPath(IISDeploymentParameters parameters, Func<string, string, string> transformation)
{
parameters.WebConfigActionList.Add(
(config, contentRoot) =>
{
var aspNetCoreElement = config.Descendants("aspNetCore").Single();
aspNetCoreElement.SetAttributeValue("processPath", transformation((string)aspNetCoreElement.Attribute("processPath"), contentRoot));
});
}
private static void TransformArguments(IISDeploymentParameters parameters, Func<string, string, string> transformation)
{
parameters.WebConfigActionList.Add(
(config, contentRoot) =>
{
var aspNetCoreElement = config.Descendants("aspNetCore").Single();
aspNetCoreElement.SetAttributeValue("arguments", transformation((string)aspNetCoreElement.Attribute("arguments"), contentRoot));
});
}
}
}

View File

@ -3,6 +3,7 @@
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
@ -46,7 +47,7 @@ namespace IISTestSite
private async Task HostingEnvironment(HttpContext context)
{
var hostingEnv = context.RequestServices.GetService<IHostingEnvironment>();
await context.Response.WriteAsync("ContentRootPath "+hostingEnv.ContentRootPath + Environment.NewLine);
await context.Response.WriteAsync("WebRootPath "+hostingEnv.WebRootPath + Environment.NewLine);
await context.Response.WriteAsync("CurrentDirectory "+Environment.CurrentDirectory);
@ -762,5 +763,10 @@ namespace IISTestSite
}
await context.Response.WriteAsync("Response End");
}
private async Task CommandLineArgs(HttpContext context)
{
await context.Response.WriteAsync(string.Join("|", Environment.GetCommandLineArgs().Skip(1)));
}
}
}