Load ANCM out of process via global versioning (#895)
This commit is contained in:
parent
f00d7b34c5
commit
9d97ff38f8
|
|
@ -29,8 +29,8 @@
|
||||||
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Condition="'$(OS)' == 'Windows_NT'">
|
<ItemGroup Condition="'$(OS)' == 'Windows_NT'">
|
||||||
<None Include="$(MSBuildThisFileDirectory)..\src\AspNetCoreModuleV2\OutOfProcessRequestHandler\bin\$(Configuration)\$(NativeFolder)\aspnetcorev2_outofprocess.dll" CopyToOutputDirectory="PreserveNewest" Visible="true" Link="$(BasePathForRequestHandler)%(FileName)%(Extension)" />
|
<None Include="$(MSBuildThisFileDirectory)..\src\AspNetCoreModuleV2\OutOfProcessRequestHandler\bin\$(Configuration)\$(NativeFolder)\aspnetcorev2_outofprocess.dll" CopyToOutputDirectory="PreserveNewest" Visible="true" Link="$(BasePathForRequestHandler)\$(AspNetCoreModuleOutOfProcessVersion)\%(FileName)%(Extension)" />
|
||||||
<None Include="$(MSBuildThisFileDirectory)..\src\AspNetCoreModuleV2\OutOfProcessRequestHandler\bin\$(Configuration)\$(NativeFolder)\aspnetcorev2_outofprocess.pdb" CopyToOutputDirectory="PreserveNewest" Visible="true" Link="$(BasePathForRequestHandler)%(FileName)%(Extension)" />
|
<None Include="$(MSBuildThisFileDirectory)..\src\AspNetCoreModuleV2\OutOfProcessRequestHandler\bin\$(Configuration)\$(NativeFolder)\aspnetcorev2_outofprocess.pdb" CopyToOutputDirectory="PreserveNewest" Visible="true" Link="$(BasePathForRequestHandler)\$(AspNetCoreModuleOutOfProcessVersion)\%(FileName)%(Extension)" />
|
||||||
<None Include="$(MSBuildThisFileDirectory)..\src\AspNetCoreModuleV2\InProcessRequestHandler\bin\$(Configuration)\$(NativeFolder)\aspnetcorev2_inprocess.dll" CopyToOutputDirectory="PreserveNewest" Visible="true" Link="$(BasePathForRequestHandler)%(FileName)%(Extension)" />
|
<None Include="$(MSBuildThisFileDirectory)..\src\AspNetCoreModuleV2\InProcessRequestHandler\bin\$(Configuration)\$(NativeFolder)\aspnetcorev2_inprocess.dll" CopyToOutputDirectory="PreserveNewest" Visible="true" Link="$(BasePathForRequestHandler)%(FileName)%(Extension)" />
|
||||||
<None Include="$(MSBuildThisFileDirectory)..\src\AspNetCoreModuleV2\InProcessRequestHandler\bin\$(Configuration)\$(NativeFolder)\aspnetcorev2_inprocess.pdb" CopyToOutputDirectory="PreserveNewest" Visible="true" Link="$(BasePathForRequestHandler)%(FileName)%(Extension)" />
|
<None Include="$(MSBuildThisFileDirectory)..\src\AspNetCoreModuleV2\InProcessRequestHandler\bin\$(Configuration)\$(NativeFolder)\aspnetcorev2_inprocess.pdb" CopyToOutputDirectory="PreserveNewest" Visible="true" Link="$(BasePathForRequestHandler)%(FileName)%(Extension)" />
|
||||||
<None Include="$(MSBuildThisFileDirectory)..\src\AspNetCoreModuleV2\AspNetCore\bin\$(Configuration)\$(NativeFolder)\aspnetcorev2.dll" CopyToOutputDirectory="PreserveNewest" Visible="true" Link="$(BasePathForRequestHandler)%(FileName)%(Extension)" />
|
<None Include="$(MSBuildThisFileDirectory)..\src\AspNetCoreModuleV2\AspNetCore\bin\$(Configuration)\$(NativeFolder)\aspnetcorev2.dll" CopyToOutputDirectory="PreserveNewest" Visible="true" Link="$(BasePathForRequestHandler)%(FileName)%(Extension)" />
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,8 @@
|
||||||
<files>
|
<files>
|
||||||
<file src="src\AspNetCoreModuleV2\AspNetCore\bin\$Configuration$\Win32\aspnetcorev2.dll" target="contentFiles\any\any\x86\aspnetcorev2.dll" />
|
<file src="src\AspNetCoreModuleV2\AspNetCore\bin\$Configuration$\Win32\aspnetcorev2.dll" target="contentFiles\any\any\x86\aspnetcorev2.dll" />
|
||||||
<file src="src\AspNetCoreModuleV2\AspNetCore\bin\$Configuration$\x64\aspnetcorev2.dll" target="contentFiles\any\any\x64\aspnetcorev2.dll" />
|
<file src="src\AspNetCoreModuleV2\AspNetCore\bin\$Configuration$\x64\aspnetcorev2.dll" target="contentFiles\any\any\x64\aspnetcorev2.dll" />
|
||||||
<file src="src\AspNetCoreModuleV2\OutOfProcessRequestHandler\bin\$Configuration$\Win32\aspnetcorev2_outofprocess.dll" target="contentFiles\any\any\x86\aspnetcorev2_outofprocess.dll" />
|
<file src="src\AspNetCoreModuleV2\OutOfProcessRequestHandler\bin\$Configuration$\Win32\aspnetcorev2_outofprocess.dll" target="contentFiles\any\any\x86\$(AspNetCoreModuleOutOfProcessVersion)\aspnetcorev2_outofprocess.dll" />
|
||||||
<file src="src\AspNetCoreModuleV2\OutOfProcessRequestHandler\bin\$Configuration$\x64\aspnetcorev2_outofprocess.dll" target="contentFiles\any\any\x64\aspnetcorev2_outofprocess.dll" />
|
<file src="src\AspNetCoreModuleV2\OutOfProcessRequestHandler\bin\$Configuration$\x64\aspnetcorev2_outofprocess.dll" target="contentFiles\any\any\x64\$(AspNetCoreModuleOutOfProcessVersion)\aspnetcorev2_outofprocess.dll" />
|
||||||
<file src="src\AspNetCoreModuleV2\InProcessRequestHandler\bin\$Configuration$\Win32\aspnetcorev2_inprocess.dll" target="contentFiles\any\any\x86\aspnetcorev2_inprocess.dll" />
|
<file src="src\AspNetCoreModuleV2\InProcessRequestHandler\bin\$Configuration$\Win32\aspnetcorev2_inprocess.dll" target="contentFiles\any\any\x86\aspnetcorev2_inprocess.dll" />
|
||||||
<file src="src\AspNetCoreModuleV2\InProcessRequestHandler\bin\$Configuration$\x64\aspnetcorev2_inprocess.dll" target="contentFiles\any\any\x64\aspnetcorev2_inprocess.dll" />
|
<file src="src\AspNetCoreModuleV2\InProcessRequestHandler\bin\$Configuration$\x64\aspnetcorev2_inprocess.dll" target="contentFiles\any\any\x64\aspnetcorev2_inprocess.dll" />
|
||||||
<file src="src\AspNetCoreModuleV2\AspNetCore\bin\$Configuration$\x64\*.xml"/>
|
<file src="src\AspNetCoreModuleV2\AspNetCore\bin\$Configuration$\x64\*.xml"/>
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@
|
||||||
<AspNetCoreModuleX86Location>$(MSBuildThisFileDirectory)..\contentFiles\any\any\x86\aspnetcore.dll</AspNetCoreModuleX86Location>
|
<AspNetCoreModuleX86Location>$(MSBuildThisFileDirectory)..\contentFiles\any\any\x86\aspnetcore.dll</AspNetCoreModuleX86Location>
|
||||||
<InProcessRequestHandlerX64Location>$(MSBuildThisFileDirectory)..\contentFiles\any\any\x64\aspnetcorev2_inprocess.dll</InProcessRequestHandlerX64Location>
|
<InProcessRequestHandlerX64Location>$(MSBuildThisFileDirectory)..\contentFiles\any\any\x64\aspnetcorev2_inprocess.dll</InProcessRequestHandlerX64Location>
|
||||||
<InProcessRequestHandlerX86Location>$(MSBuildThisFileDirectory)..\contentFiles\any\any\x86\aspnetcorev2_inprocess.dll</InProcessRequestHandlerX86Location>
|
<InProcessRequestHandlerX86Location>$(MSBuildThisFileDirectory)..\contentFiles\any\any\x86\aspnetcorev2_inprocess.dll</InProcessRequestHandlerX86Location>
|
||||||
<OutOfProcessRequestHandlerX64Location>$(MSBuildThisFileDirectory)..\contentFiles\any\any\x64\aspnetcorev2_outofprocess.dll</OutOfProcessRequestHandlerX64Location>
|
<OutOfProcessRequestHandlerX64Location>$(MSBuildThisFileDirectory)..\contentFiles\any\any\x64\$(AspNetCoreModuleOutOfProcessVersion)\aspnetcorev2_outofprocess.dll</OutOfProcessRequestHandlerX64Location>
|
||||||
<OutOfProcessRequestHandlerX86Location>$(MSBuildThisFileDirectory)..\contentFiles\any\any\x86\aspnetcorev2_outofprocess.dll</OutOfProcessRequestHandlerX86Location>
|
<OutOfProcessRequestHandlerX86Location>$(MSBuildThisFileDirectory)..\contentFiles\any\any\x86\$(AspNetCoreModuleOutOfProcessVersion)\aspnetcorev2_outofprocess.dll</OutOfProcessRequestHandlerX86Location>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "precomp.hxx"
|
#include "precomp.hxx"
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#define CS_ASPNETCORE_SECTION L"system.webServer/aspNetCore"
|
#define CS_ASPNETCORE_SECTION L"system.webServer/aspNetCore"
|
||||||
#define CS_ASPNETCORE_PROCESS_EXE_PATH L"processPath"
|
#define CS_ASPNETCORE_PROCESS_EXE_PATH L"processPath"
|
||||||
|
|
@ -105,6 +106,14 @@ public:
|
||||||
return m_hostingModel;
|
return m_hostingModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STRU*
|
||||||
|
QueryHandlerVersion(
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return &m_struHandlerVersion;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ASPNETCORE_SHIM_CONFIG() :
|
ASPNETCORE_SHIM_CONFIG() :
|
||||||
m_cRefs(1),
|
m_cRefs(1),
|
||||||
|
|
@ -120,5 +129,6 @@ private:
|
||||||
STRU m_struConfigPath;
|
STRU m_struConfigPath;
|
||||||
APP_HOSTING_MODEL m_hostingModel;
|
APP_HOSTING_MODEL m_hostingModel;
|
||||||
STRU m_struHostFxrLocation;
|
STRU m_struHostFxrLocation;
|
||||||
|
STRU m_struHandlerVersion;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -358,60 +358,47 @@ Finished:
|
||||||
|
|
||||||
HRESULT
|
HRESULT
|
||||||
APPLICATION_INFO::FindNativeAssemblyFromGlobalLocation(
|
APPLICATION_INFO::FindNativeAssemblyFromGlobalLocation(
|
||||||
PCWSTR libraryName,
|
PCWSTR pstrHandlerDllName,
|
||||||
STRU* struFilename)
|
STRU* struFilename
|
||||||
|
)
|
||||||
{
|
{
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
DWORD dwSize = MAX_PATH;
|
|
||||||
BOOL fDone = FALSE;
|
|
||||||
DWORD dwPosition = 0;
|
|
||||||
|
|
||||||
// Though we could call LoadLibrary(L"aspnetcorerh.dll") relying the OS to solve
|
try
|
||||||
// the path (the targeted dll is the same folder of w3wp.exe/iisexpress)
|
|
||||||
// let's still load with full path to avoid security issue
|
|
||||||
if (FAILED(hr = struFilename->Resize(dwSize + 20)))
|
|
||||||
{
|
{
|
||||||
goto Finished;
|
std::wstring modulePath = GlobalVersionUtility::GetModuleName(g_hModule);
|
||||||
}
|
|
||||||
|
|
||||||
while (!fDone)
|
modulePath = GlobalVersionUtility::RemoveFileNameFromFolderPath(modulePath);
|
||||||
{
|
|
||||||
DWORD dwReturnedSize = GetModuleFileNameW(g_hModule, struFilename->QueryStr(), dwSize);
|
std::wstring retval = GlobalVersionUtility::GetGlobalRequestHandlerPath(modulePath.c_str(),
|
||||||
if (dwReturnedSize == 0)
|
m_pConfiguration->QueryHandlerVersion()->QueryStr(),
|
||||||
|
pstrHandlerDllName
|
||||||
|
);
|
||||||
|
|
||||||
|
if (FAILED(hr = struFilename->Copy(retval.c_str())))
|
||||||
{
|
{
|
||||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
return hr;
|
||||||
fDone = TRUE;
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
else if ((dwReturnedSize == dwSize) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER))
|
|
||||||
{
|
|
||||||
dwSize *= 2; // smaller buffer. increase the buffer and retry
|
|
||||||
if (FAILED(hr = struFilename->Resize(dwSize + 40))) // + 40 for aspnetcorerh.dll
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fDone = TRUE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
if (FAILED(hr = struFilename->SyncWithBuffer()))
|
|
||||||
{
|
{
|
||||||
goto Finished;
|
STRU struEvent;
|
||||||
|
if (SUCCEEDED(struEvent.Copy(ASPNETCORE_EVENT_OUT_OF_PROCESS_RH_MISSING_MSG))
|
||||||
|
&& SUCCEEDED(struEvent.AppendA(e.what())))
|
||||||
|
{
|
||||||
|
UTILITY::LogEvent(g_hEventLog,
|
||||||
|
EVENTLOG_INFORMATION_TYPE,
|
||||||
|
ASPNETCORE_EVENT_OUT_OF_PROCESS_RH_MISSING,
|
||||||
|
struEvent.QueryStr());
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = E_FAIL;
|
||||||
}
|
}
|
||||||
dwPosition = struFilename->LastIndexOf(L'\\', 0);
|
catch (...)
|
||||||
struFilename->QueryStr()[dwPosition] = L'\0';
|
|
||||||
|
|
||||||
if (FAILED(hr = struFilename->SyncWithBuffer()) ||
|
|
||||||
FAILED(hr = struFilename->Append(L"\\")) ||
|
|
||||||
FAILED(hr = struFilename->Append(libraryName)))
|
|
||||||
{
|
{
|
||||||
goto Finished;
|
hr = E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Finished:
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "aspnetcore_shim_config.h"
|
#include "aspnetcore_shim_config.h"
|
||||||
|
|
||||||
|
#include "config_utility.h"
|
||||||
#include "hostfxr_utility.h"
|
#include "hostfxr_utility.h"
|
||||||
#include "debugutil.h"
|
#include "debugutil.h"
|
||||||
#include "ahutil.h"
|
#include "ahutil.h"
|
||||||
|
|
@ -192,6 +193,8 @@ ASPNETCORE_SHIM_CONFIG::Populate(
|
||||||
goto Finished;
|
goto Finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hr = ConfigUtility::FindHandlerVersion(pAspNetCoreElement, &m_struHandlerVersion);
|
||||||
|
|
||||||
Finished:
|
Finished:
|
||||||
|
|
||||||
if (pAspNetCoreElement != NULL)
|
if (pAspNetCoreElement != NULL)
|
||||||
|
|
|
||||||
|
|
@ -181,6 +181,8 @@
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="application.h" />
|
<ClInclude Include="application.h" />
|
||||||
|
<ClInclude Include="config_utility.h" />
|
||||||
|
<ClInclude Include="GlobalVersionUtility.h" />
|
||||||
<ClInclude Include="NullOutputManager.h" />
|
<ClInclude Include="NullOutputManager.h" />
|
||||||
<ClInclude Include="FileOutputManager.h" />
|
<ClInclude Include="FileOutputManager.h" />
|
||||||
<ClInclude Include="fx_ver.h" />
|
<ClInclude Include="fx_ver.h" />
|
||||||
|
|
@ -205,6 +207,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="FileOutputManager.cpp" />
|
<ClCompile Include="FileOutputManager.cpp" />
|
||||||
<ClCompile Include="fx_ver.cxx" />
|
<ClCompile Include="fx_ver.cxx" />
|
||||||
|
<ClCompile Include="GlobalVersionUtility.cpp" />
|
||||||
<ClCompile Include="hostfxr_utility.cpp" />
|
<ClCompile Include="hostfxr_utility.cpp" />
|
||||||
<ClCompile Include="hostfxroptions.cpp" />
|
<ClCompile Include="hostfxroptions.cpp" />
|
||||||
<ClCompile Include="requesthandler_config.cpp" />
|
<ClCompile Include="requesthandler_config.cpp" />
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,131 @@
|
||||||
|
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
// throws runtime error if no request handler versions are installed.
|
||||||
|
// Throw invalid_argument if any argument is null
|
||||||
|
std::wstring
|
||||||
|
GlobalVersionUtility::GetGlobalRequestHandlerPath(PCWSTR pwzAspNetCoreFolderPath, PCWSTR pwzHandlerVersion, PCWSTR pwzHandlerName)
|
||||||
|
{
|
||||||
|
if (pwzAspNetCoreFolderPath == NULL)
|
||||||
|
{
|
||||||
|
throw new std::invalid_argument("pwzAspNetCoreFolderPath is NULL");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pwzHandlerVersion == NULL)
|
||||||
|
{
|
||||||
|
throw new std::invalid_argument("pwzHandlerVersion is NULL");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pwzHandlerName == NULL)
|
||||||
|
{
|
||||||
|
throw new std::invalid_argument("pwzHandlerName is NULL");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring folderVersion(pwzHandlerVersion);
|
||||||
|
fs::path aspNetCoreFolderPath(pwzAspNetCoreFolderPath);
|
||||||
|
|
||||||
|
if (folderVersion.empty())
|
||||||
|
{
|
||||||
|
folderVersion = FindHighestGlobalVersion(pwzAspNetCoreFolderPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
aspNetCoreFolderPath = aspNetCoreFolderPath
|
||||||
|
.append(folderVersion)
|
||||||
|
.append(pwzHandlerName);
|
||||||
|
return aspNetCoreFolderPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Throw filesystem_error if directory_iterator can't iterate over the directory
|
||||||
|
// Throw invalid_argument if any argument is null
|
||||||
|
std::vector<fx_ver_t>
|
||||||
|
GlobalVersionUtility::GetRequestHandlerVersions(PCWSTR pwzAspNetCoreFolderPath)
|
||||||
|
{
|
||||||
|
if (pwzAspNetCoreFolderPath == NULL)
|
||||||
|
{
|
||||||
|
throw new std::invalid_argument("pwzAspNetCoreFolderPath is NULL");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<fx_ver_t> versionsInDirectory;
|
||||||
|
for (auto& p : fs::directory_iterator(pwzAspNetCoreFolderPath))
|
||||||
|
{
|
||||||
|
if (!fs::is_directory(p))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_ver_t requested_ver(-1, -1, -1);
|
||||||
|
if (fx_ver_t::parse(p.path().filename(), &requested_ver, false))
|
||||||
|
{
|
||||||
|
versionsInDirectory.push_back(requested_ver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return versionsInDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
// throws runtime error if no request handler versions are installed.
|
||||||
|
// Throw invalid_argument if any argument is null
|
||||||
|
std::wstring
|
||||||
|
GlobalVersionUtility::FindHighestGlobalVersion(PCWSTR pwzAspNetCoreFolderPath)
|
||||||
|
{
|
||||||
|
if (pwzAspNetCoreFolderPath == NULL)
|
||||||
|
{
|
||||||
|
throw new std::invalid_argument("pwzAspNetCoreFolderPath is NULL");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<fx_ver_t> versionsInDirectory = GetRequestHandlerVersions(pwzAspNetCoreFolderPath);
|
||||||
|
if (versionsInDirectory.empty())
|
||||||
|
{
|
||||||
|
throw new std::runtime_error("Cannot find request handler next to aspnetcorev2.dll. Verify a version of the request handler is installed in a version folder.");
|
||||||
|
}
|
||||||
|
std::sort(versionsInDirectory.begin(), versionsInDirectory.end());
|
||||||
|
|
||||||
|
return versionsInDirectory.back().as_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Throws std::out_of_range if there is an index out of range
|
||||||
|
// Throw invalid_argument if any argument is null
|
||||||
|
std::wstring
|
||||||
|
GlobalVersionUtility::RemoveFileNameFromFolderPath(std::wstring fileName)
|
||||||
|
{
|
||||||
|
fs::path path(fileName);
|
||||||
|
return path.parent_path();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring
|
||||||
|
GlobalVersionUtility::GetModuleName(HMODULE hModuleName)
|
||||||
|
{
|
||||||
|
DWORD dwSize = MAX_PATH;
|
||||||
|
BOOL fDone = FALSE;
|
||||||
|
|
||||||
|
// Instead of creating a temporary buffer, use the std::wstring directly as the receive buffer.
|
||||||
|
std::wstring retVal;
|
||||||
|
retVal.resize(dwSize);
|
||||||
|
|
||||||
|
while (!fDone)
|
||||||
|
{
|
||||||
|
DWORD dwReturnedSize = GetModuleFileNameW(hModuleName, &retVal[0], dwSize);
|
||||||
|
if (dwReturnedSize == 0)
|
||||||
|
{
|
||||||
|
throw new std::runtime_error("GetModuleFileNameW returned 0.");
|
||||||
|
}
|
||||||
|
else if ((dwReturnedSize == dwSize) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER))
|
||||||
|
{
|
||||||
|
dwSize *= 2;
|
||||||
|
retVal.resize(dwSize); // smaller buffer. increase the buffer and retry
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// GetModuleFilename will not account for the null terminator
|
||||||
|
// std::wstring auto appends one, so we don't need to subtract 1 when resizing.
|
||||||
|
retVal.resize(dwReturnedSize);
|
||||||
|
fDone = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||||
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <experimental/filesystem>
|
||||||
|
|
||||||
|
class GlobalVersionUtility
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
static
|
||||||
|
std::wstring
|
||||||
|
GetGlobalRequestHandlerPath(PCWSTR pwzAspNetCoreFolderPath, PCWSTR pwzHandlerVersion, PCWSTR pwzHandlerName);
|
||||||
|
|
||||||
|
static
|
||||||
|
std::wstring
|
||||||
|
FindHighestGlobalVersion(PCWSTR pwzAspNetCoreFolderPath);
|
||||||
|
|
||||||
|
static
|
||||||
|
std::wstring
|
||||||
|
RemoveFileNameFromFolderPath(std::wstring fileName);
|
||||||
|
|
||||||
|
static
|
||||||
|
std::vector<fx_ver_t>
|
||||||
|
GetRequestHandlerVersions(PCWSTR pwzAspNetCoreFolderPath);
|
||||||
|
|
||||||
|
static
|
||||||
|
std::wstring
|
||||||
|
GetModuleName(HMODULE hModuleName);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
@ -0,0 +1,106 @@
|
||||||
|
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||||
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
class ConfigUtility
|
||||||
|
{
|
||||||
|
#define CS_ASPNETCORE_HANDLER_SETTINGS L"handlerSettings"
|
||||||
|
#define CS_ASPNETCORE_HANDLER_VERSION L"handlerVersion"
|
||||||
|
#define CS_ASPNETCORE_HANDLER_SETTINGS_NAME L"name"
|
||||||
|
#define CS_ASPNETCORE_HANDLER_SETTINGS_VALUE L"value"
|
||||||
|
|
||||||
|
public:
|
||||||
|
static
|
||||||
|
HRESULT
|
||||||
|
FindHandlerVersion(IAppHostElement* pElement, STRU* strHandlerVersionValue)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
IAppHostElement *pHandlerSettings = NULL;
|
||||||
|
IAppHostElementCollection *pHandlerSettingsCollection = NULL;
|
||||||
|
ENUM_INDEX index;
|
||||||
|
IAppHostElement *pHandlerVar = NULL;
|
||||||
|
STRU strHandlerName;
|
||||||
|
STRU strHandlerValue;
|
||||||
|
|
||||||
|
hr = GetElementChildByName(pElement,
|
||||||
|
CS_ASPNETCORE_HANDLER_SETTINGS,
|
||||||
|
&pHandlerSettings);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
goto Finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = pHandlerSettings->get_Collection(&pHandlerSettingsCollection);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
goto Finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (hr = FindFirstElement(pHandlerSettingsCollection, &index, &pHandlerVar);
|
||||||
|
SUCCEEDED(hr);
|
||||||
|
hr = FindNextElement(pHandlerSettingsCollection, &index, &pHandlerVar))
|
||||||
|
{
|
||||||
|
if (hr == S_FALSE)
|
||||||
|
{
|
||||||
|
hr = S_OK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = GetElementStringProperty(pHandlerVar,
|
||||||
|
CS_ASPNETCORE_HANDLER_SETTINGS_NAME,
|
||||||
|
&strHandlerName);
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
goto Finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = GetElementStringProperty(pHandlerVar,
|
||||||
|
CS_ASPNETCORE_HANDLER_SETTINGS_VALUE,
|
||||||
|
&strHandlerValue);
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
goto Finished;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strHandlerName.Equals(CS_ASPNETCORE_HANDLER_VERSION))
|
||||||
|
{
|
||||||
|
hr = strHandlerVersionValue->Copy(strHandlerValue);
|
||||||
|
goto Finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
strHandlerName.Reset();
|
||||||
|
strHandlerValue.Reset();
|
||||||
|
|
||||||
|
pHandlerVar->Release();
|
||||||
|
pHandlerVar = NULL;
|
||||||
|
}
|
||||||
|
Finished:
|
||||||
|
|
||||||
|
if (pHandlerVar != NULL)
|
||||||
|
{
|
||||||
|
pHandlerVar->Release();
|
||||||
|
pHandlerVar = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pHandlerSettingsCollection != NULL)
|
||||||
|
{
|
||||||
|
pHandlerSettingsCollection->Release();
|
||||||
|
pHandlerSettingsCollection = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pHandlerSettings != NULL)
|
||||||
|
{
|
||||||
|
pHandlerSettings->Release();
|
||||||
|
pHandlerSettings = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
@ -14,6 +14,8 @@
|
||||||
#include <shellapi.h>
|
#include <shellapi.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <experimental/filesystem>
|
||||||
|
|
||||||
#include "Shlwapi.h"
|
#include "Shlwapi.h"
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
#include "hashtable.h"
|
#include "hashtable.h"
|
||||||
|
|
@ -31,10 +33,11 @@
|
||||||
#include "application.h"
|
#include "application.h"
|
||||||
#include "SRWLockWrapper.h"
|
#include "SRWLockWrapper.h"
|
||||||
#include "environmentvariablehash.h"
|
#include "environmentvariablehash.h"
|
||||||
|
#include "fx_ver.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
#include "GlobalVersionUtility.h"
|
||||||
#include "resources.h"
|
#include "resources.h"
|
||||||
#include "aspnetcore_msg.h"
|
#include "aspnetcore_msg.h"
|
||||||
#include "fx_ver.h"
|
|
||||||
#include "hostfxr_utility.h"
|
#include "hostfxr_utility.h"
|
||||||
#include "hostfxroptions.h"
|
#include "hostfxroptions.h"
|
||||||
#include "IOutputManager.h"
|
#include "IOutputManager.h"
|
||||||
|
|
@ -42,3 +45,4 @@
|
||||||
#include "PipeOutputManager.h"
|
#include "PipeOutputManager.h"
|
||||||
#include "NullOutputManager.h"
|
#include "NullOutputManager.h"
|
||||||
#include "LoggingHelpers.h"
|
#include "LoggingHelpers.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
|
||||||
#include"stdafx.h"
|
#include "stdafx.h"
|
||||||
|
|
||||||
// static
|
// static
|
||||||
HRESULT
|
HRESULT
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
class UTILITY
|
class UTILITY
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -121,3 +123,4 @@ private:
|
||||||
UTILITY() {}
|
UTILITY() {}
|
||||||
~UTILITY() {}
|
~UTILITY() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,9 @@
|
||||||
<ClInclude Include="stdafx.h" />
|
<ClInclude Include="stdafx.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="ConfigUtilityTests.cpp" />
|
||||||
<ClCompile Include="FileOutputManagerTests.cpp" />
|
<ClCompile Include="FileOutputManagerTests.cpp" />
|
||||||
|
<ClCompile Include="GlobalVersionTests.cpp" />
|
||||||
<ClCompile Include="Helpers.cpp" />
|
<ClCompile Include="Helpers.cpp" />
|
||||||
<ClCompile Include="hostfxr_utility_tests.cpp" />
|
<ClCompile Include="hostfxr_utility_tests.cpp" />
|
||||||
<ClCompile Include="inprocess_application_tests.cpp" />
|
<ClCompile Include="inprocess_application_tests.cpp" />
|
||||||
|
|
@ -93,7 +95,7 @@
|
||||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)include;%(AdditionalIncludeDirectories);..\..\src\AspNetCoreModuleV2\IISLib;..\..\src\AspNetCoreModuleV2\CommonLib;..\gtest\googletest\googletest\include;...\..\src\AspNetCoreModuleV2\AspNetCore\Inc;..\..\src\AspNetCoreModuleV2\InProcessRequestHandler\;</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)include;%(AdditionalIncludeDirectories);..\..\src\AspNetCoreModuleV2\IISLib;..\..\src\AspNetCoreModuleV2\CommonLib;..\gtest\googletest\googletest\include;..\gtest\googletest\googlemock\include;...\..\src\AspNetCoreModuleV2\AspNetCore\Inc;..\..\src\AspNetCoreModuleV2\InProcessRequestHandler\;</AdditionalIncludeDirectories>
|
||||||
<AdditionalOptions>/D "_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING" </AdditionalOptions>
|
<AdditionalOptions>/D "_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING" </AdditionalOptions>
|
||||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
@ -118,7 +120,7 @@
|
||||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)include;%(AdditionalIncludeDirectories);..\..\src\AspNetCoreModuleV2\IISLib;..\..\src\AspNetCoreModuleV2\CommonLib;..\gtest\googletest\googletest\include;...\..\src\AspNetCoreModuleV2\AspNetCore\Inc;..\..\src\AspNetCoreModuleV2\InProcessRequestHandler\;</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)include;%(AdditionalIncludeDirectories);..\..\src\AspNetCoreModuleV2\IISLib;..\..\src\AspNetCoreModuleV2\CommonLib;..\gtest\googletest\googletest\include;..\gtest\googletest\googlemock\include;...\..\src\AspNetCoreModuleV2\AspNetCore\Inc;..\..\src\AspNetCoreModuleV2\InProcessRequestHandler\;</AdditionalIncludeDirectories>
|
||||||
<AdditionalOptions>/D "_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING" </AdditionalOptions>
|
<AdditionalOptions>/D "_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING" </AdditionalOptions>
|
||||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
@ -141,7 +143,7 @@
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)include;%(AdditionalIncludeDirectories);..\..\src\AspNetCoreModuleV2\IISLib;..\..\src\AspNetCoreModuleV2\CommonLib;..\gtest\googletest\googletest\include;...\..\src\AspNetCoreModuleV2\AspNetCore\Inc;..\..\src\AspNetCoreModuleV2\InProcessRequestHandler\;</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)include;%(AdditionalIncludeDirectories);..\..\src\AspNetCoreModuleV2\IISLib;..\..\src\AspNetCoreModuleV2\CommonLib;..\gtest\googletest\googletest\include;..\gtest\googletest\googlemock\include;...\..\src\AspNetCoreModuleV2\AspNetCore\Inc;..\..\src\AspNetCoreModuleV2\InProcessRequestHandler\;</AdditionalIncludeDirectories>
|
||||||
<AdditionalOptions>/D "_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING" </AdditionalOptions>
|
<AdditionalOptions>/D "_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING" </AdditionalOptions>
|
||||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
@ -166,9 +168,9 @@
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)include;%(AdditionalIncludeDirectories);..\..\src\AspNetCoreModuleV2\IISLib;..\..\src\AspNetCoreModuleV2\CommonLib;..\gtest\googletest\googletest\include;...\..\src\AspNetCoreModuleV2\AspNetCore\Inc;..\..\src\AspNetCoreModuleV2\InProcessRequestHandler\;</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)include;%(AdditionalIncludeDirectories);..\..\src\AspNetCoreModuleV2\IISLib;..\..\src\AspNetCoreModuleV2\CommonLib;..\gtest\googletest\googletest\include;..\gtest\googletest\googlemock\include;...\..\src\AspNetCoreModuleV2\AspNetCore\Inc;..\..\src\AspNetCoreModuleV2\InProcessRequestHandler\;</AdditionalIncludeDirectories>
|
||||||
<AdditionalOptions>/D "_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING" </AdditionalOptions>
|
<AdditionalOptions>/D "_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING" </AdditionalOptions>
|
||||||
<LanguageStandard>stdcpp14</LanguageStandard>
|
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,106 @@
|
||||||
|
// 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 "gmock/gmock.h"
|
||||||
|
using ::testing::_;
|
||||||
|
using ::testing::NiceMock;
|
||||||
|
|
||||||
|
namespace ConfigUtilityTests
|
||||||
|
{
|
||||||
|
TEST(ConfigUtilityTest, HandlerVersionSet)
|
||||||
|
{
|
||||||
|
IAppHostElement* retElement = NULL;
|
||||||
|
|
||||||
|
STRU handlerVersion;
|
||||||
|
|
||||||
|
// NiceMock removes warnings about "uninteresting calls",
|
||||||
|
auto element = std::make_unique<NiceMock<MockElement>>();
|
||||||
|
auto innerElement = std::make_unique<NiceMock<MockElement>>();
|
||||||
|
auto collection = std::make_unique<NiceMock<MockCollection>>();
|
||||||
|
auto nameElement = std::make_unique<NiceMock<MockElement>>();
|
||||||
|
auto mockProperty = std::make_unique<NiceMock<MockProperty>>();
|
||||||
|
|
||||||
|
ON_CALL(*element, GetElementByName(_, _))
|
||||||
|
.WillByDefault(DoAll(testing::SetArgPointee<1>(innerElement.get()), testing::Return(S_OK)));
|
||||||
|
ON_CALL(*innerElement, get_Collection(_))
|
||||||
|
.WillByDefault(testing::DoAll(testing::SetArgPointee<0>(collection.get()), testing::Return(S_OK)));
|
||||||
|
ON_CALL(*collection, get_Count(_))
|
||||||
|
.WillByDefault(DoAll(testing::SetArgPointee<0>(1), testing::Return(S_OK)));
|
||||||
|
ON_CALL(*collection, get_Item(_, _))
|
||||||
|
.WillByDefault(DoAll(testing::SetArgPointee<1>(nameElement.get()), testing::Return(S_OK)));
|
||||||
|
ON_CALL(*nameElement, GetPropertyByName(_, _))
|
||||||
|
.WillByDefault(DoAll(testing::SetArgPointee<1>(mockProperty.get()), testing::Return(S_OK)));
|
||||||
|
EXPECT_CALL(*mockProperty, get_StringValue(_))
|
||||||
|
.WillOnce(DoAll(testing::SetArgPointee<0>(SysAllocString(L"handlerVersion")), testing::Return(S_OK)))
|
||||||
|
.WillOnce(DoAll(testing::SetArgPointee<0>(SysAllocString(L"value")), testing::Return(S_OK)));
|
||||||
|
|
||||||
|
HRESULT hr = ConfigUtility::FindHandlerVersion(element.get(), &handlerVersion);
|
||||||
|
|
||||||
|
EXPECT_STREQ(handlerVersion.QueryStr(), L"value");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ConfigUtilityTest, NoHandlerVersion)
|
||||||
|
{
|
||||||
|
IAppHostElement* retElement = NULL;
|
||||||
|
|
||||||
|
STRU handlerVersion;
|
||||||
|
|
||||||
|
// NiceMock removes warnings about "uninteresting calls",
|
||||||
|
auto element = std::make_unique<NiceMock<MockElement>>();
|
||||||
|
auto innerElement = std::make_unique<NiceMock<MockElement>>();
|
||||||
|
auto collection = std::make_unique<NiceMock<MockCollection>>();
|
||||||
|
auto nameElement = std::make_unique<NiceMock<MockElement>>();
|
||||||
|
auto mockProperty = std::make_unique<NiceMock<MockProperty>>();
|
||||||
|
|
||||||
|
ON_CALL(*element, GetElementByName(_, _))
|
||||||
|
.WillByDefault(DoAll(testing::SetArgPointee<1>(innerElement.get()), testing::Return(S_OK)));
|
||||||
|
ON_CALL(*innerElement, get_Collection(_))
|
||||||
|
.WillByDefault(testing::DoAll(testing::SetArgPointee<0>(collection.get()), testing::Return(S_OK)));
|
||||||
|
ON_CALL(*collection, get_Count(_))
|
||||||
|
.WillByDefault(DoAll(testing::SetArgPointee<0>(1), testing::Return(S_OK)));
|
||||||
|
ON_CALL(*collection, get_Item(_, _))
|
||||||
|
.WillByDefault(DoAll(testing::SetArgPointee<1>(nameElement.get()), testing::Return(S_OK)));
|
||||||
|
ON_CALL(*nameElement, GetPropertyByName(_, _))
|
||||||
|
.WillByDefault(DoAll(testing::SetArgPointee<1>(mockProperty.get()), testing::Return(S_OK)));
|
||||||
|
EXPECT_CALL(*mockProperty, get_StringValue(_))
|
||||||
|
.WillOnce(DoAll(testing::SetArgPointee<0>(SysAllocString(L"randomvalue")), testing::Return(S_OK)))
|
||||||
|
.WillOnce(DoAll(testing::SetArgPointee<0>(SysAllocString(L"value")), testing::Return(S_OK)));
|
||||||
|
|
||||||
|
HRESULT hr = ConfigUtility::FindHandlerVersion(element.get(), &handlerVersion);
|
||||||
|
|
||||||
|
EXPECT_STREQ(handlerVersion.QueryStr(), L"");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ConfigUtilityTest, MultipleElements)
|
||||||
|
{
|
||||||
|
IAppHostElement* retElement = NULL;
|
||||||
|
STRU handlerVersion;
|
||||||
|
|
||||||
|
auto element = std::make_unique<NiceMock<MockElement>>();
|
||||||
|
auto innerElement = std::make_unique<NiceMock<MockElement>>();
|
||||||
|
auto collection = std::make_unique<NiceMock<MockCollection>>();
|
||||||
|
auto nameElement = std::make_unique<NiceMock<MockElement>>();
|
||||||
|
auto mockProperty = std::make_unique<NiceMock<MockProperty>>();
|
||||||
|
|
||||||
|
ON_CALL(*element, GetElementByName(_, _))
|
||||||
|
.WillByDefault(DoAll(testing::SetArgPointee<1>(innerElement.get()), testing::Return(S_OK)));
|
||||||
|
ON_CALL(*innerElement, get_Collection(_))
|
||||||
|
.WillByDefault(testing::DoAll(testing::SetArgPointee<0>(collection.get()), testing::Return(S_OK)));
|
||||||
|
ON_CALL(*collection, get_Count(_))
|
||||||
|
.WillByDefault(DoAll(testing::SetArgPointee<0>(2), testing::Return(S_OK)));
|
||||||
|
ON_CALL(*collection, get_Item(_, _))
|
||||||
|
.WillByDefault(DoAll(testing::SetArgPointee<1>(nameElement.get()), testing::Return(S_OK)));
|
||||||
|
ON_CALL(*nameElement, GetPropertyByName(_, _))
|
||||||
|
.WillByDefault(DoAll(testing::SetArgPointee<1>(mockProperty.get()), testing::Return(S_OK)));
|
||||||
|
EXPECT_CALL(*mockProperty, get_StringValue(_))
|
||||||
|
.WillOnce(DoAll(testing::SetArgPointee<0>(SysAllocString(L"key")), testing::Return(S_OK)))
|
||||||
|
.WillOnce(DoAll(testing::SetArgPointee<0>(SysAllocString(L"value")), testing::Return(S_OK)))
|
||||||
|
.WillOnce(DoAll(testing::SetArgPointee<0>(SysAllocString(L"handlerVersion")), testing::Return(S_OK)))
|
||||||
|
.WillOnce(DoAll(testing::SetArgPointee<0>(SysAllocString(L"value2")), testing::Return(S_OK)));
|
||||||
|
|
||||||
|
HRESULT hr = ConfigUtility::FindHandlerVersion(element.get(), &handlerVersion);
|
||||||
|
|
||||||
|
EXPECT_STREQ(handlerVersion.QueryStr(), L"value2");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -40,8 +40,6 @@ namespace FileOutManagerStartupTests
|
||||||
wprintf(expected, out);
|
wprintf(expected, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
// std::filesystem is available on c++17, however gtest fails to build when using it
|
|
||||||
// c++14 has filesystem as experimental.
|
|
||||||
for (auto & p : std::experimental::filesystem::directory_iterator(tempDirectory))
|
for (auto & p : std::experimental::filesystem::directory_iterator(tempDirectory))
|
||||||
{
|
{
|
||||||
std::wstring filename(p.path().filename());
|
std::wstring filename(p.path().filename());
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,153 @@
|
||||||
|
// 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 "gtest/internal/gtest-port.h"
|
||||||
|
|
||||||
|
namespace GlobalVersionTests
|
||||||
|
{
|
||||||
|
using ::testing::Test;
|
||||||
|
namespace fs = std::experimental::filesystem;
|
||||||
|
|
||||||
|
class GlobalVersionTest : public Test
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
void
|
||||||
|
RemoveFileNamePath(PCWSTR dllPath, PCWSTR expected)
|
||||||
|
{
|
||||||
|
std::wstring res = GlobalVersionUtility::RemoveFileNameFromFolderPath(dllPath);
|
||||||
|
EXPECT_STREQ(res.c_str(), expected);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(GlobalVersionTest, RemovesPathCorrectly)
|
||||||
|
{
|
||||||
|
RemoveFileNamePath(L"test\\log.txt", L"test");
|
||||||
|
RemoveFileNamePath(L"test\\log", L"test");
|
||||||
|
RemoveFileNamePath(L"C:\\Program Files\\IIS\\aspnetcorev2.dll", L"C:\\Program Files\\IIS");
|
||||||
|
RemoveFileNamePath(L"test\\log.txt", L"test");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(GetRequestHandlerVersions, GetFolders)
|
||||||
|
{
|
||||||
|
std::wstring tempPath = Helpers::CreateRandomTempDirectory();
|
||||||
|
EXPECT_TRUE(fs::create_directories(tempPath + L"\\2.0.0"));
|
||||||
|
|
||||||
|
auto res = GlobalVersionUtility::GetRequestHandlerVersions(tempPath.c_str());
|
||||||
|
EXPECT_EQ(res.size(), 1);
|
||||||
|
EXPECT_EQ(res.at(0), fx_ver_t(2, 0, 0, std::wstring()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(GetRequestHandlerVersions, GetFolderPreview)
|
||||||
|
{
|
||||||
|
std::wstring tempPath = Helpers::CreateRandomTempDirectory();
|
||||||
|
EXPECT_TRUE(fs::create_directories(tempPath + L"\\2.0.0-preview"));
|
||||||
|
|
||||||
|
auto res = GlobalVersionUtility::GetRequestHandlerVersions(tempPath.c_str());
|
||||||
|
EXPECT_EQ(res.size(), 1);
|
||||||
|
EXPECT_EQ(res.at(0), fx_ver_t(2, 0, 0, std::wstring(L"-preview")));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(GetRequestHandlerVersions, GetFolderManyVersions)
|
||||||
|
{
|
||||||
|
std::wstring tempPath = Helpers::CreateRandomTempDirectory();
|
||||||
|
EXPECT_TRUE(fs::create_directories(tempPath + L"\\2.0.0"));
|
||||||
|
EXPECT_TRUE(fs::create_directories(tempPath + L"\\1.9.0"));
|
||||||
|
EXPECT_TRUE(fs::create_directories(tempPath + L"\\2.1.0"));
|
||||||
|
|
||||||
|
auto res = GlobalVersionUtility::GetRequestHandlerVersions(tempPath.c_str());
|
||||||
|
EXPECT_EQ(res.size(), 3);
|
||||||
|
EXPECT_TRUE(std::find(res.begin(), res.end(), fx_ver_t(1, 9, 0, std::wstring())) != std::end(res));
|
||||||
|
EXPECT_TRUE(std::find(res.begin(), res.end(), fx_ver_t(2, 0, 0, std::wstring())) != std::end(res));
|
||||||
|
EXPECT_TRUE(std::find(res.begin(), res.end(), fx_ver_t(2, 1, 0, std::wstring())) != std::end(res));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(FindHighestGlobalVersion, HighestVersionWithSingleFolder)
|
||||||
|
{
|
||||||
|
std::wstring tempPath = Helpers::CreateRandomTempDirectory();
|
||||||
|
EXPECT_TRUE(fs::create_directories(tempPath + L"\\2.0.0"));
|
||||||
|
|
||||||
|
auto res = GlobalVersionUtility::FindHighestGlobalVersion(tempPath.c_str());
|
||||||
|
|
||||||
|
EXPECT_STREQ(res.c_str(), L"2.0.0");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(FindHighestGlobalVersion, HighestVersionWithMultipleVersions)
|
||||||
|
{
|
||||||
|
std::wstring tempPath = Helpers::CreateRandomTempDirectory();
|
||||||
|
EXPECT_TRUE(fs::create_directories(tempPath + L"\\2.0.0"));
|
||||||
|
EXPECT_TRUE(fs::create_directories(tempPath + L"\\2.1.0"));
|
||||||
|
|
||||||
|
auto res = GlobalVersionUtility::FindHighestGlobalVersion(tempPath.c_str());
|
||||||
|
|
||||||
|
EXPECT_STREQ(res.c_str(), L"2.1.0");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(FindHighestGlobalVersion, HighestVersionWithMultipleVersionsPreview)
|
||||||
|
{
|
||||||
|
std::wstring tempPath = Helpers::CreateRandomTempDirectory();
|
||||||
|
EXPECT_TRUE(fs::create_directories(tempPath + L"\\2.0.0"));
|
||||||
|
EXPECT_TRUE(fs::create_directories(tempPath + L"\\2.1.0"));
|
||||||
|
EXPECT_TRUE(fs::create_directories(tempPath + L"\\2.2.0-preview"));
|
||||||
|
|
||||||
|
auto res = GlobalVersionUtility::FindHighestGlobalVersion(tempPath.c_str());
|
||||||
|
|
||||||
|
EXPECT_STREQ(res.c_str(), L"2.2.0-preview");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(FindHighestGlobalVersion, HighestVersionWithMultipleVersionNoPreview)
|
||||||
|
{
|
||||||
|
std::wstring tempPath = Helpers::CreateRandomTempDirectory();
|
||||||
|
EXPECT_TRUE(fs::create_directories(tempPath + L"\\2.0.0"));
|
||||||
|
EXPECT_TRUE(fs::create_directories(tempPath + L"\\2.1.0-preview"));
|
||||||
|
EXPECT_TRUE(fs::create_directories(tempPath + L"\\2.1.0"));
|
||||||
|
|
||||||
|
auto res = GlobalVersionUtility::FindHighestGlobalVersion(tempPath.c_str());
|
||||||
|
|
||||||
|
EXPECT_STREQ(res.c_str(), L"2.1.0");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(GetGlobalRequestHandlerPath, FindHighestVersionNoHandlerName)
|
||||||
|
{
|
||||||
|
std::wstring tempPath = Helpers::CreateRandomTempDirectory();
|
||||||
|
EXPECT_TRUE(fs::create_directories(tempPath + L"\\2.0.0"));
|
||||||
|
auto result = GlobalVersionUtility::GetGlobalRequestHandlerPath(tempPath.c_str(), L"", L"aspnetcorev2_outofprocess.dll");
|
||||||
|
|
||||||
|
EXPECT_STREQ(result.c_str(), (tempPath + L"2.0.0\\aspnetcorev2_outofprocess.dll").c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(GetGlobalRequestHandlerPath, FindHighestVersionPreviewWins)
|
||||||
|
{
|
||||||
|
std::wstring tempPath = Helpers::CreateRandomTempDirectory();
|
||||||
|
EXPECT_TRUE(fs::create_directories(tempPath + L"\\2.0.0"));
|
||||||
|
EXPECT_TRUE(fs::create_directories(tempPath + L"\\2.1.0-preview"));
|
||||||
|
|
||||||
|
auto result = GlobalVersionUtility::GetGlobalRequestHandlerPath(tempPath.c_str(), L"", L"aspnetcorev2_outofprocess.dll");
|
||||||
|
|
||||||
|
EXPECT_STREQ(result.c_str(), (tempPath + L"2.1.0-preview\\aspnetcorev2_outofprocess.dll").c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(GetGlobalRequestHandlerPath, FindHighestVersionSpecificVersion)
|
||||||
|
{
|
||||||
|
std::wstring tempPath = Helpers::CreateRandomTempDirectory();
|
||||||
|
EXPECT_TRUE(fs::create_directories(tempPath + L"\\2.0.0"));
|
||||||
|
EXPECT_TRUE(fs::create_directories(tempPath + L"\\2.1.0-preview"));
|
||||||
|
|
||||||
|
auto result = GlobalVersionUtility::GetGlobalRequestHandlerPath(tempPath.c_str(), L"2.0.0", L"aspnetcorev2_outofprocess.dll");
|
||||||
|
|
||||||
|
EXPECT_STREQ(result.c_str(), (tempPath + L"2.0.0\\aspnetcorev2_outofprocess.dll").c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(GetGlobalRequestHandlerPath, FindHighestVersionSpecificPreview)
|
||||||
|
{
|
||||||
|
std::wstring tempPath = Helpers::CreateRandomTempDirectory();
|
||||||
|
EXPECT_TRUE(fs::create_directories(tempPath + L"\\2.0.0"));
|
||||||
|
EXPECT_TRUE(fs::create_directories(tempPath + L"\\2.1.0-preview"));
|
||||||
|
EXPECT_TRUE(fs::create_directories(tempPath + L"\\2.2.0"));
|
||||||
|
|
||||||
|
|
||||||
|
auto result = GlobalVersionUtility::GetGlobalRequestHandlerPath(tempPath.c_str(), L"2.1.0-preview", L"aspnetcorev2_outofprocess.dll");
|
||||||
|
|
||||||
|
EXPECT_STREQ(result.c_str(), (tempPath + L"2.1.0-preview\\aspnetcorev2_outofprocess.dll").c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,62 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
#include "stdafx.h"
|
#pragma once
|
||||||
|
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
|
||||||
|
class MockProperty : public IAppHostProperty
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MOCK_METHOD2_WITH_CALLTYPE(__stdcall, QueryInterface, HRESULT(REFIID riid, void ** ppvObject));
|
||||||
|
MOCK_METHOD0_WITH_CALLTYPE(__stdcall, AddRef, ULONG());
|
||||||
|
MOCK_METHOD0_WITH_CALLTYPE(__stdcall, Release, ULONG());
|
||||||
|
MOCK_METHOD1_WITH_CALLTYPE(__stdcall, get_Name, HRESULT(BSTR* pbstrValue));
|
||||||
|
MOCK_METHOD1_WITH_CALLTYPE(__stdcall, get_Value, HRESULT(VARIANT * pVariant));
|
||||||
|
MOCK_METHOD1_WITH_CALLTYPE(__stdcall, put_Value, HRESULT(VARIANT value));
|
||||||
|
MOCK_METHOD0_WITH_CALLTYPE(__stdcall, Clear, HRESULT());
|
||||||
|
MOCK_METHOD1_WITH_CALLTYPE(__stdcall, get_StringValue, HRESULT(BSTR* pbstrValue));
|
||||||
|
MOCK_METHOD1_WITH_CALLTYPE(__stdcall, get_Exception, HRESULT(IAppHostPropertyException ** ppException));
|
||||||
|
MOCK_METHOD2_WITH_CALLTYPE(__stdcall, GetMetadata, HRESULT(BSTR bstrMetadataType, VARIANT * pValue));
|
||||||
|
MOCK_METHOD2_WITH_CALLTYPE(__stdcall, SetMetadata, HRESULT(BSTR bstrMetadataType, VARIANT value));
|
||||||
|
MOCK_METHOD1_WITH_CALLTYPE(__stdcall, get_Schema, HRESULT(IAppHostPropertySchema ** ppSchema));
|
||||||
|
};
|
||||||
|
|
||||||
|
class MockCollection : public IAppHostElementCollection
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MOCK_METHOD2_WITH_CALLTYPE(__stdcall, QueryInterface, HRESULT(REFIID riid, void ** ppvObject));
|
||||||
|
MOCK_METHOD0_WITH_CALLTYPE(__stdcall, AddRef, ULONG());
|
||||||
|
MOCK_METHOD0_WITH_CALLTYPE(__stdcall, Release, ULONG());
|
||||||
|
MOCK_METHOD0_WITH_CALLTYPE(__stdcall, Clear, HRESULT());
|
||||||
|
MOCK_METHOD1_WITH_CALLTYPE(__stdcall, get_Schema, HRESULT(IAppHostCollectionSchema** pSchema));
|
||||||
|
MOCK_METHOD1_WITH_CALLTYPE(__stdcall, get_Count, HRESULT(DWORD * dwordElem));
|
||||||
|
MOCK_METHOD2_WITH_CALLTYPE(__stdcall, get_Item, HRESULT(VARIANT cIndex, IAppHostElement ** ppElement));
|
||||||
|
MOCK_METHOD2_WITH_CALLTYPE(__stdcall, AddElement, HRESULT(IAppHostElement * pElement, INT cPosition));
|
||||||
|
MOCK_METHOD1_WITH_CALLTYPE(__stdcall, DeleteElement, HRESULT(VARIANT cIndex));
|
||||||
|
MOCK_METHOD2_WITH_CALLTYPE(__stdcall, CreateNewElement, HRESULT(BSTR bstrElementName, IAppHostElement** ppElement));
|
||||||
|
};
|
||||||
|
|
||||||
|
class MockElement : public IAppHostElement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
MOCK_METHOD2_WITH_CALLTYPE(__stdcall, QueryInterface, HRESULT(REFIID riid, void ** ppvObject));
|
||||||
|
MOCK_METHOD0_WITH_CALLTYPE(__stdcall, AddRef, ULONG());
|
||||||
|
MOCK_METHOD0_WITH_CALLTYPE(__stdcall, Release, ULONG());
|
||||||
|
MOCK_METHOD1_WITH_CALLTYPE(__stdcall, get_Name, HRESULT(BSTR * pbstrName));
|
||||||
|
MOCK_METHOD1_WITH_CALLTYPE(__stdcall, get_Collection, HRESULT(IAppHostElementCollection ** ppCollection));
|
||||||
|
MOCK_METHOD1_WITH_CALLTYPE(__stdcall, get_Properties, HRESULT(IAppHostPropertyCollection ** ppProperties));
|
||||||
|
MOCK_METHOD1_WITH_CALLTYPE(__stdcall, get_ChildElements, HRESULT(IAppHostChildElementCollection ** ppElements));
|
||||||
|
MOCK_METHOD2_WITH_CALLTYPE(__stdcall, GetMetadata, HRESULT(BSTR bstrMetadataType, VARIANT * pValue));
|
||||||
|
MOCK_METHOD2_WITH_CALLTYPE(__stdcall, SetMetadata, HRESULT(BSTR bstrMetadataType, VARIANT value));
|
||||||
|
MOCK_METHOD1_WITH_CALLTYPE(__stdcall, get_Schema, HRESULT(IAppHostElementSchema** pSchema));
|
||||||
|
MOCK_METHOD2_WITH_CALLTYPE(__stdcall, GetElementByName, HRESULT(BSTR bstrSubName, IAppHostElement ** ppElement));
|
||||||
|
MOCK_METHOD2_WITH_CALLTYPE(__stdcall, GetPropertyByName, HRESULT(BSTR bstrSubName, IAppHostProperty ** ppProperty));
|
||||||
|
MOCK_METHOD0_WITH_CALLTYPE(__stdcall, Clear, HRESULT());
|
||||||
|
MOCK_METHOD1_WITH_CALLTYPE(__stdcall, get_Methods, HRESULT(IAppHostMethodCollection ** ppMethods));
|
||||||
|
};
|
||||||
|
|
||||||
class MockHttpServer : public IHttpServer
|
class MockHttpServer : public IHttpServer
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@
|
||||||
|
|
||||||
#include "requesthandler_config.h"
|
#include "requesthandler_config.h"
|
||||||
#include "hostfxr_utility.h"
|
#include "hostfxr_utility.h"
|
||||||
|
#include "config_utility.h"
|
||||||
#include "environmentvariablehash.h"
|
#include "environmentvariablehash.h"
|
||||||
#include "iapplication.h"
|
#include "iapplication.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
|
@ -51,9 +52,11 @@
|
||||||
#include "resources.h"
|
#include "resources.h"
|
||||||
#include "aspnetcore_msg.h"
|
#include "aspnetcore_msg.h"
|
||||||
#include "Helpers.h"
|
#include "Helpers.h"
|
||||||
|
#include "GlobalVersionUtility.h"
|
||||||
|
|
||||||
#undef assert // Macro redefinition in IISLib.
|
#undef assert // Macro redefinition in IISLib.
|
||||||
#include "gtest\gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
#include "fakeclasses.h"
|
||||||
|
|
||||||
// Externals defined in inprocess
|
// Externals defined in inprocess
|
||||||
BOOL g_fProcessDetach;
|
BOOL g_fProcessDetach;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,160 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
using IISIntegration.FunctionalTests.Utilities;
|
||||||
|
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
||||||
|
using Xunit;
|
||||||
|
using Xunit.Abstractions;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
|
||||||
|
{
|
||||||
|
public class GlobalVersionTests : IISFunctionalTestBase
|
||||||
|
{
|
||||||
|
private const string _aspNetCoreDll = "aspnetcorev2_outofprocess.dll";
|
||||||
|
private const string _handlerVersion20 = "2.0.0";
|
||||||
|
private const string _helloWorldRequest = "HelloWorld";
|
||||||
|
private const string _helloWorldResponse = "Hello World";
|
||||||
|
private const string _outOfProcessVersionVariable = "/p:AspNetCoreModuleOutOfProcessVersion=";
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GlobalVersion_DefaultWorks()
|
||||||
|
{
|
||||||
|
var deploymentParameters = GetGlobalVersionBaseDeploymentParameters();
|
||||||
|
deploymentParameters.PublishApplicationBeforeDeployment = false;
|
||||||
|
|
||||||
|
deploymentParameters.ServerConfigTemplateContent = GetServerConfig(
|
||||||
|
element =>
|
||||||
|
{
|
||||||
|
var handlerVersionElement = new XElement("handlerSetting");
|
||||||
|
handlerVersionElement.SetAttributeValue("name", "handlerVersion");
|
||||||
|
handlerVersionElement.SetAttributeValue("value", _handlerVersion20);
|
||||||
|
|
||||||
|
element.Descendants("aspNetCore").Single()
|
||||||
|
.Add(new XElement("handlerSettings", handlerVersionElement));
|
||||||
|
});
|
||||||
|
|
||||||
|
var deploymentResult = await DeployAsync(deploymentParameters);
|
||||||
|
|
||||||
|
var response = await deploymentResult.RetryingHttpClient.GetAsync(_helloWorldRequest);
|
||||||
|
var responseText = await response.Content.ReadAsStringAsync();
|
||||||
|
Assert.Equal(_helloWorldResponse, responseText);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory] // Tests need to publish to change folder locations
|
||||||
|
[InlineData("2.1.0")]
|
||||||
|
[InlineData("2.1.0-preview")]
|
||||||
|
public async Task GlobalVersion_NewVersionNumber_Fails(string version)
|
||||||
|
{
|
||||||
|
var deploymentParameters = GetGlobalVersionBaseDeploymentParameters();
|
||||||
|
|
||||||
|
var deploymentResult = await DeployAsync(deploymentParameters);
|
||||||
|
|
||||||
|
Helpers.ModifyHandlerSectionInWebConfig(deploymentResult, version);
|
||||||
|
|
||||||
|
var response = await deploymentResult.RetryingHttpClient.GetAsync(_helloWorldRequest);
|
||||||
|
Assert.False(response.IsSuccessStatusCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory] // Tests need to publish to change folder locations
|
||||||
|
[InlineData("2.1.0")]
|
||||||
|
[InlineData("2.1.0-preview")]
|
||||||
|
public async Task GlobalVersion_NewVersionNumber(string version)
|
||||||
|
{
|
||||||
|
var deploymentParameters = GetGlobalVersionBaseDeploymentParameters();
|
||||||
|
deploymentParameters.AdditionalPublishParameters = $"{_outOfProcessVersionVariable}{version}";
|
||||||
|
|
||||||
|
var deploymentResult = await DeployAsync(deploymentParameters);
|
||||||
|
|
||||||
|
Helpers.ModifyHandlerSectionInWebConfig(deploymentResult, version);
|
||||||
|
|
||||||
|
var response = await deploymentResult.RetryingHttpClient.GetAsync(_helloWorldRequest);
|
||||||
|
var responseText = await response.Content.ReadAsStringAsync();
|
||||||
|
Assert.Equal(_helloWorldResponse, responseText);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory] // Tests need to publish to change folder locations
|
||||||
|
[InlineData("2.1.0")]
|
||||||
|
[InlineData("2.1.0-preview")]
|
||||||
|
public async Task GlobalVersion_MultipleRequestHandlers_PicksHighestOne(string version)
|
||||||
|
{
|
||||||
|
var deploymentParameters = GetGlobalVersionBaseDeploymentParameters();
|
||||||
|
|
||||||
|
var deploymentResult = await DeployAsync(deploymentParameters);
|
||||||
|
|
||||||
|
var originalANCMPath = GetANCMRequestHandlerPath(deploymentResult, _handlerVersion20);
|
||||||
|
|
||||||
|
var newANCMPath = GetANCMRequestHandlerPath(deploymentResult, version);
|
||||||
|
|
||||||
|
var di = Directory.CreateDirectory(Path.GetDirectoryName(newANCMPath));
|
||||||
|
|
||||||
|
File.Copy(originalANCMPath, newANCMPath, true);
|
||||||
|
|
||||||
|
deploymentResult.RetryingHttpClient.DefaultRequestHeaders.Add("ANCMRHPath", newANCMPath);
|
||||||
|
var response = await deploymentResult.RetryingHttpClient.GetAsync("CheckRequestHandlerVersion");
|
||||||
|
var responseText = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
Assert.Equal(_helloWorldResponse, responseText);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("2.1.0")]
|
||||||
|
[InlineData("2.1.0-preview")]
|
||||||
|
public async Task GlobalVersion_MultipleRequestHandlers_UpgradeWorks(string version)
|
||||||
|
{
|
||||||
|
var deploymentParameters = GetGlobalVersionBaseDeploymentParameters();
|
||||||
|
var deploymentResult = await DeployAsync(deploymentParameters);
|
||||||
|
|
||||||
|
var originalANCMPath = GetANCMRequestHandlerPath(deploymentResult, _handlerVersion20);
|
||||||
|
|
||||||
|
deploymentResult.RetryingHttpClient.DefaultRequestHeaders.Add("ANCMRHPath", originalANCMPath);
|
||||||
|
var response = await deploymentResult.RetryingHttpClient.GetAsync("CheckRequestHandlerVersion");
|
||||||
|
var responseText = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
Assert.Equal(_helloWorldResponse, responseText);
|
||||||
|
|
||||||
|
Dispose();
|
||||||
|
|
||||||
|
deploymentResult = await DeployAsync(deploymentParameters);
|
||||||
|
|
||||||
|
originalANCMPath = GetANCMRequestHandlerPath(deploymentResult, _handlerVersion20);
|
||||||
|
|
||||||
|
var newANCMPath = GetANCMRequestHandlerPath(deploymentResult, version);
|
||||||
|
|
||||||
|
var di = Directory.CreateDirectory(Path.GetDirectoryName(newANCMPath));
|
||||||
|
|
||||||
|
File.Copy(originalANCMPath, newANCMPath, true);
|
||||||
|
|
||||||
|
deploymentResult.RetryingHttpClient.DefaultRequestHeaders.Add("ANCMRHPath", newANCMPath);
|
||||||
|
response = await deploymentResult.RetryingHttpClient.GetAsync("CheckRequestHandlerVersion");
|
||||||
|
responseText = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
Assert.Equal(_helloWorldResponse, responseText);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DeploymentParameters GetGlobalVersionBaseDeploymentParameters()
|
||||||
|
{
|
||||||
|
return new DeploymentParameters(Helpers.GetOutOfProcessTestSitesPath(), ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64)
|
||||||
|
{
|
||||||
|
TargetFramework = Tfm.NetCoreApp22,
|
||||||
|
ApplicationType = ApplicationType.Portable,
|
||||||
|
AncmVersion = AncmVersion.AspNetCoreModuleV2,
|
||||||
|
HostingModel = HostingModel.OutOfProcess,
|
||||||
|
PublishApplicationBeforeDeployment = true,
|
||||||
|
AdditionalPublishParameters = $"{_outOfProcessVersionVariable}{_handlerVersion20}"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetANCMRequestHandlerPath(IISDeploymentResult deploymentResult, string version)
|
||||||
|
{
|
||||||
|
return Path.Combine(deploymentResult.DeploymentResult.ContentRoot,
|
||||||
|
deploymentResult.DeploymentResult.DeploymentParameters.RuntimeArchitecture.ToString(),
|
||||||
|
version,
|
||||||
|
_aspNetCoreDll);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -21,16 +21,31 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
|
||||||
public static string GetOutOfProcessTestSitesPath() => GetTestWebSitePath("OutOfProcessWebSite");
|
public static string GetOutOfProcessTestSitesPath() => GetTestWebSitePath("OutOfProcessWebSite");
|
||||||
|
|
||||||
public static void ModifyAspNetCoreSectionInWebConfig(IISDeploymentResult deploymentResult, string key, string value)
|
public static void ModifyAspNetCoreSectionInWebConfig(IISDeploymentResult deploymentResult, string key, string value)
|
||||||
=> ModifySectionInWebConfig(deploymentResult, key, value, section: "aspNetCore", 0);
|
=> ModifyAttributeInWebConfig(deploymentResult, key, value, section: "aspNetCore");
|
||||||
|
|
||||||
public static void ModifySectionInWebConfig(IISDeploymentResult deploymentResult, string key, string value, string section, int index)
|
public static void ModifyAttributeInWebConfig(IISDeploymentResult deploymentResult, string key, string value, string section)
|
||||||
{
|
{
|
||||||
// modify the web.config after publish
|
var webConfigFile = GetWebConfigFile(deploymentResult);
|
||||||
var root = deploymentResult.DeploymentResult.ContentRoot;
|
|
||||||
var webConfigFile = $"{root}/web.config";
|
|
||||||
var config = XDocument.Load(webConfigFile);
|
var config = XDocument.Load(webConfigFile);
|
||||||
var element = config.Descendants(section).ToList()[index];
|
|
||||||
|
var element = config.Descendants(section).Single();
|
||||||
element.SetAttributeValue(key, value);
|
element.SetAttributeValue(key, value);
|
||||||
|
|
||||||
|
config.Save(webConfigFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ModifyHandlerSectionInWebConfig(IISDeploymentResult deploymentResult, string handlerVersionValue)
|
||||||
|
{
|
||||||
|
var webConfigFile = GetWebConfigFile(deploymentResult);
|
||||||
|
var config = XDocument.Load(webConfigFile);
|
||||||
|
|
||||||
|
var handlerVersionElement = new XElement("handlerSetting");
|
||||||
|
handlerVersionElement.SetAttributeValue("name", "handlerVersion");
|
||||||
|
handlerVersionElement.SetAttributeValue("value", handlerVersionValue);
|
||||||
|
|
||||||
|
config.Descendants("aspNetCore").Single()
|
||||||
|
.Add(new XElement("handlerSettings", handlerVersionElement));
|
||||||
|
|
||||||
config.Save(webConfigFile);
|
config.Save(webConfigFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -46,5 +61,8 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
|
||||||
PublishApplicationBeforeDeployment = site == "InProcessWebSite",
|
PublishApplicationBeforeDeployment = site == "InProcessWebSite",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string GetWebConfigFile(IISDeploymentResult deploymentResult)
|
||||||
|
=> Path.Combine(deploymentResult.DeploymentResult.ContentRoot, "web.config");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,9 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Security.Principal;
|
using System.Security.Principal;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Authentication;
|
using Microsoft.AspNetCore.Authentication;
|
||||||
|
|
@ -84,5 +86,22 @@ namespace TestSites
|
||||||
|
|
||||||
public Task UpgradeFeatureDetection(HttpContext context) =>
|
public Task UpgradeFeatureDetection(HttpContext context) =>
|
||||||
context.Response.WriteAsync(context.Features.Get<IHttpUpgradeFeature>() != null? "Enabled": "Disabled");
|
context.Response.WriteAsync(context.Features.Get<IHttpUpgradeFeature>() != null? "Enabled": "Disabled");
|
||||||
|
|
||||||
|
public Task CheckRequestHandlerVersion(HttpContext context)
|
||||||
|
{
|
||||||
|
// We need to check if the aspnetcorev2_outofprocess dll is loaded by iisexpress.exe
|
||||||
|
// As they aren't in the same process, we will try to delete the file and expect a file
|
||||||
|
// in use error
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File.Delete(context.Request.Headers["ANCMRHPath"]);
|
||||||
|
}
|
||||||
|
catch(UnauthorizedAccessException)
|
||||||
|
{
|
||||||
|
return context.Response.WriteAsync("Hello World");
|
||||||
|
}
|
||||||
|
|
||||||
|
return context.Response.WriteAsync(context.Request.Headers["ANCMRHPath"]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
</ProjectConfiguration>
|
</ProjectConfiguration>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="googletest\googlemock\src\gmock-all.cc" />
|
||||||
<ClCompile Include="googletest\googletest\src\gtest-all.cc" />
|
<ClCompile Include="googletest\googletest\src\gtest-all.cc" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
|
|
@ -105,7 +106,7 @@
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<AdditionalIncludeDirectories>googletest\googletest\include;googletest\googletest;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>googletest\googletest\include;googletest\googletest;googletest\googlemock;googletest\googlemock\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
|
|
@ -121,7 +122,7 @@
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<AdditionalIncludeDirectories>googletest\googletest\include;googletest\googletest;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>googletest\googletest\include;googletest\googletest;googletest\googlemock;googletest\googlemock\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
|
|
@ -139,7 +140,7 @@
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<AdditionalIncludeDirectories>googletest\googletest\include;googletest\googletest;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>googletest\googletest\include;googletest\googletest;googletest\googlemock;googletest\googlemock\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
|
|
@ -159,7 +160,7 @@
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<AdditionalIncludeDirectories>googletest\googletest\include;googletest\googletest;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>googletest\googletest\include;googletest\googletest;googletest\googlemock;googletest\googlemock\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
|
|
|
||||||
|
|
@ -11,5 +11,6 @@
|
||||||
<AspNetCoreModuleVersionMajor>8</AspNetCoreModuleVersionMajor>
|
<AspNetCoreModuleVersionMajor>8</AspNetCoreModuleVersionMajor>
|
||||||
<AspNetCoreModuleVersionMinor>1</AspNetCoreModuleVersionMinor>
|
<AspNetCoreModuleVersionMinor>1</AspNetCoreModuleVersionMinor>
|
||||||
<AspNetCoreModuleVersionRevision>0</AspNetCoreModuleVersionRevision>
|
<AspNetCoreModuleVersionRevision>0</AspNetCoreModuleVersionRevision>
|
||||||
|
<AspNetCoreModuleOutOfProcessVersion>2.0.0</AspNetCoreModuleOutOfProcessVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue