Improve logging architecture; add tests for logging and startup exceptions (#858)
This commit is contained in:
parent
f09edb3b5d
commit
e1ae70166b
|
|
@ -37,6 +37,7 @@ project.lock.json
|
|||
*.tlog
|
||||
*.CppClean.log
|
||||
*msbuild.log
|
||||
gtest.log
|
||||
|
||||
src/*/*/Debug/
|
||||
src/*/*/x64/Debug/
|
||||
|
|
|
|||
|
|
@ -115,6 +115,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InProcessRequestHandler", "
|
|||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OutOfProcessRequestHandler", "src\AspNetCoreModuleV2\OutOfProcessRequestHandler\OutOfProcessRequestHandler.vcxproj", "{7F87406C-A3C8-4139-A68D-E4C344294A67}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StartupExceptionWebSite", "test\WebSites\StartupExceptionWebSite\StartupExceptionWebSite.csproj", "{340C59FC-C682-4CBA-81F8-791821EC8EDE}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -359,6 +361,16 @@ Global
|
|||
{7F87406C-A3C8-4139-A68D-E4C344294A67}.Release|x64.Build.0 = Release|x64
|
||||
{7F87406C-A3C8-4139-A68D-E4C344294A67}.Release|x86.ActiveCfg = Release|Win32
|
||||
{7F87406C-A3C8-4139-A68D-E4C344294A67}.Release|x86.Build.0 = Release|Win32
|
||||
{340C59FC-C682-4CBA-81F8-791821EC8EDE}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||
{340C59FC-C682-4CBA-81F8-791821EC8EDE}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{340C59FC-C682-4CBA-81F8-791821EC8EDE}.Debug|x64.Build.0 = Debug|x64
|
||||
{340C59FC-C682-4CBA-81F8-791821EC8EDE}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{340C59FC-C682-4CBA-81F8-791821EC8EDE}.Debug|x86.Build.0 = Debug|x86
|
||||
{340C59FC-C682-4CBA-81F8-791821EC8EDE}.Release|Any CPU.ActiveCfg = Release|x86
|
||||
{340C59FC-C682-4CBA-81F8-791821EC8EDE}.Release|x64.ActiveCfg = Release|x64
|
||||
{340C59FC-C682-4CBA-81F8-791821EC8EDE}.Release|x64.Build.0 = Release|x64
|
||||
{340C59FC-C682-4CBA-81F8-791821EC8EDE}.Release|x86.ActiveCfg = Release|x86
|
||||
{340C59FC-C682-4CBA-81F8-791821EC8EDE}.Release|x86.Build.0 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
@ -388,6 +400,7 @@ Global
|
|||
{48F46909-E76A-4788-BCE1-E543C0E140FE} = {622D35C9-627B-466E-8D15-752968CC79AF}
|
||||
{D57EA297-6DC2-4BC0-8C91-334863327863} = {06CA2C2B-83B0-4D83-905A-E0C74790009E}
|
||||
{7F87406C-A3C8-4139-A68D-E4C344294A67} = {06CA2C2B-83B0-4D83-905A-E0C74790009E}
|
||||
{340C59FC-C682-4CBA-81F8-791821EC8EDE} = {744ACDC6-F6A0-4FF9-9421-F25C5F2DC520}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {DB4F868D-E1AE-4FD7-9333-69FA15B268C5}
|
||||
|
|
|
|||
|
|
@ -1,238 +1,247 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{55494E58-E061-4C4C-A0A8-837008E72F85}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>NewCommon</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IncludePath>C:\AspNetCoreModule\src\IISLib;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<ShowIncludes>false</ShowIncludes>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<AdditionalIncludeDirectories>..\iislib;</AdditionalIncludeDirectories>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<ShowIncludes>false</ShowIncludes>
|
||||
<AdditionalIncludeDirectories>..\iislib;</AdditionalIncludeDirectories>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<ShowIncludes>false</ShowIncludes>
|
||||
<AdditionalIncludeDirectories>..\iislib;</AdditionalIncludeDirectories>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>..\iislib;</AdditionalIncludeDirectories>
|
||||
<AdditionalUsingDirectories>
|
||||
</AdditionalUsingDirectories>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<ShowIncludes>false</ShowIncludes>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
<Lib>
|
||||
<AdditionalLibraryDirectories>..\iislib</AdditionalLibraryDirectories>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="application.h" />
|
||||
<ClInclude Include="fx_ver.h" />
|
||||
<ClInclude Include="hostfxroptions.h" />
|
||||
<ClInclude Include="hostfxr_utility.h" />
|
||||
<ClInclude Include="iapplication.h" />
|
||||
<ClInclude Include="debugutil.h" />
|
||||
<ClInclude Include="disconnectcontext.h" />
|
||||
<ClInclude Include="environmentvariablehash.h" />
|
||||
<ClInclude Include="irequesthandler.h" />
|
||||
<ClInclude Include="requesthandler.h" />
|
||||
<ClInclude Include="requesthandler_config.h" />
|
||||
<ClInclude Include="resources.h" />
|
||||
<ClInclude Include="SRWLockWrapper.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="utility.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="fx_ver.cxx" />
|
||||
<ClCompile Include="hostfxroptions.cpp" />
|
||||
<ClCompile Include="hostfxr_utility.cpp" />
|
||||
<ClCompile Include="requesthandler_config.cpp" />
|
||||
<ClCompile Include="SRWLockWrapper.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="utility.cxx" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\IISLib\IISLib.vcxproj">
|
||||
<Project>{4787a64f-9a3e-4867-a55a-70cb4b2b2ffe}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="aspnetcore_msg.mc">
|
||||
<FileType>Document</FileType>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">mc %(FullPath)</Command>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Compiling Event Messages ...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(Filename).rc;%(Filename).h;MSG0409.bin</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">mc %(FullPath)</Command>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Compiling Event Messages ...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(Filename).rc;%(Filename).h;MSG0409.bin</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">mc %(FullPath)</Command>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Compiling Event Messages ...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(Filename).rc;%(Filename).h;MSG0409.bin</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">mc %(FullPath)</Command>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Compiling Event Messages ...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(Filename).rc;%(Filename).h;MSG0409.bin</Outputs>
|
||||
</CustomBuild>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{55494E58-E061-4C4C-A0A8-837008E72F85}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>NewCommon</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IncludePath>C:\AspNetCoreModule\src\IISLib;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<ShowIncludes>false</ShowIncludes>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<AdditionalIncludeDirectories>..\iislib;</AdditionalIncludeDirectories>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<ShowIncludes>false</ShowIncludes>
|
||||
<AdditionalIncludeDirectories>..\iislib;</AdditionalIncludeDirectories>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<ShowIncludes>false</ShowIncludes>
|
||||
<AdditionalIncludeDirectories>..\iislib;</AdditionalIncludeDirectories>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>..\iislib;</AdditionalIncludeDirectories>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<AdditionalUsingDirectories>
|
||||
</AdditionalUsingDirectories>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<ShowIncludes>false</ShowIncludes>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
<Lib>
|
||||
<AdditionalLibraryDirectories>..\iislib</AdditionalLibraryDirectories>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="application.h" />
|
||||
<ClInclude Include="NullOutputManager.h" />
|
||||
<ClInclude Include="FileOutputManager.h" />
|
||||
<ClInclude Include="fx_ver.h" />
|
||||
<ClInclude Include="hostfxroptions.h" />
|
||||
<ClInclude Include="hostfxr_utility.h" />
|
||||
<ClInclude Include="iapplication.h" />
|
||||
<ClInclude Include="debugutil.h" />
|
||||
<ClInclude Include="disconnectcontext.h" />
|
||||
<ClInclude Include="environmentvariablehash.h" />
|
||||
<ClInclude Include="IOutputManager.h" />
|
||||
<ClInclude Include="irequesthandler.h" />
|
||||
<ClInclude Include="LoggingHelpers.h" />
|
||||
<ClInclude Include="PipeOutputManager.h" />
|
||||
<ClInclude Include="requesthandler.h" />
|
||||
<ClInclude Include="requesthandler_config.h" />
|
||||
<ClInclude Include="resources.h" />
|
||||
<ClInclude Include="SRWLockWrapper.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="sttimer.h" />
|
||||
<ClInclude Include="utility.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="FileOutputManager.cpp" />
|
||||
<ClCompile Include="fx_ver.cxx" />
|
||||
<ClCompile Include="hostfxr_utility.cpp" />
|
||||
<ClCompile Include="hostfxroptions.cpp" />
|
||||
<ClCompile Include="requesthandler_config.cpp" />
|
||||
<ClCompile Include="LoggingHelpers.cpp" />
|
||||
<ClCompile Include="PipeOutputManager.cpp" />
|
||||
<ClCompile Include="SRWLockWrapper.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="utility.cxx" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\IISLib\IISLib.vcxproj">
|
||||
<Project>{4787a64f-9a3e-4867-a55a-70cb4b2b2ffe}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="aspnetcore_msg.mc">
|
||||
<FileType>Document</FileType>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">mc %(FullPath)</Command>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Compiling Event Messages ...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(Filename).rc;%(Filename).h;MSG0409.bin</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">mc %(FullPath)</Command>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Compiling Event Messages ...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(Filename).rc;%(Filename).h;MSG0409.bin</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">mc %(FullPath)</Command>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Compiling Event Messages ...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(Filename).rc;%(Filename).h;MSG0409.bin</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">mc %(FullPath)</Command>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Compiling Event Messages ...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(Filename).rc;%(Filename).h;MSG0409.bin</Outputs>
|
||||
</CustomBuild>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,184 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
|
||||
FileOutputManager::FileOutputManager()
|
||||
: m_pStdOutFile(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
FileOutputManager::~FileOutputManager()
|
||||
{
|
||||
HANDLE handle = NULL;
|
||||
WIN32_FIND_DATA fileData;
|
||||
|
||||
if (m_pStdOutFile != NULL)
|
||||
{
|
||||
m_Timer.CancelTimer();
|
||||
_close(_fileno(m_pStdOutFile));
|
||||
m_pStdOutFile = NULL;
|
||||
}
|
||||
|
||||
// delete empty log file
|
||||
handle = FindFirstFile(m_struLogFilePath.QueryStr(), &fileData);
|
||||
if (handle != INVALID_HANDLE_VALUE &&
|
||||
fileData.nFileSizeHigh == 0 &&
|
||||
fileData.nFileSizeLow == 0) // skip check of nFileSizeHigh
|
||||
{
|
||||
FindClose(handle);
|
||||
// no need to check whether the deletion succeeds
|
||||
// as nothing can be done
|
||||
DeleteFile(m_struLogFilePath.QueryStr());
|
||||
}
|
||||
|
||||
_dup2(m_fdStdOut, _fileno(stdout));
|
||||
_dup2(m_fdStdErr, _fileno(stderr));
|
||||
}
|
||||
|
||||
HRESULT
|
||||
FileOutputManager::Initialize(PCWSTR pwzStdOutLogFileName, PCWSTR pwzApplicationPath)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (SUCCEEDED(hr = m_wsApplicationPath.Copy(pwzApplicationPath)))
|
||||
{
|
||||
hr = m_wsStdOutLogFileName.Copy(pwzStdOutLogFileName);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
void FileOutputManager::NotifyStartupComplete()
|
||||
{
|
||||
}
|
||||
|
||||
bool FileOutputManager::GetStdOutContent(STRA* struStdOutput)
|
||||
{
|
||||
//
|
||||
// Ungraceful shutdown, try to log an error message.
|
||||
// This will be a common place for errors as it means the hostfxr_main returned
|
||||
// or there was an exception.
|
||||
//
|
||||
CHAR pzFileContents[4096] = { 0 };
|
||||
DWORD dwNumBytesRead;
|
||||
LARGE_INTEGER li = { 0 };
|
||||
BOOL fLogged = FALSE;
|
||||
DWORD dwFilePointer = 0;
|
||||
|
||||
if (m_hLogFileHandle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (GetFileSizeEx(m_hLogFileHandle, &li) && li.LowPart > 0 && li.HighPart == 0)
|
||||
{
|
||||
if (li.LowPart > 4096)
|
||||
{
|
||||
dwFilePointer = SetFilePointer(m_hLogFileHandle, -4096, NULL, FILE_END);
|
||||
}
|
||||
else
|
||||
{
|
||||
dwFilePointer = SetFilePointer(m_hLogFileHandle, 0, NULL, FILE_BEGIN);
|
||||
}
|
||||
|
||||
if (dwFilePointer != INVALID_SET_FILE_POINTER)
|
||||
{
|
||||
// Read file fails.
|
||||
if (ReadFile(m_hLogFileHandle, pzFileContents, 4096, &dwNumBytesRead, NULL))
|
||||
{
|
||||
if (SUCCEEDED(struStdOutput->Copy(pzFileContents, dwNumBytesRead)))
|
||||
{
|
||||
fLogged = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fLogged;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
FileOutputManager::Start()
|
||||
{
|
||||
HRESULT hr;
|
||||
SYSTEMTIME systemTime;
|
||||
SECURITY_ATTRIBUTES saAttr = { 0 };
|
||||
STRU struPath;
|
||||
|
||||
hr = UTILITY::ConvertPathToFullPath(
|
||||
m_wsStdOutLogFileName.QueryStr(),
|
||||
m_wsApplicationPath.QueryStr(),
|
||||
&struPath);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = UTILITY::EnsureDirectoryPathExist(struPath.QueryStr());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
m_fdStdOut = _dup(_fileno(stdout));
|
||||
if (m_fdStdOut == -1)
|
||||
{
|
||||
hr = E_HANDLE;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
m_fdStdErr = _dup(_fileno(stderr));
|
||||
if (m_fdStdErr == -1)
|
||||
{
|
||||
hr = E_HANDLE;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
GetSystemTime(&systemTime);
|
||||
hr = m_struLogFilePath.SafeSnwprintf(L"%s_%d%02d%02d%02d%02d%02d_%d.log",
|
||||
struPath.QueryStr(),
|
||||
systemTime.wYear,
|
||||
systemTime.wMonth,
|
||||
systemTime.wDay,
|
||||
systemTime.wHour,
|
||||
systemTime.wMinute,
|
||||
systemTime.wSecond,
|
||||
GetCurrentProcessId());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
saAttr.bInheritHandle = TRUE;
|
||||
saAttr.lpSecurityDescriptor = NULL;
|
||||
|
||||
if (_wfreopen_s(&m_pStdOutFile, m_struLogFilePath.QueryStr(), L"w+", stdout) == 0)
|
||||
{
|
||||
setvbuf(m_pStdOutFile, NULL, _IONBF, 0);
|
||||
if (_dup2(_fileno(m_pStdOutFile), _fileno(stdout)) == -1)
|
||||
{
|
||||
hr = E_HANDLE;
|
||||
goto Finished;
|
||||
}
|
||||
if (_dup2(_fileno(m_pStdOutFile), _fileno(stderr)) == -1)
|
||||
{
|
||||
hr = E_HANDLE;
|
||||
goto Finished;
|
||||
}
|
||||
}
|
||||
|
||||
m_hLogFileHandle = (HANDLE)_get_osfhandle(_fileno(m_pStdOutFile));
|
||||
if (m_hLogFileHandle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
hr = E_HANDLE;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
// Periodically flush the log content to file
|
||||
m_Timer.InitializeTimer(STTIMER::TimerCallback, &m_struLogFilePath, FILE_FLUSH_TIMEOUT, FILE_FLUSH_TIMEOUT);
|
||||
|
||||
Finished:
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
class FileOutputManager : public IOutputManager
|
||||
{
|
||||
#define FILE_FLUSH_TIMEOUT 3000
|
||||
public:
|
||||
FileOutputManager();
|
||||
~FileOutputManager();
|
||||
|
||||
HRESULT
|
||||
Initialize(PCWSTR pwzStdOutLogFileName, PCWSTR pwzApplciationpath);
|
||||
|
||||
virtual bool GetStdOutContent(STRA* struStdOutput) override;
|
||||
virtual HRESULT Start() override;
|
||||
virtual void NotifyStartupComplete() override;
|
||||
|
||||
private:
|
||||
HANDLE m_hLogFileHandle;
|
||||
STTIMER m_Timer;
|
||||
STRU m_wsStdOutLogFileName;
|
||||
STRU m_wsApplicationPath;
|
||||
STRU m_struLogFilePath;
|
||||
int m_fdStdOut;
|
||||
int m_fdStdErr;
|
||||
FILE* m_pStdOutFile;
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#pragma once
|
||||
class IOutputManager
|
||||
{
|
||||
public:
|
||||
virtual
|
||||
HRESULT
|
||||
Start() = 0;
|
||||
|
||||
virtual
|
||||
~IOutputManager() {};
|
||||
|
||||
virtual
|
||||
void
|
||||
NotifyStartupComplete() = 0;
|
||||
|
||||
virtual
|
||||
bool
|
||||
GetStdOutContent(STRA* struStdOutput) = 0;
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
HRESULT
|
||||
LoggingHelpers::CreateLoggingProvider(
|
||||
bool fIsLoggingEnabled,
|
||||
bool fEnablePipe,
|
||||
PCWSTR pwzStdOutFileName,
|
||||
PCWSTR pwzApplicationPath,
|
||||
_Out_ IOutputManager** outputManager
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
DBG_ASSERT(outputManager != NULL);
|
||||
|
||||
if (fIsLoggingEnabled)
|
||||
{
|
||||
FileOutputManager* manager = new FileOutputManager;
|
||||
hr = manager->Initialize(pwzStdOutFileName, pwzApplicationPath);
|
||||
*outputManager = manager;
|
||||
}
|
||||
else if (fEnablePipe)
|
||||
{
|
||||
*outputManager = new PipeOutputManager;
|
||||
}
|
||||
else
|
||||
{
|
||||
*outputManager = new NullOutputManager;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
class LoggingHelpers
|
||||
{
|
||||
public:
|
||||
|
||||
static
|
||||
HRESULT
|
||||
CreateLoggingProvider(
|
||||
bool fLoggingEnabled,
|
||||
bool fEnablePipe,
|
||||
PCWSTR pwzStdOutFileName,
|
||||
PCWSTR pwzApplicationPath,
|
||||
_Out_ IOutputManager** outputManager
|
||||
);
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
class NullOutputManager : public IOutputManager
|
||||
{
|
||||
public:
|
||||
|
||||
NullOutputManager() = default;
|
||||
|
||||
~NullOutputManager() = default;
|
||||
|
||||
HRESULT Start()
|
||||
{
|
||||
// The process has console, e.g., IIS Express scenario
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void NotifyStartupComplete()
|
||||
{
|
||||
}
|
||||
|
||||
bool GetStdOutContent(STRA*)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,196 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
PipeOutputManager::PipeOutputManager() :
|
||||
m_dwStdErrReadTotal(0),
|
||||
m_hErrReadPipe(INVALID_HANDLE_VALUE),
|
||||
m_hErrWritePipe(INVALID_HANDLE_VALUE),
|
||||
m_hErrThread(INVALID_HANDLE_VALUE),
|
||||
m_fDisposed(FALSE)
|
||||
{
|
||||
}
|
||||
|
||||
PipeOutputManager::~PipeOutputManager()
|
||||
{
|
||||
StopOutputRedirection();
|
||||
}
|
||||
|
||||
VOID
|
||||
PipeOutputManager::StopOutputRedirection()
|
||||
{
|
||||
DWORD dwThreadStatus = 0;
|
||||
STRA straStdOutput;
|
||||
|
||||
if (m_fDisposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_fDisposed = true;
|
||||
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
|
||||
if (m_hErrWritePipe != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
CloseHandle(m_hErrWritePipe);
|
||||
m_hErrWritePipe = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
if (m_hErrThread != NULL &&
|
||||
GetExitCodeThread(m_hErrThread, &dwThreadStatus) != 0 &&
|
||||
dwThreadStatus == STILL_ACTIVE)
|
||||
{
|
||||
// wait for gracefullshut down, i.e., the exit of the background thread or timeout
|
||||
if (WaitForSingleObject(m_hErrThread, PIPE_OUTPUT_THREAD_TIMEOUT) != WAIT_OBJECT_0)
|
||||
{
|
||||
// if the thread is still running, we need kill it first before exit to avoid AV
|
||||
if (GetExitCodeThread(m_hErrThread, &dwThreadStatus) != 0 && dwThreadStatus == STILL_ACTIVE)
|
||||
{
|
||||
TerminateThread(m_hErrThread, STATUS_CONTROL_C_EXIT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(m_hErrThread);
|
||||
m_hErrThread = NULL;
|
||||
|
||||
if (m_hErrReadPipe != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
CloseHandle(m_hErrReadPipe);
|
||||
m_hErrReadPipe = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
// Restore the original stdout and stderr handles of the process,
|
||||
// as the application has either finished startup or has exited.
|
||||
if (_dup2(m_fdStdOut, _fileno(stdout)) == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_dup2(m_fdStdErr, _fileno(stderr)) == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetStdOutContent(&straStdOutput))
|
||||
{
|
||||
printf(straStdOutput.QueryStr());
|
||||
// Need to flush contents.
|
||||
_flushall();
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT PipeOutputManager::Start()
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
SECURITY_ATTRIBUTES saAttr = { 0 };
|
||||
HANDLE hStdErrReadPipe;
|
||||
HANDLE hStdErrWritePipe;
|
||||
|
||||
m_fdStdOut = _dup(_fileno(stdout));
|
||||
if (m_fdStdOut == -1)
|
||||
{
|
||||
hr = E_HANDLE;
|
||||
goto Finished;
|
||||
}
|
||||
m_fdStdErr = _dup(_fileno(stderr));
|
||||
if (m_fdStdErr == -1)
|
||||
{
|
||||
hr = E_HANDLE;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (!CreatePipe(&hStdErrReadPipe, &hStdErrWritePipe, &saAttr, 0 /*nSize*/))
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
// TODO this still doesn't redirect calls in native, like wprintf
|
||||
if (!SetStdHandle(STD_ERROR_HANDLE, hStdErrWritePipe))
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (!SetStdHandle(STD_OUTPUT_HANDLE, hStdErrWritePipe))
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
m_hErrReadPipe = hStdErrReadPipe;
|
||||
m_hErrWritePipe = hStdErrWritePipe;
|
||||
|
||||
// Read the stderr handle on a separate thread until we get 4096 bytes.
|
||||
m_hErrThread = CreateThread(
|
||||
NULL, // default security attributes
|
||||
0, // default stack size
|
||||
(LPTHREAD_START_ROUTINE)ReadStdErrHandle,
|
||||
this, // thread function arguments
|
||||
0, // default creation flags
|
||||
NULL); // receive thread identifier
|
||||
|
||||
if (m_hErrThread == NULL)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
Finished:
|
||||
return hr;
|
||||
}
|
||||
|
||||
VOID
|
||||
PipeOutputManager::ReadStdErrHandle(
|
||||
LPVOID pContext
|
||||
)
|
||||
{
|
||||
PipeOutputManager *pLoggingProvider = (PipeOutputManager*)pContext;
|
||||
DBG_ASSERT(pLoggingProvider != NULL);
|
||||
pLoggingProvider->ReadStdErrHandleInternal();
|
||||
}
|
||||
|
||||
bool PipeOutputManager::GetStdOutContent(STRA* struStdOutput)
|
||||
{
|
||||
bool fLogged = false;
|
||||
if (m_dwStdErrReadTotal > 0)
|
||||
{
|
||||
if (SUCCEEDED(struStdOutput->Copy(m_pzFileContents, m_dwStdErrReadTotal)))
|
||||
{
|
||||
fLogged = TRUE;
|
||||
}
|
||||
}
|
||||
return fLogged;
|
||||
}
|
||||
|
||||
VOID
|
||||
PipeOutputManager::ReadStdErrHandleInternal(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
DWORD dwNumBytesRead = 0;
|
||||
while (true)
|
||||
{
|
||||
if (ReadFile(m_hErrReadPipe, &m_pzFileContents[m_dwStdErrReadTotal], MAX_PIPE_READ_SIZE - m_dwStdErrReadTotal, &dwNumBytesRead, NULL))
|
||||
{
|
||||
m_dwStdErrReadTotal += dwNumBytesRead;
|
||||
if (m_dwStdErrReadTotal >= MAX_PIPE_READ_SIZE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (GetLastError() == ERROR_BROKEN_PIPE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
PipeOutputManager::NotifyStartupComplete()
|
||||
{
|
||||
StopOutputRedirection();
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
class PipeOutputManager : public IOutputManager
|
||||
{
|
||||
#define PIPE_OUTPUT_THREAD_TIMEOUT 2000
|
||||
#define MAX_PIPE_READ_SIZE 4096
|
||||
public:
|
||||
PipeOutputManager();
|
||||
~PipeOutputManager();
|
||||
|
||||
// Inherited via ILoggerProvider
|
||||
virtual HRESULT Start() override;
|
||||
virtual void NotifyStartupComplete() override;
|
||||
|
||||
// Inherited via IOutputManager
|
||||
virtual bool GetStdOutContent(STRA* struStdOutput) override;
|
||||
|
||||
VOID ReadStdErrHandleInternal(VOID);
|
||||
|
||||
static
|
||||
VOID ReadStdErrHandle(LPVOID pContext);
|
||||
|
||||
VOID StopOutputRedirection();
|
||||
private:
|
||||
HANDLE m_hErrReadPipe;
|
||||
HANDLE m_hErrWritePipe;
|
||||
STRU m_struLogFilePath;
|
||||
HANDLE m_hErrThread;
|
||||
CHAR m_pzFileContents[MAX_PIPE_READ_SIZE] = { 0 };
|
||||
BOOL m_fDisposed;
|
||||
DWORD m_dwStdErrReadTotal;
|
||||
int m_fdStdOut;
|
||||
int m_fdStdErr;
|
||||
};
|
||||
|
||||
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "SRWLockWrapper.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
class SRWLockWrapper
|
||||
{
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include <sstream>
|
||||
#include <memory>
|
||||
#include "Shlwapi.h"
|
||||
#include <io.h>
|
||||
#include "hashtable.h"
|
||||
#include "stringu.h"
|
||||
#include "stringa.h"
|
||||
|
|
@ -23,6 +24,7 @@
|
|||
#include "ahutil.h"
|
||||
#include "hashfn.h"
|
||||
#include "irequesthandler.h"
|
||||
#include "sttimer.h"
|
||||
#include "requesthandler.h"
|
||||
#include "iapplication.h"
|
||||
#include "application.h"
|
||||
|
|
@ -34,3 +36,8 @@
|
|||
#include "fx_ver.h"
|
||||
#include "hostfxr_utility.h"
|
||||
#include "hostfxroptions.h"
|
||||
#include "IOutputManager.h"
|
||||
#include "FileOutputManager.h"
|
||||
#include "PipeOutputManager.h"
|
||||
#include "NullOutputManager.h"
|
||||
#include "LoggingHelpers.h"
|
||||
|
|
|
|||
|
|
@ -214,7 +214,6 @@
|
|||
<ClInclude Include="disconnectcontext.h" />
|
||||
<ClInclude Include="environmentvariablehelpers.h" />
|
||||
<ClInclude Include="precomp.hxx" />
|
||||
<ClInclude Include="sttimer.h" />
|
||||
<ClInclude Include=".\inprocess\inprocessapplication.h" />
|
||||
<ClInclude Include=".\inprocess\inprocesshandler.h" />
|
||||
</ItemGroup>
|
||||
|
|
|
|||
|
|
@ -10,11 +10,6 @@ IN_PROCESS_APPLICATION::IN_PROCESS_APPLICATION(
|
|||
PCWSTR pDotnetExeLocation) :
|
||||
m_pHttpServer(pHttpServer),
|
||||
m_ProcessExitCode(0),
|
||||
m_hLogFileHandle(INVALID_HANDLE_VALUE),
|
||||
m_hErrReadPipe(INVALID_HANDLE_VALUE),
|
||||
m_hErrWritePipe(INVALID_HANDLE_VALUE),
|
||||
m_dwStdErrReadTotal(0),
|
||||
m_fDoneStdRedirect(FALSE),
|
||||
m_fBlockCallbacksIntoManaged(FALSE),
|
||||
m_fInitialized(FALSE),
|
||||
m_fShutdownCalledFromNative(FALSE),
|
||||
|
|
@ -35,12 +30,6 @@ IN_PROCESS_APPLICATION::IN_PROCESS_APPLICATION(
|
|||
|
||||
IN_PROCESS_APPLICATION::~IN_PROCESS_APPLICATION()
|
||||
{
|
||||
if (m_hLogFileHandle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
m_Timer.CancelTimer();
|
||||
CloseHandle(m_hLogFileHandle);
|
||||
m_hLogFileHandle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
if (m_pConfig != NULL)
|
||||
{
|
||||
|
|
@ -106,6 +95,12 @@ IN_PROCESS_APPLICATION::ShutDown(
|
|||
}
|
||||
}
|
||||
|
||||
if (m_pLoggerProvider != NULL)
|
||||
{
|
||||
delete m_pLoggerProvider;
|
||||
m_pLoggerProvider = NULL;
|
||||
}
|
||||
|
||||
Finished:
|
||||
|
||||
if (FAILED(hr))
|
||||
|
|
@ -131,8 +126,6 @@ IN_PROCESS_APPLICATION::ShutDownInternal()
|
|||
{
|
||||
DWORD dwThreadStatus = 0;
|
||||
DWORD dwTimeout = m_pConfig->QueryShutdownTimeLimitInMS();
|
||||
HANDLE handle = NULL;
|
||||
WIN32_FIND_DATA fileData;
|
||||
|
||||
if (IsDebuggerPresent())
|
||||
{
|
||||
|
|
@ -201,34 +194,6 @@ IN_PROCESS_APPLICATION::ShutDownInternal()
|
|||
CloseHandle(m_hThread);
|
||||
m_hThread = NULL;
|
||||
s_Application = NULL;
|
||||
|
||||
CloseStdErrHandles();
|
||||
|
||||
if (m_pStdFile != NULL)
|
||||
{
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
fclose(m_pStdFile);
|
||||
}
|
||||
|
||||
if (m_hLogFileHandle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
m_Timer.CancelTimer();
|
||||
CloseHandle(m_hLogFileHandle);
|
||||
m_hLogFileHandle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
// delete empty log file
|
||||
handle = FindFirstFile(m_struLogFilePath.QueryStr(), &fileData);
|
||||
if (handle != INVALID_HANDLE_VALUE &&
|
||||
fileData.nFileSizeHigh == 0 &&
|
||||
fileData.nFileSizeLow == 0) // skip check of nFileSizeHigh
|
||||
{
|
||||
FindClose(handle);
|
||||
// no need to check whether the deletion succeeds
|
||||
// as nothing can be done
|
||||
DeleteFile(m_struLogFilePath.QueryStr());
|
||||
}
|
||||
}
|
||||
|
||||
__override
|
||||
|
|
@ -371,263 +336,13 @@ IN_PROCESS_APPLICATION::SetCallbackHandles(
|
|||
m_ShutdownHandlerContext = pvShutdownHandlerContext;
|
||||
m_AsyncCompletionHandler = async_completion_handler;
|
||||
|
||||
CloseStdErrHandles();
|
||||
m_pLoggerProvider->NotifyStartupComplete();
|
||||
// Can't check the std err handle as it isn't a critical error
|
||||
SetStdHandle(STD_ERROR_HANDLE, INVALID_HANDLE_VALUE);
|
||||
// Initialization complete
|
||||
SetEvent(m_pInitalizeEvent);
|
||||
m_fInitialized = TRUE;
|
||||
}
|
||||
|
||||
VOID
|
||||
IN_PROCESS_APPLICATION::SetStdOut(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
STRU struPath;
|
||||
SYSTEMTIME systemTime;
|
||||
SECURITY_ATTRIBUTES saAttr = { 0 };
|
||||
HANDLE hStdErrReadPipe;
|
||||
HANDLE hStdErrWritePipe;
|
||||
|
||||
if (!m_fDoneStdRedirect)
|
||||
{
|
||||
// Have not set stdout yet, redirect stdout to log file
|
||||
SRWLockWrapper lock(m_srwLock);
|
||||
if (!m_fDoneStdRedirect)
|
||||
{
|
||||
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
saAttr.bInheritHandle = TRUE;
|
||||
saAttr.lpSecurityDescriptor = NULL;
|
||||
|
||||
//
|
||||
// best effort
|
||||
// no need to capture the error code as nothing we can do here
|
||||
// in case mamanged layer exits abnormally, may not be able to capture the log content as it is buffered.
|
||||
//
|
||||
if (!GetConsoleWindow())
|
||||
{
|
||||
// Full IIS scenario.
|
||||
|
||||
//
|
||||
// SetStdHandle works as w3wp does not have Console
|
||||
// Current process does not have a console
|
||||
//
|
||||
if (m_pConfig->QueryStdoutLogEnabled())
|
||||
{
|
||||
hr = UTILITY::ConvertPathToFullPath(
|
||||
m_pConfig->QueryStdoutLogFile()->QueryStr(),
|
||||
m_pConfig->QueryApplicationPhysicalPath()->QueryStr(),
|
||||
&struPath);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = UTILITY::EnsureDirectoryPathExist(struPath.QueryStr());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
GetSystemTime(&systemTime);
|
||||
hr = m_struLogFilePath.SafeSnwprintf(L"%s_%d%02d%02d%02d%02d%02d_%d.log",
|
||||
struPath.QueryStr(),
|
||||
systemTime.wYear,
|
||||
systemTime.wMonth,
|
||||
systemTime.wDay,
|
||||
systemTime.wHour,
|
||||
systemTime.wMinute,
|
||||
systemTime.wSecond,
|
||||
GetCurrentProcessId());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
m_hLogFileHandle = CreateFileW(m_struLogFilePath.QueryStr(),
|
||||
FILE_READ_DATA | FILE_WRITE_DATA,
|
||||
FILE_SHARE_READ,
|
||||
&saAttr,
|
||||
CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
|
||||
if (m_hLogFileHandle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (!SetStdHandle(STD_OUTPUT_HANDLE, m_hLogFileHandle))
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (!SetStdHandle(STD_ERROR_HANDLE, m_hLogFileHandle))
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
// not work
|
||||
// AllocConsole() does not help
|
||||
// *stdout = *m_pStdFile;
|
||||
// *stderr = *m_pStdFile;
|
||||
// _dup2(_fileno(m_pStdFile), _fileno(stdout));
|
||||
// _dup2(_fileno(m_pStdFile), _fileno(stderr));
|
||||
// this one cannot capture the process start failure
|
||||
// _wfreopen_s(&m_pStdFile, struLogFileName.QueryStr(), L"w", stdout);
|
||||
|
||||
// Periodically flush the log content to file
|
||||
m_Timer.InitializeTimer(STTIMER::TimerCallback, &m_struLogFilePath, 3000, 3000);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// CreatePipe for outputting stderr to the windows event log.
|
||||
// Ignore failures
|
||||
//
|
||||
if (!CreatePipe(&hStdErrReadPipe, &hStdErrWritePipe, &saAttr, 0 /*nSize*/))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (!SetStdHandle(STD_ERROR_HANDLE, hStdErrWritePipe))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
m_hErrReadPipe = hStdErrReadPipe;
|
||||
m_hErrWritePipe = hStdErrWritePipe;
|
||||
|
||||
// Read the stderr handle on a separate thread until we get 4096 bytes.
|
||||
m_hErrThread = CreateThread(
|
||||
NULL, // default security attributes
|
||||
0, // default stack size
|
||||
(LPTHREAD_START_ROUTINE)ReadStdErrHandle,
|
||||
this, // thread function arguments
|
||||
0, // default creation flags
|
||||
NULL); // receive thread identifier
|
||||
|
||||
if (m_hErrThread == NULL)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
goto Finished;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The process has console, e.g., IIS Express scenario
|
||||
|
||||
if (_wfopen_s(&m_pStdFile, m_struLogFilePath.QueryStr(), L"w") == 0)
|
||||
{
|
||||
// known issue: error info may not be capture when process crashes during buffering
|
||||
// even we disabled FILE buffering
|
||||
setvbuf(m_pStdFile, NULL, _IONBF, 0);
|
||||
_dup2(_fileno(m_pStdFile), _fileno(stdout));
|
||||
_dup2(_fileno(m_pStdFile), _fileno(stderr));
|
||||
}
|
||||
// These don't work for console scenario
|
||||
// close and AllocConsole does not help
|
||||
//_wfreopen_s(&m_pStdFile, struLogFileName.QueryStr(), L"w", stdout);
|
||||
// SetStdHandle(STD_ERROR_HANDLE, m_hLogFileHandle);
|
||||
// SetStdHandle(STD_OUTPUT_HANDLE, m_hLogFileHandle);
|
||||
//*stdout = *m_pStdFile;
|
||||
//*stderr = *m_pStdFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Finished:
|
||||
m_fDoneStdRedirect = TRUE;
|
||||
if (FAILED(hr) && m_pConfig->QueryStdoutLogEnabled())
|
||||
{
|
||||
UTILITY::LogEventF(g_hEventLog,
|
||||
EVENTLOG_WARNING_TYPE,
|
||||
ASPNETCORE_EVENT_CONFIG_ERROR,
|
||||
ASPNETCORE_EVENT_INVALID_STDOUT_LOG_FILE_MSG,
|
||||
m_struLogFilePath.QueryStr(),
|
||||
hr);
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
IN_PROCESS_APPLICATION::ReadStdErrHandle(
|
||||
LPVOID pContext
|
||||
)
|
||||
{
|
||||
IN_PROCESS_APPLICATION *pApplication = (IN_PROCESS_APPLICATION*)pContext;
|
||||
DBG_ASSERT(pApplication != NULL);
|
||||
pApplication->ReadStdErrHandleInternal();
|
||||
}
|
||||
|
||||
VOID
|
||||
IN_PROCESS_APPLICATION::ReadStdErrHandleInternal(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
DWORD dwNumBytesRead = 0;
|
||||
while (true)
|
||||
{
|
||||
if (ReadFile(m_hErrReadPipe, &m_pzFileContents[m_dwStdErrReadTotal], 4096 - m_dwStdErrReadTotal, &dwNumBytesRead, NULL))
|
||||
{
|
||||
m_dwStdErrReadTotal += dwNumBytesRead;
|
||||
if (m_dwStdErrReadTotal >= 4096)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (GetLastError() == ERROR_BROKEN_PIPE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
IN_PROCESS_APPLICATION::CloseStdErrHandles
|
||||
(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
DWORD dwThreadStatus = 0;
|
||||
DWORD dwTimeout = m_pConfig->QueryShutdownTimeLimitInMS();
|
||||
// Close Handles for stderr as we only care about capturing startup errors
|
||||
if (m_hErrWritePipe != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
CloseHandle(m_hErrWritePipe);
|
||||
m_hErrWritePipe = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
if (m_hErrThread != NULL &&
|
||||
GetExitCodeThread(m_hErrThread, &dwThreadStatus) != 0 &&
|
||||
dwThreadStatus == STILL_ACTIVE)
|
||||
{
|
||||
// wait for gracefullshut down, i.e., the exit of the background thread or timeout
|
||||
if (WaitForSingleObject(m_hErrThread, dwTimeout) != WAIT_OBJECT_0)
|
||||
{
|
||||
// if the thread is still running, we need kill it first before exit to avoid AV
|
||||
if (GetExitCodeThread(m_hErrThread, &dwThreadStatus) != 0 && dwThreadStatus == STILL_ACTIVE)
|
||||
{
|
||||
TerminateThread(m_hErrThread, STATUS_CONTROL_C_EXIT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(m_hErrThread);
|
||||
m_hErrThread = NULL;
|
||||
|
||||
if (m_hErrReadPipe != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
CloseHandle(m_hErrReadPipe);
|
||||
m_hErrReadPipe = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Will be called by the inprocesshandler
|
||||
HRESULT
|
||||
IN_PROCESS_APPLICATION::LoadManagedApplication
|
||||
|
|
@ -657,11 +372,27 @@ IN_PROCESS_APPLICATION::LoadManagedApplication
|
|||
goto Finished;
|
||||
}
|
||||
|
||||
// Set up stdout redirect
|
||||
SetStdOut();
|
||||
|
||||
{
|
||||
// Set up stdout redirect
|
||||
|
||||
SRWLockWrapper lock(m_srwLock);
|
||||
|
||||
if (m_pLoggerProvider == NULL)
|
||||
{
|
||||
hr = LoggingHelpers::CreateLoggingProvider(
|
||||
m_pConfig->QueryStdoutLogEnabled(),
|
||||
!GetConsoleWindow(),
|
||||
m_pConfig->QueryStdoutLogFile()->QueryStr(),
|
||||
m_pConfig->QueryApplicationPhysicalPath()->QueryStr(),
|
||||
&m_pLoggerProvider);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
m_pLoggerProvider->Start();
|
||||
}
|
||||
|
||||
if (m_status != APPLICATION_STATUS::STARTING)
|
||||
{
|
||||
if (m_status == APPLICATION_STATUS::FAIL)
|
||||
|
|
@ -887,6 +618,8 @@ Finished:
|
|||
|
||||
if (!m_fShutdownCalledFromNative)
|
||||
{
|
||||
m_pLoggerProvider->NotifyStartupComplete();
|
||||
|
||||
LogErrorsOnMainExit(hr);
|
||||
if (m_fInitialized)
|
||||
{
|
||||
|
|
@ -910,72 +643,20 @@ IN_PROCESS_APPLICATION::LogErrorsOnMainExit(
|
|||
// This will be a common place for errors as it means the hostfxr_main returned
|
||||
// or there was an exception.
|
||||
//
|
||||
CHAR pzFileContents[4096] = { 0 };
|
||||
DWORD dwNumBytesRead;
|
||||
STRU struStdErrLog;
|
||||
LARGE_INTEGER li = { 0 };
|
||||
BOOL fLogged = FALSE;
|
||||
DWORD dwFilePointer = 0;
|
||||
|
||||
if (m_pConfig->QueryStdoutLogEnabled())
|
||||
STRA struStdErrOutput;
|
||||
if (m_pLoggerProvider->GetStdOutContent(&struStdErrOutput))
|
||||
{
|
||||
// Put stdout/stderr logs into
|
||||
if (m_hLogFileHandle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (GetFileSizeEx(m_hLogFileHandle, &li) && li.LowPart > 0 && li.HighPart == 0)
|
||||
{
|
||||
if (li.LowPart > 4096)
|
||||
{
|
||||
dwFilePointer = SetFilePointer(m_hLogFileHandle, -4096, NULL, FILE_END);
|
||||
}
|
||||
else
|
||||
{
|
||||
dwFilePointer = SetFilePointer(m_hLogFileHandle, 0, NULL, FILE_BEGIN);
|
||||
}
|
||||
if (dwFilePointer != INVALID_SET_FILE_POINTER)
|
||||
{
|
||||
if (ReadFile(m_hLogFileHandle, pzFileContents, 4096, &dwNumBytesRead, NULL))
|
||||
{
|
||||
if (SUCCEEDED(struStdErrLog.CopyA(m_pzFileContents, m_dwStdErrReadTotal)))
|
||||
{
|
||||
UTILITY::LogEventF(g_hEventLog,
|
||||
EVENTLOG_ERROR_TYPE,
|
||||
ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT,
|
||||
ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT_STDOUT_MSG,
|
||||
m_pConfig->QueryApplicationPath()->QueryStr(),
|
||||
m_pConfig->QueryApplicationPhysicalPath()->QueryStr(),
|
||||
hr,
|
||||
struStdErrLog.QueryStr());
|
||||
fLogged = TRUE;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
UTILITY::LogEventF(g_hEventLog,
|
||||
EVENTLOG_ERROR_TYPE,
|
||||
ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT,
|
||||
ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT_STDOUT_MSG,
|
||||
m_pConfig->QueryApplicationPath()->QueryStr(),
|
||||
m_pConfig->QueryApplicationPhysicalPath()->QueryStr(),
|
||||
hr,
|
||||
struStdErrOutput.QueryStr());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_dwStdErrReadTotal > 0)
|
||||
{
|
||||
if (SUCCEEDED(struStdErrLog.CopyA(m_pzFileContents, m_dwStdErrReadTotal)))
|
||||
{
|
||||
UTILITY::LogEventF(g_hEventLog,
|
||||
EVENTLOG_ERROR_TYPE,
|
||||
ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT,
|
||||
ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT_STDERR_MSG,
|
||||
m_pConfig->QueryApplicationPath()->QueryStr(),
|
||||
m_pConfig->QueryApplicationPhysicalPath()->QueryStr(),
|
||||
hr,
|
||||
struStdErrLog.QueryStr());
|
||||
fLogged = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!fLogged)
|
||||
{
|
||||
// If we didn't log, log the generic message.
|
||||
UTILITY::LogEventF(g_hEventLog,
|
||||
EVENTLOG_ERROR_TYPE,
|
||||
ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT,
|
||||
|
|
@ -983,41 +664,34 @@ IN_PROCESS_APPLICATION::LogErrorsOnMainExit(
|
|||
m_pConfig->QueryApplicationPath()->QueryStr(),
|
||||
m_pConfig->QueryApplicationPhysicalPath()->QueryStr(),
|
||||
hr);
|
||||
fLogged = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Calls hostfxr_main with the hostfxr and application as arguments.
|
||||
// Method should be called with only
|
||||
// Need to have __try / __except in methods that require unwinding.
|
||||
// Note, this will not
|
||||
//
|
||||
HRESULT
|
||||
IN_PROCESS_APPLICATION::RunDotnetApplication(DWORD argc, CONST PCWSTR* argv, hostfxr_main_fn pProc)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
__try
|
||||
{
|
||||
m_ProcessExitCode = pProc(argc, argv);
|
||||
if (m_ProcessExitCode != 0)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
}
|
||||
__except (FilterException(GetExceptionCode(), GetExceptionInformation()))
|
||||
__except(GetExceptionCode() != 0)
|
||||
{
|
||||
// TODO Log error message here.
|
||||
hr = E_APPLICATION_ACTIVATION_EXEC_FAILURE;
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
// static
|
||||
INT
|
||||
IN_PROCESS_APPLICATION::FilterException(unsigned int, struct _EXCEPTION_POINTERS*)
|
||||
{
|
||||
// We assume that any exception is a failure as the applicaiton didn't start or there was a startup error.
|
||||
// TODO, log error based on exception code.
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
|
||||
REQUESTHANDLER_CONFIG*
|
||||
IN_PROCESS_APPLICATION::QueryConfig() const
|
||||
|
|
|
|||
|
|
@ -55,16 +55,6 @@ public:
|
|||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
ReadStdErrHandleInternal(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
CloseStdErrHandles(
|
||||
VOID
|
||||
);
|
||||
|
||||
HRESULT
|
||||
LoadManagedApplication(
|
||||
VOID
|
||||
|
|
@ -130,17 +120,6 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
static
|
||||
DWORD
|
||||
DoShutDown(
|
||||
LPVOID lpParam
|
||||
);
|
||||
|
||||
VOID
|
||||
ShutDownInternal(
|
||||
VOID
|
||||
);
|
||||
|
||||
IHttpServer* const m_pHttpServer;
|
||||
|
||||
// Thread executing the .NET Core process
|
||||
|
|
@ -159,26 +138,18 @@ private:
|
|||
// The event that gets triggered when managed initialization is complete
|
||||
HANDLE m_pInitalizeEvent;
|
||||
|
||||
// The std log file handle
|
||||
HANDLE m_hLogFileHandle;
|
||||
HANDLE m_hErrReadPipe;
|
||||
HANDLE m_hErrWritePipe;
|
||||
STRU m_struLogFilePath;
|
||||
STRU m_struExeLocation;
|
||||
|
||||
// The exit code of the .NET Core process
|
||||
INT m_ProcessExitCode;
|
||||
|
||||
BOOL m_fIsWebSocketsConnection;
|
||||
BOOL m_fDoneStdRedirect;
|
||||
volatile BOOL m_fBlockCallbacksIntoManaged;
|
||||
volatile BOOL m_fShutdownCalledFromNative;
|
||||
volatile BOOL m_fShutdownCalledFromManaged;
|
||||
BOOL m_fRecycleCalled;
|
||||
BOOL m_fInitialized;
|
||||
|
||||
FILE* m_pStdFile;
|
||||
STTIMER m_Timer;
|
||||
SRWLOCK m_srwLock;
|
||||
|
||||
// Thread for capturing startup stderr logs when logging is disabled
|
||||
|
|
@ -188,6 +159,7 @@ private:
|
|||
PCWSTR m_pstrDotnetExeLocation;
|
||||
static IN_PROCESS_APPLICATION* s_Application;
|
||||
|
||||
IOutputManager* m_pLoggerProvider;
|
||||
REQUESTHANDLER_CONFIG* m_pConfig;
|
||||
|
||||
// Allows to override call to hostfxr_main with custome callback
|
||||
|
|
@ -205,26 +177,26 @@ private:
|
|||
_In_ LPVOID pContext
|
||||
);
|
||||
|
||||
static
|
||||
VOID
|
||||
ReadStdErrHandle
|
||||
(
|
||||
_In_ LPVOID pContext
|
||||
);
|
||||
|
||||
HRESULT
|
||||
SetEnvironementVariablesOnWorkerProcess(
|
||||
VOID
|
||||
);
|
||||
|
||||
static
|
||||
INT
|
||||
FilterException(unsigned int code, struct _EXCEPTION_POINTERS *ep);
|
||||
|
||||
HRESULT
|
||||
RunDotnetApplication(
|
||||
DWORD argc,
|
||||
CONST PCWSTR* argv,
|
||||
hostfxr_main_fn pProc
|
||||
);
|
||||
|
||||
static
|
||||
DWORD
|
||||
DoShutDown(
|
||||
LPVOID lpParam
|
||||
);
|
||||
|
||||
VOID
|
||||
ShutDownInternal(
|
||||
VOID
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -217,7 +217,6 @@
|
|||
<ClInclude Include="aspnetcore_event.h" />
|
||||
<ClInclude Include="disconnectcontext.h" />
|
||||
<ClInclude Include="environmentvariablehelpers.h" />
|
||||
<ClInclude Include="sttimer.h" />
|
||||
<ClInclude Include="outofprocess\forwarderconnection.h" />
|
||||
<ClInclude Include="outofprocess\processmanager.h" />
|
||||
<ClInclude Include="outofprocess\protocolconfig.h" />
|
||||
|
|
|
|||
|
|
@ -32,12 +32,28 @@
|
|||
<ImportGroup Label="Shared" />
|
||||
<ImportGroup Label="PropertySheets" />
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(MSBuildProjectDirectory)\bin\$(Configuration)\$(Platform)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(MSBuildProjectDirectory)\bin\$(Configuration)\$(Platform)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutDir>$(MSBuildProjectDirectory)\bin\$(Configuration)\$(Platform)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<OutDir>$(MSBuildProjectDirectory)\bin\$(Configuration)\$(Platform)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Helpers.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="FileOutputManagerTests.cpp" />
|
||||
<ClCompile Include="Helpers.cpp" />
|
||||
<ClCompile Include="hostfxr_utility_tests.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="PipeOutputManagerTests.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
|
|
@ -141,7 +157,7 @@
|
|||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)include;%(AdditionalIncludeDirectories);..\..\src\AspNetCoreModuleV2\IISLib;..\..\src\AspNetCoreModuleV2\CommonLib;..\gtest-1.8.0\include;..\..\src\AspNetCoreModuleV2\AspNetCore\Inc;</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/D "_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING" </AdditionalOptions>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<LanguageStandard>stdcpp14</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,142 @@
|
|||
// 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"
|
||||
|
||||
class FileManagerWrapper
|
||||
{
|
||||
public:
|
||||
FileOutputManager* manager;
|
||||
FileManagerWrapper(FileOutputManager* m)
|
||||
: manager(m)
|
||||
{
|
||||
manager->Start();
|
||||
}
|
||||
|
||||
~FileManagerWrapper()
|
||||
{
|
||||
delete manager;
|
||||
}
|
||||
};
|
||||
|
||||
namespace FileOutManagerStartupTests
|
||||
{
|
||||
using ::testing::Test;
|
||||
class FileOutputManagerTest : public Test
|
||||
{
|
||||
protected:
|
||||
void
|
||||
Test(std::wstring fileNamePrefix, FILE* out)
|
||||
{
|
||||
PCWSTR expected = L"test";
|
||||
|
||||
std::wstring tempDirectory = Helpers::CreateRandomTempDirectory();
|
||||
FileOutputManager* pManager = new FileOutputManager;
|
||||
pManager->Initialize(fileNamePrefix.c_str(), tempDirectory.c_str());
|
||||
{
|
||||
FileManagerWrapper wrapper(pManager);
|
||||
|
||||
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))
|
||||
{
|
||||
std::wstring filename(p.path().filename());
|
||||
ASSERT_EQ(filename.substr(0, fileNamePrefix.size()), fileNamePrefix);
|
||||
|
||||
std::wstring content = Helpers::ReadFileContent(std::wstring(p.path()));
|
||||
ASSERT_EQ(content.length(), DWORD(4));
|
||||
ASSERT_STREQ(content.c_str(), expected);
|
||||
}
|
||||
|
||||
Helpers::DeleteDirectory(tempDirectory);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(FileOutputManagerTest, WriteToFileCheckContentsWritten)
|
||||
{
|
||||
Test(L"", stdout);
|
||||
Test(L"log", stdout);
|
||||
}
|
||||
|
||||
TEST_F(FileOutputManagerTest, WriteToFileCheckContentsWrittenErr)
|
||||
{
|
||||
Test(L"", stderr);
|
||||
Test(L"log", stderr);
|
||||
}
|
||||
}
|
||||
|
||||
namespace FileOutManagerOutputTests
|
||||
{
|
||||
|
||||
TEST(FileOutManagerOutputTest, StdErr)
|
||||
{
|
||||
PCSTR expected = "test";
|
||||
|
||||
std::wstring tempDirectory = Helpers::CreateRandomTempDirectory();
|
||||
|
||||
FileOutputManager* pManager = new FileOutputManager;
|
||||
pManager->Initialize(L"", tempDirectory.c_str());
|
||||
{
|
||||
FileManagerWrapper wrapper(pManager);
|
||||
|
||||
printf(expected, stderr);
|
||||
STRA straContent;
|
||||
ASSERT_TRUE(pManager->GetStdOutContent(&straContent));
|
||||
|
||||
ASSERT_STREQ(straContent.QueryStr(), expected);
|
||||
}
|
||||
|
||||
Helpers::DeleteDirectory(tempDirectory);
|
||||
}
|
||||
|
||||
TEST(FileOutManagerOutputTest, CheckFileOutput)
|
||||
{
|
||||
PCSTR expected = "test";
|
||||
|
||||
std::wstring tempDirectory = Helpers::CreateRandomTempDirectory();
|
||||
|
||||
FileOutputManager* pManager = new FileOutputManager;
|
||||
pManager->Initialize(L"", tempDirectory.c_str());
|
||||
{
|
||||
FileManagerWrapper wrapper(pManager);
|
||||
|
||||
printf(expected);
|
||||
STRA straContent;
|
||||
ASSERT_TRUE(pManager->GetStdOutContent(&straContent));
|
||||
|
||||
ASSERT_STREQ(straContent.QueryStr(), expected);
|
||||
}
|
||||
|
||||
Helpers::DeleteDirectory(tempDirectory);
|
||||
}
|
||||
|
||||
TEST(FileOutManagerOutputTest, CapAt4KB)
|
||||
{
|
||||
PCSTR expected = "test";
|
||||
|
||||
std::wstring tempDirectory = Helpers::CreateRandomTempDirectory();
|
||||
|
||||
FileOutputManager* pManager = new FileOutputManager;
|
||||
pManager->Initialize(L"", tempDirectory.c_str());
|
||||
{
|
||||
FileManagerWrapper wrapper(pManager);
|
||||
|
||||
for (int i = 0; i < 1200; i++)
|
||||
{
|
||||
printf(expected);
|
||||
}
|
||||
|
||||
STRA straContent;
|
||||
ASSERT_TRUE(pManager->GetStdOutContent(&straContent));
|
||||
|
||||
ASSERT_EQ(straContent.QueryCCH(), 4096);
|
||||
}
|
||||
|
||||
Helpers::DeleteDirectory(tempDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
std::wstring
|
||||
Helpers::CreateRandomValue()
|
||||
{
|
||||
int randomValue = rand();
|
||||
return std::to_wstring(randomValue);
|
||||
}
|
||||
|
||||
std::wstring
|
||||
Helpers::CreateRandomTempDirectory()
|
||||
{
|
||||
PWSTR tempPath = new WCHAR[256];
|
||||
GetTempPath(256, tempPath);
|
||||
std::wstring wstringPath(tempPath);
|
||||
|
||||
return wstringPath.append(Helpers::CreateRandomValue()).append(L"\\");
|
||||
}
|
||||
|
||||
void
|
||||
Helpers::DeleteDirectory(std::wstring directory)
|
||||
{
|
||||
std::experimental::filesystem::remove_all(directory);
|
||||
}
|
||||
|
||||
std::wstring
|
||||
Helpers::ReadFileContent(std::wstring file)
|
||||
{
|
||||
std::wcout << file << std::endl;
|
||||
|
||||
std::fstream t(file);
|
||||
std::stringstream buffer;
|
||||
buffer << t.rdbuf();
|
||||
|
||||
int nChars = MultiByteToWideChar(CP_ACP, 0, buffer.str().c_str(), -1, NULL, 0);
|
||||
|
||||
LPWSTR pwzName = new WCHAR[nChars];
|
||||
MultiByteToWideChar(CP_UTF8, 0, buffer.str().c_str(), -1, pwzName, nChars);
|
||||
|
||||
std::wstring retVal(pwzName);
|
||||
|
||||
delete pwzName;
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
class Helpers
|
||||
{
|
||||
public:
|
||||
|
||||
static
|
||||
std::wstring
|
||||
CreateRandomValue();
|
||||
|
||||
static
|
||||
std::wstring
|
||||
CreateRandomTempDirectory();
|
||||
|
||||
static
|
||||
void
|
||||
DeleteDirectory(std::wstring directory);
|
||||
|
||||
static
|
||||
std::wstring
|
||||
ReadFileContent(std::wstring file);
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
// 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"
|
||||
|
||||
class FileManagerWrapper
|
||||
{
|
||||
public:
|
||||
PipeOutputManager * manager;
|
||||
FileManagerWrapper(PipeOutputManager* m)
|
||||
: manager(m)
|
||||
{
|
||||
manager->Start();
|
||||
}
|
||||
|
||||
~FileManagerWrapper()
|
||||
{
|
||||
delete manager;
|
||||
}
|
||||
};
|
||||
|
||||
namespace PipeOutputManagerTests
|
||||
{
|
||||
TEST(PipeManagerOutputTest, NotifyStartupCompleteCallsDispose)
|
||||
{
|
||||
PCWSTR expected = L"test";
|
||||
|
||||
PipeOutputManager* pManager = new PipeOutputManager();
|
||||
ASSERT_EQ(S_OK, pManager->Start());
|
||||
|
||||
pManager->NotifyStartupComplete();
|
||||
|
||||
// Test will fail if we didn't redirect stdout back to a file descriptor.
|
||||
// This is because gtest relies on console output to know if a test succeeded or failed.
|
||||
// If the output still points to a file/pipe, the test (and all other tests after it) will fail.
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -9,6 +9,7 @@ int wmain(int argc, wchar_t* argv[])
|
|||
int main(int argc, char* argv[])
|
||||
#endif
|
||||
{
|
||||
std::srand((unsigned int)std::time(0));
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
RUN_ALL_TESTS();
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
#include <wchar.h>
|
||||
#include <io.h>
|
||||
#include <stdio.h>
|
||||
#include <experimental/filesystem>
|
||||
#include <fstream>
|
||||
|
||||
#include <hashfn.h>
|
||||
#include <hashtable.h>
|
||||
|
|
@ -48,6 +50,7 @@
|
|||
#include "requesthandler.h"
|
||||
#include "resources.h"
|
||||
#include "aspnetcore_msg.h"
|
||||
#include "Helpers.h"
|
||||
|
||||
#undef assert // Macro redefinition in IISLib.
|
||||
#include "gtest\gtest.h"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
// 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.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using IISIntegration.FunctionalTests.Utilities;
|
||||
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
|
||||
{
|
||||
public class LoggingTests : IISFunctionalTestBase
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("CheckErrLogFile")]
|
||||
[InlineData("CheckLogFile")]
|
||||
public async Task CheckStdoutLogging(string path)
|
||||
{
|
||||
var deploymentParameters = Helpers.GetBaseDeploymentParameters();
|
||||
deploymentParameters.PublishApplicationBeforeDeployment = true;
|
||||
deploymentParameters.PreservePublishedApplicationForDebugging = true; // workaround for keeping
|
||||
|
||||
var deploymentResult = await DeployAsync(deploymentParameters);
|
||||
|
||||
Helpers.ModifyAspNetCoreSectionInWebConfig(deploymentResult, "stdoutLogEnabled", "true");
|
||||
Helpers.ModifyAspNetCoreSectionInWebConfig(deploymentResult, "stdoutLogFile", @".\logs\stdout");
|
||||
|
||||
var response = await deploymentResult.RetryingHttpClient.GetAsync(path);
|
||||
|
||||
var responseText = await response.Content.ReadAsStringAsync();
|
||||
|
||||
Assert.Equal("Hello World", responseText);
|
||||
|
||||
Dispose();
|
||||
|
||||
var folderPath = Path.Combine(deploymentResult.DeploymentResult.ContentRoot, @"logs");
|
||||
|
||||
var fileInDirectory = Directory.GetFiles(folderPath).Single();
|
||||
Assert.NotNull(fileInDirectory);
|
||||
|
||||
string contents = null;
|
||||
for (var i = 0; i < 20; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
contents = await File.ReadAllTextAsync(fileInDirectory);
|
||||
break;
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
// File in use by IISExpress, delay a bit before rereading.
|
||||
}
|
||||
await Task.Delay(20);
|
||||
}
|
||||
|
||||
Assert.NotNull(contents);
|
||||
|
||||
// Open the log file and see if there are any contents.
|
||||
Assert.Contains("TEST MESSAGE", contents);
|
||||
|
||||
RetryHelper.RetryOperation(
|
||||
() => Directory.Delete(deploymentParameters.PublishedApplicationRootPath, true),
|
||||
e => Logger.LogWarning($"Failed to delete directory : {e.Message}"),
|
||||
retryCount: 3,
|
||||
retryDelayMilliseconds: 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
// 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.Threading.Tasks;
|
||||
using IISIntegration.FunctionalTests.Utilities;
|
||||
using Xunit;
|
||||
using System.Net;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
|
||||
{
|
||||
public class StartupExceptionTests : IISFunctionalTestBase
|
||||
{
|
||||
|
||||
[Theory]
|
||||
[InlineData("CheckLogFile")]
|
||||
[InlineData("CheckErrLogFile")]
|
||||
public async Task CheckStdoutWithRandomNumber(string path)
|
||||
{
|
||||
var deploymentParameters = Helpers.GetBaseDeploymentParameters("StartupExceptionWebsite");
|
||||
deploymentParameters.EnvironmentVariables["ASPNETCORE_INPROCESS_STARTUP_VALUE"] = path;
|
||||
var randomNumberString = new Random(Guid.NewGuid().GetHashCode()).Next(10000000).ToString();
|
||||
deploymentParameters.EnvironmentVariables["ASPNETCORE_INPROCESS_RANDOM_VALUE"] = randomNumberString;
|
||||
|
||||
var deploymentResult = await DeployAsync(deploymentParameters);
|
||||
|
||||
var response = await deploymentResult.RetryingHttpClient.GetAsync(path);
|
||||
|
||||
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
|
||||
|
||||
Assert.Contains(TestSink.Writes, context => context.Message.Contains($"Random number: {randomNumberString}"));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("CheckLargeStdErrWrites")]
|
||||
[InlineData("CheckLargeStdOutWrites")]
|
||||
[InlineData("CheckOversizedStdErrWrites")]
|
||||
[InlineData("CheckOversizedStdOutWrites")]
|
||||
public async Task CheckStdoutWithLargeWrites(string path)
|
||||
{
|
||||
var deploymentParameters = Helpers.GetBaseDeploymentParameters("StartupExceptionWebsite");
|
||||
deploymentParameters.EnvironmentVariables["ASPNETCORE_INPROCESS_STARTUP_VALUE"] = path;
|
||||
var deploymentResult = await DeployAsync(deploymentParameters);
|
||||
|
||||
var response = await deploymentResult.RetryingHttpClient.GetAsync(path);
|
||||
|
||||
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
|
||||
|
||||
Assert.Contains(TestSink.Writes, context => context.Message.Contains(new string('a', 4096)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -33,7 +33,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
|
|||
|
||||
var deploymentResult = await DeployAsync(deploymentParameters);
|
||||
|
||||
ModifyAspNetCoreSectionInWebConfig(deploymentResult, "processPath", "%DotnetPath%");
|
||||
Helpers.ModifyAspNetCoreSectionInWebConfig(deploymentResult, "processPath", "%DotnetPath%");
|
||||
|
||||
var response = await deploymentResult.RetryingHttpClient.GetAsync("HelloWorld");
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
|
|||
|
||||
var deploymentResult = await DeployAsync(deploymentParameters);
|
||||
|
||||
ModifyAspNetCoreSectionInWebConfig(deploymentResult, "processPath", "%DotnetPath%");
|
||||
Helpers.ModifyAspNetCoreSectionInWebConfig(deploymentResult, "processPath", "%DotnetPath%");
|
||||
|
||||
// Request to base address and check if various parts of the body are rendered & measure the cold startup time.
|
||||
var response = await deploymentResult.RetryingHttpClient.GetAsync("HelloWorld");
|
||||
|
|
@ -60,7 +60,6 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
|
|||
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
|
||||
}
|
||||
|
||||
|
||||
public static TestMatrix TestVariants
|
||||
=> TestMatrix.ForServers(ServerType.IISExpress)
|
||||
.WithTfms(Tfm.NetCoreApp22)
|
||||
|
|
@ -94,7 +93,8 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
|
|||
Assert.Contains(TestSink.Writes, context => context.Message.Contains("Application is running inside IIS process but is not configured to use IIS server"));
|
||||
}
|
||||
|
||||
private DeploymentParameters GetBaseDeploymentParameters(string site = "InProcessWebSite")
|
||||
// Defaults to inprocess specific deployment parameters
|
||||
public static DeploymentParameters GetBaseDeploymentParameters(string site = "InProcessWebSite")
|
||||
{
|
||||
return new DeploymentParameters(Helpers.GetTestWebSitePath(site), ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64)
|
||||
{
|
||||
|
|
@ -105,16 +105,5 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
|
|||
PublishApplicationBeforeDeployment = site == "InProcessWebSite",
|
||||
};
|
||||
}
|
||||
|
||||
private static void ModifyAspNetCoreSectionInWebConfig(IISDeploymentResult deploymentResult, string key, string value)
|
||||
{
|
||||
// modify the web.config after publish
|
||||
var root = deploymentResult.DeploymentResult.ContentRoot;
|
||||
var webConfigFile = $"{root}/web.config";
|
||||
var config = XDocument.Load(webConfigFile);
|
||||
var element = config.Descendants("aspNetCore").FirstOrDefault();
|
||||
element.SetAttributeValue(key, value);
|
||||
config.Save(webConfigFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
|
||||
|
|
@ -16,5 +19,32 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
|
|||
public static string GetInProcessTestSitesPath() => GetTestWebSitePath("InProcessWebSite");
|
||||
|
||||
public static string GetOutOfProcessTestSitesPath() => GetTestWebSitePath("OutOfProcessWebSite");
|
||||
|
||||
public static void ModifyAspNetCoreSectionInWebConfig(IISDeploymentResult deploymentResult, string key, string value)
|
||||
=> ModifySectionInWebConfig(deploymentResult, key, value, section: "aspNetCore", 0);
|
||||
|
||||
public static void ModifySectionInWebConfig(IISDeploymentResult deploymentResult, string key, string value, string section, int index)
|
||||
{
|
||||
// modify the web.config after publish
|
||||
var root = deploymentResult.DeploymentResult.ContentRoot;
|
||||
var webConfigFile = $"{root}/web.config";
|
||||
var config = XDocument.Load(webConfigFile);
|
||||
var element = config.Descendants(section).ToList()[index];
|
||||
element.SetAttributeValue(key, value);
|
||||
config.Save(webConfigFile);
|
||||
}
|
||||
|
||||
// Defaults to inprocess specific deployment parameters
|
||||
public static DeploymentParameters GetBaseDeploymentParameters(string site = "InProcessWebSite")
|
||||
{
|
||||
return new DeploymentParameters(Helpers.GetTestWebSitePath(site), ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64)
|
||||
{
|
||||
TargetFramework = Tfm.NetCoreApp22,
|
||||
ApplicationType = ApplicationType.Portable,
|
||||
AncmVersion = AncmVersion.AspNetCoreModuleV2,
|
||||
HostingModel = HostingModel.InProcess,
|
||||
PublishApplicationBeforeDeployment = site == "InProcessWebSite",
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -657,7 +657,6 @@ namespace IISTestSite
|
|||
{
|
||||
app.Run(async context =>
|
||||
{
|
||||
|
||||
if (context.Request.Path.StartsWithSegments("/NullBuffer"))
|
||||
{
|
||||
await context.Response.Body.WriteAsync(null, 0, 0);
|
||||
|
|
@ -704,5 +703,27 @@ namespace IISTestSite
|
|||
{
|
||||
app.Run(async ctx => { await ctx.Response.WriteAsync(AppDomain.CurrentDomain.BaseDirectory); });
|
||||
}
|
||||
|
||||
private void CheckLogFile(IApplicationBuilder app)
|
||||
{
|
||||
app.Run(async ctx =>
|
||||
{
|
||||
Console.WriteLine("TEST MESSAGE");
|
||||
|
||||
await ctx.Response.WriteAsync("Hello World");
|
||||
});
|
||||
}
|
||||
|
||||
private void CheckErrLogFile(IApplicationBuilder app)
|
||||
{
|
||||
app.Run(async ctx =>
|
||||
{
|
||||
Console.Error.WriteLine("TEST MESSAGE");
|
||||
Console.Error.Flush();
|
||||
|
||||
await ctx.Response.WriteAsync("Hello World");
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<system.webServer>
|
||||
<handlers>
|
||||
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
|
||||
</handlers>
|
||||
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false" hostingModel="inprocess">
|
||||
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="true" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false" hostingModel="inprocess">
|
||||
<environmentVariables>
|
||||
<environmentVariable name="ASPNETCORE_INPROCESS_TESTING_VALUE" value="foobar" />
|
||||
<environmentVariable name="ASPNETCORE_INPROCESS_TESTING_LONG_VALUE" value="AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNativeAReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNativeAReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNativeAReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNativeAReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNativeAReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative" />
|
||||
<environmentVariable name="ProgramFiles" value="foobarbaz" />
|
||||
<environmentVariable name="ASPNETCORE_IIS_HTTPAUTH" value="shouldberemoved"/>
|
||||
<environmentVariable name="ASPNETCORE_IIS_HTTPAUTH" value="shouldberemoved" />
|
||||
</environmentVariables>
|
||||
</aspNetCore>
|
||||
</system.webServer>
|
||||
</configuration>
|
||||
</configuration>
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
// 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;
|
||||
|
||||
namespace IISTestSite
|
||||
{
|
||||
public static class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var envVariable = Environment.GetEnvironmentVariable("ASPNETCORE_INPROCESS_STARTUP_VALUE");
|
||||
var randomNumber = Environment.GetEnvironmentVariable("ASPNETCORE_INPROCESS_RANDOM_VALUE");
|
||||
|
||||
// Semicolons are appended to env variables; removing them.
|
||||
if (envVariable == "CheckLargeStdOutWrites")
|
||||
{
|
||||
Console.WriteLine(new string('a', 4096));
|
||||
}
|
||||
else if (envVariable == "CheckLargeStdErrWrites")
|
||||
{
|
||||
Console.Error.WriteLine(new string('a', 4096));
|
||||
Console.Error.Flush();
|
||||
}
|
||||
else if (envVariable == "CheckLogFile")
|
||||
{
|
||||
Console.WriteLine($"Random number: {randomNumber}");
|
||||
}
|
||||
else if (envVariable == "CheckErrLogFile")
|
||||
{
|
||||
Console.Error.WriteLine($"Random number: {randomNumber}");
|
||||
Console.Error.Flush();
|
||||
}
|
||||
else if (envVariable == "CheckOversizedStdErrWrites")
|
||||
{
|
||||
Console.WriteLine(new string('a', 5000));
|
||||
|
||||
}
|
||||
else if (envVariable == "CheckOversizedStdOutWrites")
|
||||
{
|
||||
Console.Error.WriteLine(new string('a', 4096));
|
||||
Console.Error.Flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": true,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:5762/",
|
||||
"sslPort": 0
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"ANCM IIS Express": {
|
||||
"commandName": "Executable",
|
||||
"executablePath": "$(IISExpressPath)",
|
||||
"commandLineArgs": "$(IISExpressArguments)",
|
||||
"nativeDebugging": true,
|
||||
"environmentVariables": {
|
||||
"IIS_SITE_PATH": "$(MSBuildThisFileDirectory)",
|
||||
"ANCM_PATH": "$(TargetDir)$(AncmV2Path)",
|
||||
"LAUNCHER_ARGS": "$(TargetPath)",
|
||||
"ASPNETCORE_ENVIRONMENT": "Development",
|
||||
"LAUNCHER_PATH": "$(DotNetPath)"
|
||||
}
|
||||
},
|
||||
"ANCM IIS": {
|
||||
"commandName": "Executable",
|
||||
"executablePath": "$(IISPath)",
|
||||
"commandLineArgs": "$(IISArguments)",
|
||||
"environmentVariables": {
|
||||
"IIS_SITE_PATH": "$(MSBuildThisFileDirectory)",
|
||||
"ANCM_PATH": "$(TargetDir)$(AncmV2Path)",
|
||||
"LAUNCHER_ARGS": "$(TargetPath)",
|
||||
"ASPNETCORE_ENVIRONMENT": "Development",
|
||||
"LAUNCHER_PATH": "$(DotNetPath)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<Import Project="..\..\..\build\testsite.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netcoreapp2.2</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\src\Microsoft.AspNetCore.Server.IIS\Microsoft.AspNetCore.Server.IIS.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="$(MicrosoftAspNetCoreHostingPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Loading…
Reference in New Issue