Add better error message when someone does single file publish in ANCM (#10871)
This commit is contained in:
parent
2b2bf067dd
commit
f080c89e89
|
|
@ -64,6 +64,7 @@ HandlerResolver::LoadRequestHandlerAssembly(const IHttpApplication &pApplication
|
|||
pConfiguration.QueryProcessPath(),
|
||||
pApplication.GetApplicationPhysicalPath(),
|
||||
pConfiguration.QueryArguments(),
|
||||
errorContext,
|
||||
options));
|
||||
|
||||
location = options->GetDotnetExeLocation();
|
||||
|
|
|
|||
|
|
@ -196,6 +196,7 @@
|
|||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ErrorContext.h" />
|
||||
<ClInclude Include="PollingAppOfflineApplication.h" />
|
||||
<ClInclude Include="application.h" />
|
||||
<ClInclude Include="BindingInformation.h" />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
struct ErrorContext
|
||||
{
|
||||
// TODO consider adding HRESULT here
|
||||
std::string detailedErrorContent;
|
||||
USHORT statusCode;
|
||||
USHORT subStatusCode;
|
||||
std::string generalErrorType;
|
||||
std::string errorReason;
|
||||
};
|
||||
|
|
@ -28,16 +28,6 @@ typedef int(*hostfxr_set_runtime_property_value_fn)(void* host_context_handle, P
|
|||
typedef int(*hostfxr_run_app_fn)(void* host_context_handle);
|
||||
typedef int(*hostfxr_close_fn)(void* hostfxr_context_handle);
|
||||
|
||||
struct ErrorContext
|
||||
{
|
||||
// TODO consider adding HRESULT here
|
||||
std::string detailedErrorContent;
|
||||
USHORT statusCode;
|
||||
USHORT subStatusCode;
|
||||
std::string generalErrorType;
|
||||
std::string errorReason;
|
||||
};
|
||||
|
||||
class HostFxrErrorRedirector: NonCopyable
|
||||
{
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ HRESULT HostFxrResolutionResult::Create(
|
|||
_In_ const std::wstring& pcwzProcessPath,
|
||||
_In_ const std::wstring& pcwzApplicationPhysicalPath,
|
||||
_In_ const std::wstring& pcwzArguments,
|
||||
_In_ ErrorContext& errorContext,
|
||||
_Out_ std::unique_ptr<HostFxrResolutionResult>& ppWrapper)
|
||||
{
|
||||
std::filesystem::path knownDotnetLocation;
|
||||
|
|
@ -42,7 +43,8 @@ HRESULT HostFxrResolutionResult::Create(
|
|||
pcwzArguments,
|
||||
hostFxrDllPath,
|
||||
knownDotnetLocation,
|
||||
arguments);
|
||||
arguments,
|
||||
errorContext);
|
||||
|
||||
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++)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@
|
|||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "ErrorContext.h"
|
||||
|
||||
class HostFxrResolutionResult
|
||||
{
|
||||
public:
|
||||
|
|
@ -44,6 +46,7 @@ public:
|
|||
_In_ const std::wstring& pcwzProcessPath,
|
||||
_In_ const std::wstring& pcwzApplicationPhysicalPath,
|
||||
_In_ const std::wstring& pcwzArguments,
|
||||
_In_ ErrorContext& errorContext,
|
||||
_Out_ std::unique_ptr<HostFxrResolutionResult>& ppWrapper);
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@ HostFxrResolver::GetHostFxrParameters(
|
|||
const std::wstring &applicationArguments,
|
||||
fs::path &hostFxrDllPath,
|
||||
fs::path &dotnetExePath,
|
||||
std::vector<std::wstring> &arguments
|
||||
std::vector<std::wstring> &arguments,
|
||||
ErrorContext& errorContext
|
||||
)
|
||||
{
|
||||
LOG_INFOF(L"Resolving hostfxr parameters for application: '%ls' arguments: '%ls' path: '%ls'",
|
||||
|
|
@ -93,7 +94,13 @@ HostFxrResolver::GetHostFxrParameters(
|
|||
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()));
|
||||
errorContext.subStatusCode = 38;
|
||||
errorContext.errorReason = "Application DLL not found. Confirm the application dll is present. Single-file deployments are not supported in IIS.";
|
||||
errorContext.generalErrorType = "ANCM Application DLL Not Found";
|
||||
errorContext.detailedErrorContent = format("Application DLL was not found at %s.", to_multi_byte_string(applicationDllPath, CP_UTF8).c_str());
|
||||
throw InvalidOperationException(
|
||||
format(L"Application DLL was not found at %s. Confirm the application dll is present. Single-file deployments are not supported in IIS.",
|
||||
applicationDllPath.c_str()));
|
||||
}
|
||||
|
||||
hostFxrDllPath = executablePath.parent_path() / "hostfxr.dll";
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@
|
|||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "ErrorContext.h"
|
||||
|
||||
#define READ_BUFFER_SIZE 4096
|
||||
|
||||
class HostFxrResolver
|
||||
|
|
@ -23,7 +25,8 @@ public:
|
|||
const std::wstring &applicationArguments,
|
||||
std::filesystem::path &hostFxrDllPath,
|
||||
std::filesystem::path &dotnetExePath,
|
||||
std::vector<std::wstring> &arguments
|
||||
std::vector<std::wstring> &arguments,
|
||||
ErrorContext& errorContext
|
||||
);
|
||||
|
||||
static
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@
|
|||
<ClCompile Include="ConfigUtilityTests.cpp" />
|
||||
<ClCompile Include="GlobalVersionTests.cpp" />
|
||||
<ClCompile Include="Helpers.cpp" />
|
||||
<ClCompile Include="hostfxr_utility_tests.cpp" />
|
||||
<ClCompile Include="inprocess_application_tests.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="StandardOutputRedirectionTest.cpp" />
|
||||
|
|
@ -187,4 +186,4 @@
|
|||
<PropertyGroup>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
@ -1,122 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <filesystem>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "HostFxrResolver.h"
|
||||
#include "Environment.h"
|
||||
|
||||
TEST(ParseHostFxrArguments, BasicHostFxrArguments)
|
||||
{
|
||||
std::vector<std::wstring> bstrArray;
|
||||
|
||||
HostFxrResolver::AppendArguments(
|
||||
L"exec \"test.dll\"", // args
|
||||
L"invalid", // physical path to application
|
||||
bstrArray); // args array.
|
||||
|
||||
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;
|
||||
|
||||
HostFxrResolver::AppendArguments(
|
||||
L"test.dll", // args
|
||||
L"ignored", // physical path to application
|
||||
bstrArray); // args array.
|
||||
|
||||
EXPECT_EQ(1, bstrArray.size());
|
||||
ASSERT_STREQ(L"test.dll", bstrArray[0].c_str());
|
||||
}
|
||||
|
||||
TEST(ParseHostFxrArguments, ConvertDllToAbsolutePath)
|
||||
{
|
||||
std::vector<std::wstring> bstrArray;
|
||||
// we need to use existing dll so let's use ntdll that we know exists everywhere
|
||||
auto system32 = Environment::ExpandEnvironmentVariables(L"%WINDIR%\\System32");
|
||||
HostFxrResolver::AppendArguments(
|
||||
L"exec \"ntdll.dll\"", // args
|
||||
system32, // physical path to application
|
||||
bstrArray, // args array.
|
||||
true); // expandDllPaths
|
||||
|
||||
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;
|
||||
std::filesystem::path struHostFxrDllLocation;
|
||||
std::filesystem::path struExeLocation;
|
||||
|
||||
EXPECT_THROW(HostFxrResolver::GetHostFxrParameters(
|
||||
L"dotnet", // processPath
|
||||
L"some\\path", // application physical path, ignored.
|
||||
L"", //arguments
|
||||
struHostFxrDllLocation,
|
||||
struExeLocation,
|
||||
bstrArray), // args array.
|
||||
InvalidOperationException);
|
||||
}
|
||||
|
||||
TEST(GetAbsolutePathToDotnetFromProgramFiles, BackupWorks)
|
||||
{
|
||||
STRU struAbsolutePathToDotnet;
|
||||
BOOL fDotnetInProgramFiles;
|
||||
BOOL is64Bit;
|
||||
BOOL fIsWow64 = FALSE;
|
||||
SYSTEM_INFO systemInfo;
|
||||
IsWow64Process(GetCurrentProcess(), &fIsWow64);
|
||||
if (fIsWow64)
|
||||
{
|
||||
is64Bit = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
GetNativeSystemInfo(&systemInfo);
|
||||
is64Bit = systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64;
|
||||
}
|
||||
|
||||
if (is64Bit)
|
||||
{
|
||||
fDotnetInProgramFiles = std::filesystem::is_regular_file(L"C:/Program Files/dotnet/dotnet.exe");
|
||||
}
|
||||
else
|
||||
{
|
||||
fDotnetInProgramFiles = std::filesystem::is_regular_file(L"C:/Program Files (x86)/dotnet/dotnet.exe");
|
||||
}
|
||||
|
||||
auto dotnetPath = HostFxrResolver::GetAbsolutePathToDotnetFromProgramFiles();
|
||||
if (fDotnetInProgramFiles)
|
||||
{
|
||||
EXPECT_TRUE(dotnetPath.has_value());
|
||||
}
|
||||
else
|
||||
{
|
||||
EXPECT_FALSE(dotnetPath.has_value());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(GetHostFxrArguments, InvalidParams)
|
||||
{
|
||||
std::vector<std::wstring> bstrArray;
|
||||
std::filesystem::path struHostFxrDllLocation;
|
||||
std::filesystem::path struExeLocation;
|
||||
|
||||
EXPECT_THROW(HostFxrResolver::GetHostFxrParameters(
|
||||
L"bogus", // processPath
|
||||
L"", // application physical path, ignored.
|
||||
L"ignored", //arguments
|
||||
struHostFxrDllLocation,
|
||||
struExeLocation,
|
||||
bstrArray), // args array.
|
||||
InvalidOperationException);
|
||||
}
|
||||
|
|
@ -195,6 +195,8 @@ IN_PROCESS_APPLICATION::ExecuteApplication()
|
|||
|
||||
auto context = std::make_shared<ExecuteClrContext>();
|
||||
|
||||
ErrorContext errorContext; // unused
|
||||
|
||||
if (s_fMainCallback == nullptr)
|
||||
{
|
||||
THROW_IF_FAILED(HostFxrResolutionResult::Create(
|
||||
|
|
@ -202,6 +204,7 @@ IN_PROCESS_APPLICATION::ExecuteApplication()
|
|||
m_pConfig->QueryProcessPath(),
|
||||
QueryApplicationPhysicalPath(),
|
||||
m_pConfig->QueryArguments(),
|
||||
errorContext,
|
||||
hostFxrResolutionResult
|
||||
));
|
||||
|
||||
|
|
|
|||
|
|
@ -365,6 +365,24 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests.InProcess
|
|||
EventLogHelpers.VerifyEventLogEvent(deploymentResult, EventLogHelpers.InProcessFailedToFindNativeDependencies(deploymentResult), Logger);
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
public async Task SingleExecutable_FailedToFindNativeDependencies()
|
||||
{
|
||||
var deploymentParameters = Fixture.GetBaseDeploymentParameters(Fixture.InProcessTestSite);
|
||||
deploymentParameters.ApplicationType = ApplicationType.Standalone;
|
||||
var deploymentResult = await DeployAsync(deploymentParameters);
|
||||
|
||||
File.Delete(Path.Combine(deploymentResult.ContentRoot, "InProcessWebSite.dll"));
|
||||
if (DeployerSelector.HasNewShim)
|
||||
{
|
||||
await AssertSiteFailsToStartWithInProcessStaticContent(deploymentResult, "HTTP Error 500.38 - ANCM Application DLL Not Found");
|
||||
}
|
||||
else
|
||||
{
|
||||
await AssertSiteFailsToStartWithInProcessStaticContent(deploymentResult);
|
||||
}
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
public async Task TargedDifferenceSharedFramework_FailedToFindNativeDependenciesErrorInResponse()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
|
|
|
|||
Loading…
Reference in New Issue