Apphost shim (#8893)
* Publish app host to folder under SDK * Use carried apphost as shim * Remove full framework launcher * Fix test run command issue * Use latest release/2.1 build * Test with 32 bit env * Add missing return * Update to latest prodcon build * Add xlfs
This commit is contained in:
parent
113f008c04
commit
e70f07178a
28 changed files with 532 additions and 284 deletions
|
@ -22,12 +22,15 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestPackages", "TestPackage
|
|||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{89905EC4-BC0F-443B-8ADF-691321F10108}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
build\AppHostTemplate.proj = build\AppHostTemplate.proj
|
||||
build\AzureInfo.props = build\AzureInfo.props
|
||||
build\BackwardsCompatibilityRuntimes.props = build\BackwardsCompatibilityRuntimes.props
|
||||
build\BranchInfo.props = build\BranchInfo.props
|
||||
build\Branding.props = build\Branding.props
|
||||
build\BuildDefaults.props = build\BuildDefaults.props
|
||||
build\BuildInfo.targets = build\BuildInfo.targets
|
||||
build\BundledDotnetTools.proj = build\BundledDotnetTools.proj
|
||||
build\BundledDotnetTools.props = build\BundledDotnetTools.props
|
||||
build\BundledRuntimes.props = build\BundledRuntimes.props
|
||||
build\BundledSdks.props = build\BundledSdks.props
|
||||
build\BundledTemplates.proj = build\BundledTemplates.proj
|
||||
|
|
49
build/AppHostTemplate.proj
Normal file
49
build/AppHostTemplate.proj
Normal file
|
@ -0,0 +1,49 @@
|
|||
<Project ToolsVersion="15.0" DefaultTargets="ExtractAppHostToOutput">
|
||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
|
||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.tasks))\dir.tasks" />
|
||||
|
||||
<PropertyGroup>
|
||||
<NativeExecutableExtension Condition=" $(Rid.StartsWith('win'))">.exe</NativeExecutableExtension>
|
||||
<AppHostExecutableName>AppHost$(NativeExecutableExtension)</AppHostExecutableName>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="ExtractAppHostToOutput"
|
||||
Condition="!Exists('$(AppHostTemplatePath)/$(AppHostExecutableName)')"
|
||||
DependsOnTargets="EnsureAppHostPackageRestored">
|
||||
|
||||
<Message Text="Restore $(TemplateFillInPackageName) from $(AppHostTemplatePath) to $(AppHostTemplateRestoreAdditionalParameters)."
|
||||
Importance="High" />
|
||||
|
||||
<ItemGroup>
|
||||
<AllFileOfRestoredAppHostPackage Include="$(AppHostIntermediateDirectory)\**\*.*" />
|
||||
<NativeRestoredAppHostNETCore
|
||||
Include="@(AllFileOfRestoredAppHostPackage)"
|
||||
Condition="'%(FileName)%(Extension)' == '$(AppHostExecutableName)'"/>
|
||||
</ItemGroup>
|
||||
|
||||
<Error Condition="@(NativeRestoredAppHostNETCore->Distinct()->Count()) != 1"
|
||||
Text="Failed to determine the $(_NETCoreDotNetAppHostPackageName) executable in $(AllFileOfRestoredAppHostPackage)" />
|
||||
|
||||
<Copy
|
||||
SourceFiles="@(NativeRestoredAppHostNETCore)"
|
||||
DestinationFolder="$(AppHostTemplatePath)" />
|
||||
|
||||
<Message Text="Copy from @(NativeRestoredAppHostNETCore) to $(AppHostTemplatePath)."
|
||||
Importance="High" />
|
||||
|
||||
</Target>
|
||||
|
||||
<Target Name="EnsureAppHostPackageRestored">
|
||||
<PropertyGroup>
|
||||
<AppHostTemplateRestoreAdditionalParameters>--runtime $(Rid)</AppHostTemplateRestoreAdditionalParameters>
|
||||
<AppHostTemplateRestoreAdditionalParameters>$(AppHostTemplateRestoreAdditionalParameters) /p:TargetFramework=$(CliTargetFramework)</AppHostTemplateRestoreAdditionalParameters>
|
||||
<AppHostTemplateRestoreAdditionalParameters>$(AppHostTemplateRestoreAdditionalParameters) /p:TemplateFillInPackageName=$(TemplateFillInPackageName)</AppHostTemplateRestoreAdditionalParameters>
|
||||
<AppHostTemplateRestoreAdditionalParameters>$(AppHostTemplateRestoreAdditionalParameters) /p:TemplateFillInPackageVersion=$(TemplateFillInPackageVersion)</AppHostTemplateRestoreAdditionalParameters>
|
||||
<AppHostTemplateRestoreAdditionalParameters>$(AppHostTemplateRestoreAdditionalParameters) /p:RestorePackagesPath=$(AppHostIntermediateDirectory)</AppHostTemplateRestoreAdditionalParameters>
|
||||
</PropertyGroup>
|
||||
|
||||
<DotNetRestore ToolPath="$(PreviousStageDirectory)"
|
||||
ProjectPath="$(MSBuildThisFileDirectory)/templates/templates.csproj"
|
||||
AdditionalParameters="$(AppHostTemplateRestoreAdditionalParameters)" />
|
||||
</Target>
|
||||
</Project>
|
|
@ -2,7 +2,7 @@
|
|||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<MicrosoftAspNetCoreAppPackageVersion>2.1.0-preview2-30475</MicrosoftAspNetCoreAppPackageVersion>
|
||||
<MicrosoftNETCoreAppPackageVersion>2.1.0-preview2-26314-02</MicrosoftNETCoreAppPackageVersion>
|
||||
<MicrosoftNETCoreAppPackageVersion>2.1.0-preview2-26330-03</MicrosoftNETCoreAppPackageVersion>
|
||||
<MicrosoftNETCoreDotNetHostResolverPackageVersion>$(MicrosoftNETCoreAppPackageVersion)</MicrosoftNETCoreDotNetHostResolverPackageVersion>
|
||||
<MicrosoftBuildPackageVersion>15.7.0-preview-000127</MicrosoftBuildPackageVersion>
|
||||
<MicrosoftBuildFrameworkPackageVersion>$(MicrosoftBuildPackageVersion)</MicrosoftBuildFrameworkPackageVersion>
|
||||
|
@ -28,8 +28,8 @@
|
|||
<MicrosoftTemplateEngineCliLocalizationPackageVersion>$(MicrosoftTemplateEngineCliPackageVersion)</MicrosoftTemplateEngineCliLocalizationPackageVersion>
|
||||
<MicrosoftTemplateEngineOrchestratorRunnableProjectsPackageVersion>$(MicrosoftTemplateEngineCliPackageVersion)</MicrosoftTemplateEngineOrchestratorRunnableProjectsPackageVersion>
|
||||
<MicrosoftTemplateEngineUtilsPackageVersion>$(MicrosoftTemplateEngineCliPackageVersion)</MicrosoftTemplateEngineUtilsPackageVersion>
|
||||
<MicrosoftDotNetPlatformAbstractionsPackageVersion>2.1.0-preview2-26314-02</MicrosoftDotNetPlatformAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsDependencyModelPackageVersion>2.1.0-preview2-26314-02</MicrosoftExtensionsDependencyModelPackageVersion>
|
||||
<MicrosoftDotNetPlatformAbstractionsPackageVersion>2.1.0-preview2-26330-03</MicrosoftDotNetPlatformAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsDependencyModelPackageVersion>2.1.0-preview2-26330-03</MicrosoftExtensionsDependencyModelPackageVersion>
|
||||
<MicrosoftDotNetCliCommandLinePackageVersion>0.1.1-alpha-174</MicrosoftDotNetCliCommandLinePackageVersion>
|
||||
<MicrosoftDotNetProjectJsonMigrationPackageVersion>1.2.1-alpha-002133</MicrosoftDotNetProjectJsonMigrationPackageVersion>
|
||||
<MicrosoftDotNetToolsMigrateCommandPackageVersion>$(MicrosoftDotNetProjectJsonMigrationPackageVersion)</MicrosoftDotNetToolsMigrateCommandPackageVersion>
|
||||
|
|
145
src/Microsoft.DotNet.Cli.Utils/EmbedAppNameInHost.cs
Normal file
145
src/Microsoft.DotNet.Cli.Utils/EmbedAppNameInHost.cs
Normal file
|
@ -0,0 +1,145 @@
|
|||
// 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.
|
||||
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.DotNet.Cli.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// Embeds the App Name into the AppHost.exe
|
||||
/// </summary>
|
||||
public static class EmbedAppNameInHost
|
||||
{
|
||||
private static string _placeHolder = "c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2"; //hash value embedded in default apphost executable
|
||||
private static byte[] _bytesToSearch = Encoding.UTF8.GetBytes(_placeHolder);
|
||||
public static void EmbedAndReturnModifiedAppHostPath(
|
||||
string appHostSourceFilePath,
|
||||
string appHostDestinationFilePath,
|
||||
string appBinaryName)
|
||||
{
|
||||
var hostExtension = Path.GetExtension(appHostSourceFilePath);
|
||||
var appbaseName = Path.GetFileNameWithoutExtension(appBinaryName);
|
||||
var bytesToWrite = Encoding.UTF8.GetBytes(appBinaryName);
|
||||
var destinationDirectory = new FileInfo(appHostDestinationFilePath).Directory.FullName;
|
||||
|
||||
if (File.Exists(appHostDestinationFilePath))
|
||||
{
|
||||
//We have already done the required modification to apphost.exe
|
||||
return;
|
||||
}
|
||||
|
||||
if (bytesToWrite.Length > 1024)
|
||||
{
|
||||
throw new EmbedAppNameInHostException(string.Format(LocalizableStrings.EmbedAppNameInHostFileNameIsTooLong, appBinaryName));
|
||||
}
|
||||
|
||||
var array = File.ReadAllBytes(appHostSourceFilePath);
|
||||
|
||||
SearchAndReplace(array, _bytesToSearch, bytesToWrite, appHostSourceFilePath);
|
||||
|
||||
if (!Directory.Exists(destinationDirectory))
|
||||
{
|
||||
Directory.CreateDirectory(destinationDirectory);
|
||||
}
|
||||
|
||||
// Copy AppHostSourcePath to ModifiedAppHostPath so it inherits the same attributes\permissions.
|
||||
File.Copy(appHostSourceFilePath, appHostDestinationFilePath);
|
||||
|
||||
// Re-write ModifiedAppHostPath with the proper contents.
|
||||
using (FileStream fs = new FileStream(appHostDestinationFilePath, FileMode.Truncate, FileAccess.ReadWrite, FileShare.Read))
|
||||
{
|
||||
fs.Write(array, 0, array.Length);
|
||||
}
|
||||
}
|
||||
|
||||
// See: https://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm
|
||||
private static int[] ComputeKMPFailureFunction(byte[] pattern)
|
||||
{
|
||||
int[] table = new int[pattern.Length];
|
||||
if (pattern.Length >= 1)
|
||||
{
|
||||
table[0] = -1;
|
||||
}
|
||||
if (pattern.Length >= 2)
|
||||
{
|
||||
table[1] = 0;
|
||||
}
|
||||
|
||||
int pos = 2;
|
||||
int cnd = 0;
|
||||
while (pos < pattern.Length)
|
||||
{
|
||||
if (pattern[pos - 1] == pattern[cnd])
|
||||
{
|
||||
table[pos] = cnd + 1;
|
||||
cnd++;
|
||||
pos++;
|
||||
}
|
||||
else if (cnd > 0)
|
||||
{
|
||||
cnd = table[cnd];
|
||||
}
|
||||
else
|
||||
{
|
||||
table[pos] = 0;
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
// See: https://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm
|
||||
private static int KMPSearch(byte[] pattern, byte[] bytes)
|
||||
{
|
||||
int m = 0;
|
||||
int i = 0;
|
||||
int[] table = ComputeKMPFailureFunction(pattern);
|
||||
|
||||
while (m + i < bytes.Length)
|
||||
{
|
||||
if (pattern[i] == bytes[m + i])
|
||||
{
|
||||
if (i == pattern.Length - 1)
|
||||
{
|
||||
return m;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (table[i] > -1)
|
||||
{
|
||||
m = m + i - table[i];
|
||||
i = table[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
m++;
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static void SearchAndReplace(byte[] array, byte[] searchPattern, byte[] patternToReplace, string appHostSourcePath)
|
||||
{
|
||||
int offset = KMPSearch(searchPattern, array);
|
||||
if (offset < 0)
|
||||
{
|
||||
throw new EmbedAppNameInHostException(string.Format(LocalizableStrings.EmbedAppNameInHostAppHostHasBeenModified, appHostSourcePath, _placeHolder));
|
||||
}
|
||||
|
||||
patternToReplace.CopyTo(array, offset);
|
||||
|
||||
if (patternToReplace.Length < searchPattern.Length)
|
||||
{
|
||||
for (int i = patternToReplace.Length; i < searchPattern.Length; i++)
|
||||
{
|
||||
array[i + offset] = 0x0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
// 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.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.DotNet.Cli.Utils
|
||||
{
|
||||
public class EmbedAppNameInHostException : Exception
|
||||
{
|
||||
public EmbedAppNameInHostException()
|
||||
{
|
||||
}
|
||||
|
||||
public EmbedAppNameInHostException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public EmbedAppNameInHostException(string message, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -265,4 +265,10 @@
|
|||
<data name="MSBuildArgs" xml:space="preserve">
|
||||
<value>MSBuild arguments: {0}</value>
|
||||
</data>
|
||||
</root>
|
||||
<data name="EmbedAppNameInHostAppHostHasBeenModified" xml:space="preserve">
|
||||
<value>Unable to use '{0}' as application host executable as it does not contain the expected placeholder byte sequence '{1}' that would mark where the application name would be written.</value>
|
||||
</data>
|
||||
<data name="EmbedAppNameInHostFileNameIsTooLong" xml:space="preserve">
|
||||
<value>Given file name '{0}' is longer than 1024 bytes</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
|
@ -249,6 +249,16 @@
|
|||
<target state="new">MSBuild arguments: {0}</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="EmbedAppNameInHostAppHostHasBeenModified">
|
||||
<source>Unable to use '{0}' as application host executable as it does not contain the expected placeholder byte sequence '{1}' that would mark where the application name would be written.</source>
|
||||
<target state="new">Unable to use '{0}' as application host executable as it does not contain the expected placeholder byte sequence '{1}' that would mark where the application name would be written.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="EmbedAppNameInHostFileNameIsTooLong">
|
||||
<source>Given file name '{0}' is longer than 1024 bytes</source>
|
||||
<target state="new">Given file name '{0}' is longer than 1024 bytes</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
|
@ -249,6 +249,16 @@
|
|||
<target state="new">MSBuild arguments: {0}</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="EmbedAppNameInHostAppHostHasBeenModified">
|
||||
<source>Unable to use '{0}' as application host executable as it does not contain the expected placeholder byte sequence '{1}' that would mark where the application name would be written.</source>
|
||||
<target state="new">Unable to use '{0}' as application host executable as it does not contain the expected placeholder byte sequence '{1}' that would mark where the application name would be written.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="EmbedAppNameInHostFileNameIsTooLong">
|
||||
<source>Given file name '{0}' is longer than 1024 bytes</source>
|
||||
<target state="new">Given file name '{0}' is longer than 1024 bytes</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
|
@ -249,6 +249,16 @@
|
|||
<target state="new">MSBuild arguments: {0}</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="EmbedAppNameInHostAppHostHasBeenModified">
|
||||
<source>Unable to use '{0}' as application host executable as it does not contain the expected placeholder byte sequence '{1}' that would mark where the application name would be written.</source>
|
||||
<target state="new">Unable to use '{0}' as application host executable as it does not contain the expected placeholder byte sequence '{1}' that would mark where the application name would be written.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="EmbedAppNameInHostFileNameIsTooLong">
|
||||
<source>Given file name '{0}' is longer than 1024 bytes</source>
|
||||
<target state="new">Given file name '{0}' is longer than 1024 bytes</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
|
@ -249,6 +249,16 @@
|
|||
<target state="new">MSBuild arguments: {0}</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="EmbedAppNameInHostAppHostHasBeenModified">
|
||||
<source>Unable to use '{0}' as application host executable as it does not contain the expected placeholder byte sequence '{1}' that would mark where the application name would be written.</source>
|
||||
<target state="new">Unable to use '{0}' as application host executable as it does not contain the expected placeholder byte sequence '{1}' that would mark where the application name would be written.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="EmbedAppNameInHostFileNameIsTooLong">
|
||||
<source>Given file name '{0}' is longer than 1024 bytes</source>
|
||||
<target state="new">Given file name '{0}' is longer than 1024 bytes</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
|
@ -249,6 +249,16 @@
|
|||
<target state="new">MSBuild arguments: {0}</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="EmbedAppNameInHostAppHostHasBeenModified">
|
||||
<source>Unable to use '{0}' as application host executable as it does not contain the expected placeholder byte sequence '{1}' that would mark where the application name would be written.</source>
|
||||
<target state="new">Unable to use '{0}' as application host executable as it does not contain the expected placeholder byte sequence '{1}' that would mark where the application name would be written.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="EmbedAppNameInHostFileNameIsTooLong">
|
||||
<source>Given file name '{0}' is longer than 1024 bytes</source>
|
||||
<target state="new">Given file name '{0}' is longer than 1024 bytes</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
|
@ -249,6 +249,16 @@
|
|||
<target state="new">MSBuild arguments: {0}</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="EmbedAppNameInHostAppHostHasBeenModified">
|
||||
<source>Unable to use '{0}' as application host executable as it does not contain the expected placeholder byte sequence '{1}' that would mark where the application name would be written.</source>
|
||||
<target state="new">Unable to use '{0}' as application host executable as it does not contain the expected placeholder byte sequence '{1}' that would mark where the application name would be written.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="EmbedAppNameInHostFileNameIsTooLong">
|
||||
<source>Given file name '{0}' is longer than 1024 bytes</source>
|
||||
<target state="new">Given file name '{0}' is longer than 1024 bytes</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
|
@ -249,6 +249,16 @@
|
|||
<target state="new">MSBuild arguments: {0}</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="EmbedAppNameInHostAppHostHasBeenModified">
|
||||
<source>Unable to use '{0}' as application host executable as it does not contain the expected placeholder byte sequence '{1}' that would mark where the application name would be written.</source>
|
||||
<target state="new">Unable to use '{0}' as application host executable as it does not contain the expected placeholder byte sequence '{1}' that would mark where the application name would be written.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="EmbedAppNameInHostFileNameIsTooLong">
|
||||
<source>Given file name '{0}' is longer than 1024 bytes</source>
|
||||
<target state="new">Given file name '{0}' is longer than 1024 bytes</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
|
@ -249,6 +249,16 @@
|
|||
<target state="new">MSBuild arguments: {0}</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="EmbedAppNameInHostAppHostHasBeenModified">
|
||||
<source>Unable to use '{0}' as application host executable as it does not contain the expected placeholder byte sequence '{1}' that would mark where the application name would be written.</source>
|
||||
<target state="new">Unable to use '{0}' as application host executable as it does not contain the expected placeholder byte sequence '{1}' that would mark where the application name would be written.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="EmbedAppNameInHostFileNameIsTooLong">
|
||||
<source>Given file name '{0}' is longer than 1024 bytes</source>
|
||||
<target state="new">Given file name '{0}' is longer than 1024 bytes</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
|
@ -249,6 +249,16 @@
|
|||
<target state="new">MSBuild arguments: {0}</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="EmbedAppNameInHostAppHostHasBeenModified">
|
||||
<source>Unable to use '{0}' as application host executable as it does not contain the expected placeholder byte sequence '{1}' that would mark where the application name would be written.</source>
|
||||
<target state="new">Unable to use '{0}' as application host executable as it does not contain the expected placeholder byte sequence '{1}' that would mark where the application name would be written.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="EmbedAppNameInHostFileNameIsTooLong">
|
||||
<source>Given file name '{0}' is longer than 1024 bytes</source>
|
||||
<target state="new">Given file name '{0}' is longer than 1024 bytes</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
|
@ -249,6 +249,16 @@
|
|||
<target state="new">MSBuild arguments: {0}</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="EmbedAppNameInHostAppHostHasBeenModified">
|
||||
<source>Unable to use '{0}' as application host executable as it does not contain the expected placeholder byte sequence '{1}' that would mark where the application name would be written.</source>
|
||||
<target state="new">Unable to use '{0}' as application host executable as it does not contain the expected placeholder byte sequence '{1}' that would mark where the application name would be written.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="EmbedAppNameInHostFileNameIsTooLong">
|
||||
<source>Given file name '{0}' is longer than 1024 bytes</source>
|
||||
<target state="new">Given file name '{0}' is longer than 1024 bytes</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
|
@ -249,6 +249,16 @@
|
|||
<target state="new">MSBuild arguments: {0}</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="EmbedAppNameInHostAppHostHasBeenModified">
|
||||
<source>Unable to use '{0}' as application host executable as it does not contain the expected placeholder byte sequence '{1}' that would mark where the application name would be written.</source>
|
||||
<target state="new">Unable to use '{0}' as application host executable as it does not contain the expected placeholder byte sequence '{1}' that would mark where the application name would be written.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="EmbedAppNameInHostFileNameIsTooLong">
|
||||
<source>Given file name '{0}' is longer than 1024 bytes</source>
|
||||
<target state="new">Given file name '{0}' is longer than 1024 bytes</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
|
@ -249,6 +249,16 @@
|
|||
<target state="new">MSBuild arguments: {0}</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="EmbedAppNameInHostAppHostHasBeenModified">
|
||||
<source>Unable to use '{0}' as application host executable as it does not contain the expected placeholder byte sequence '{1}' that would mark where the application name would be written.</source>
|
||||
<target state="new">Unable to use '{0}' as application host executable as it does not contain the expected placeholder byte sequence '{1}' that would mark where the application name would be written.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="EmbedAppNameInHostFileNameIsTooLong">
|
||||
<source>Given file name '{0}' is longer than 1024 bytes</source>
|
||||
<target state="new">Given file name '{0}' is longer than 1024 bytes</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
|
@ -249,6 +249,16 @@
|
|||
<target state="new">MSBuild arguments: {0}</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="EmbedAppNameInHostAppHostHasBeenModified">
|
||||
<source>Unable to use '{0}' as application host executable as it does not contain the expected placeholder byte sequence '{1}' that would mark where the application name would be written.</source>
|
||||
<target state="new">Unable to use '{0}' as application host executable as it does not contain the expected placeholder byte sequence '{1}' that would mark where the application name would be written.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="EmbedAppNameInHostFileNameIsTooLong">
|
||||
<source>Given file name '{0}' is longer than 1024 bytes</source>
|
||||
<target state="new">Given file name '{0}' is longer than 1024 bytes</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
|
@ -6,25 +6,27 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.DotNet.Cli;
|
||||
using Microsoft.DotNet.Cli.Utils;
|
||||
using Microsoft.DotNet.PlatformAbstractions;
|
||||
using Microsoft.DotNet.Tools;
|
||||
using Microsoft.Extensions.EnvironmentAbstractions;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.DotNet.ShellShim
|
||||
{
|
||||
internal class ShellShimRepository : IShellShimRepository
|
||||
{
|
||||
private const string LauncherExeResourceName = "Microsoft.DotNet.Tools.Launcher.Executable";
|
||||
private const string LauncherConfigResourceName = "Microsoft.DotNet.Tools.Launcher.Config";
|
||||
private const string ApphostNameWithoutExtension = "apphost";
|
||||
|
||||
private readonly DirectoryPath _shimsDirectory;
|
||||
private readonly string _appHostSourceDirectory;
|
||||
|
||||
public ShellShimRepository(DirectoryPath shimsDirectory)
|
||||
public ShellShimRepository(DirectoryPath shimsDirectory, string appHostSourcePath = null)
|
||||
{
|
||||
_shimsDirectory = shimsDirectory;
|
||||
_appHostSourceDirectory = appHostSourcePath ?? Path.Combine(ApplicationEnvironment.ApplicationBasePath,
|
||||
"AppHostTemplate");
|
||||
}
|
||||
|
||||
public void CreateShim(FilePath targetExecutablePath, string commandName)
|
||||
|
@ -47,7 +49,8 @@ namespace Microsoft.DotNet.ShellShim
|
|||
}
|
||||
|
||||
TransactionalAction.Run(
|
||||
action: () => {
|
||||
action: () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(_shimsDirectory.Value))
|
||||
|
@ -55,29 +58,13 @@ namespace Microsoft.DotNet.ShellShim
|
|||
Directory.CreateDirectory(_shimsDirectory.Value);
|
||||
}
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
CreateApphostShimAndConfigFile(
|
||||
commandName,
|
||||
entryPoint: targetExecutablePath);
|
||||
|
||||
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
CreateConfigFile(
|
||||
outputPath: GetWindowsConfigPath(commandName),
|
||||
entryPoint: targetExecutablePath,
|
||||
runner: "dotnet");
|
||||
|
||||
using (var shim = File.Create(GetWindowsShimPath(commandName).Value))
|
||||
using (var resource = typeof(ShellShimRepository).Assembly.GetManifestResourceStream(LauncherExeResourceName))
|
||||
{
|
||||
resource.CopyTo(shim);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var script = new StringBuilder();
|
||||
script.AppendLine("#!/bin/sh");
|
||||
script.AppendLine($"dotnet {targetExecutablePath.ToQuotedString()} \"$@\"");
|
||||
|
||||
var shimPath = GetPosixShimPath(commandName);
|
||||
File.WriteAllText(shimPath.Value, script.ToString());
|
||||
|
||||
SetUserExecutionPermission(shimPath);
|
||||
SetUserExecutionPermission(GetShimPath(commandName));
|
||||
}
|
||||
}
|
||||
catch (Exception ex) when (ex is UnauthorizedAccessException || ex is IOException)
|
||||
|
@ -138,18 +125,43 @@ namespace Microsoft.DotNet.ShellShim
|
|||
});
|
||||
}
|
||||
|
||||
internal void CreateConfigFile(FilePath outputPath, FilePath entryPoint, string runner)
|
||||
private void CreateApphostShimAndConfigFile(string commandName, FilePath entryPoint)
|
||||
{
|
||||
XDocument config;
|
||||
using (var resource = typeof(ShellShimRepository).Assembly.GetManifestResourceStream(LauncherConfigResourceName))
|
||||
string appHostSourcePath;
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
config = XDocument.Load(resource);
|
||||
appHostSourcePath = Path.Combine(_appHostSourceDirectory, ApphostNameWithoutExtension + ".exe");
|
||||
}
|
||||
else
|
||||
{
|
||||
appHostSourcePath = Path.Combine(_appHostSourceDirectory, ApphostNameWithoutExtension);
|
||||
}
|
||||
|
||||
var appSettings = config.Descendants("appSettings").First();
|
||||
appSettings.Add(new XElement("add", new XAttribute("key", "entryPoint"), new XAttribute("value", entryPoint.Value)));
|
||||
appSettings.Add(new XElement("add", new XAttribute("key", "runner"), new XAttribute("value", runner ?? string.Empty)));
|
||||
config.Save(outputPath.Value);
|
||||
EmbedAppNameInHost.EmbedAndReturnModifiedAppHostPath(
|
||||
appHostSourceFilePath: appHostSourcePath,
|
||||
appHostDestinationFilePath: GetShimPath(commandName).Value,
|
||||
appBinaryName: Path.GetFileName(entryPoint.Value));
|
||||
|
||||
var config = JsonConvert.SerializeObject(
|
||||
new RootObject
|
||||
{
|
||||
startupOptions = new StartupOptions
|
||||
{
|
||||
appRoot = entryPoint.GetDirectoryPath().Value
|
||||
}
|
||||
});
|
||||
|
||||
File.WriteAllText(GetConfigPath(commandName).Value, config);
|
||||
}
|
||||
|
||||
private class StartupOptions
|
||||
{
|
||||
public string appRoot { get; set; }
|
||||
}
|
||||
|
||||
private class RootObject
|
||||
{
|
||||
public StartupOptions startupOptions { get; set; }
|
||||
}
|
||||
|
||||
private bool ShimExists(string commandName)
|
||||
|
@ -164,30 +176,25 @@ namespace Microsoft.DotNet.ShellShim
|
|||
yield break;
|
||||
}
|
||||
|
||||
yield return GetShimPath(commandName);
|
||||
yield return GetConfigPath(commandName);
|
||||
}
|
||||
|
||||
private FilePath GetShimPath(string commandName)
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
yield return GetWindowsShimPath(commandName);
|
||||
yield return GetWindowsConfigPath(commandName);
|
||||
return new FilePath(_shimsDirectory.WithFile(commandName).Value +".exe");
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return GetPosixShimPath(commandName);
|
||||
return _shimsDirectory.WithFile(commandName);
|
||||
}
|
||||
}
|
||||
|
||||
private FilePath GetPosixShimPath(string commandName)
|
||||
private FilePath GetConfigPath(string commandName)
|
||||
{
|
||||
return _shimsDirectory.WithFile(commandName);
|
||||
}
|
||||
|
||||
private FilePath GetWindowsShimPath(string commandName)
|
||||
{
|
||||
return new FilePath(_shimsDirectory.WithFile(commandName).Value + ".exe");
|
||||
}
|
||||
|
||||
private FilePath GetWindowsConfigPath(string commandName)
|
||||
{
|
||||
return new FilePath(GetWindowsShimPath(commandName).Value + ".config");
|
||||
return _shimsDirectory.WithFile(commandName + ".startupconfig.json");
|
||||
}
|
||||
|
||||
private static void SetUserExecutionPermission(FilePath path)
|
||||
|
|
|
@ -79,5 +79,5 @@
|
|||
<Folder Include="commands\dotnet-migrate\xlf" />
|
||||
<Folder Include="dotnet-complete\commands\" />
|
||||
</ItemGroup>
|
||||
<Import Project="dotnet.win.targets" Condition="'$(OS)' == 'Windows_NT'" />
|
||||
</Project>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
<!-- This file should only be used when building dotnet for windows. -->
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Only included to ensure this is built first. -->
|
||||
<ProjectReference Include="..\tool_launcher\tool_launcher.csproj"
|
||||
ReferenceOutputAssembly="false"
|
||||
SkipGetTargetFrameworkProperties="true"
|
||||
PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="EmbedDotnetLauncher" BeforeTargets="PrepareForBuild">
|
||||
<MSBuild Projects="..\tool_launcher\tool_launcher.csproj" Targets="GetTargetPath" Properties="Configuration=$(Configuration)">
|
||||
<Output TaskParameter="TargetOutputs" PropertyName="DotnetLauncherFullPath" />
|
||||
</MSBuild>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="$(DotnetLauncherFullPath)" LogicalName="Microsoft.DotNet.Tools.Launcher.Executable" />
|
||||
<EmbeddedResource Include="$(DotnetLauncherFullPath).config" LogicalName="Microsoft.DotNet.Tools.Launcher.Config" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
</Project>
|
|
@ -211,6 +211,44 @@
|
|||
</MSBuild>
|
||||
</Target>
|
||||
|
||||
<Target Name="PublishAppHostTemplate"
|
||||
AfterTargets="Publish">
|
||||
|
||||
<PropertyGroup>
|
||||
<NETCoreDotNetAppHostPackageName>Microsoft.NETCore.DotNetAppHost</NETCoreDotNetAppHostPackageName>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<NETCoreDotNetAppHostPackageVersions Include="@(PackageDefinitions->'%(Version)')"
|
||||
Condition="%(PackageDefinitions.Name) == $(NETCoreDotNetAppHostPackageName)" />
|
||||
</ItemGroup>
|
||||
|
||||
<Error Condition="@(NETCoreDotNetAppHostPackageVersions->Distinct()->Count()) != 1"
|
||||
Text="Failed to determine the $(NETCoreDotNetAppHostPackageName) version pulled in Microsoft.NETCore.App" />
|
||||
|
||||
<PropertyGroup>
|
||||
<_NETCoreDotNetAppHostPackageVersion>@(NETCoreDotNetAppHostPackageVersions->Distinct())</_NETCoreDotNetAppHostPackageVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<AppHostTemplate Include="$(RepoRoot)/build/AppHostTemplate.proj">
|
||||
<Properties>
|
||||
AppHostTemplatePath=$(SdkOutputDirectory)/AppHostTemplate;
|
||||
TemplateFillInPackageName=$(NETCoreDotNetAppHostPackageName);
|
||||
TemplateFillInPackageVersion=$(_NETCoreDotNetAppHostPackageVersion);
|
||||
PreviousStageDirectory=$(PreviousStageDirectory);
|
||||
AppHostIntermediateDirectory=$(IntermediateDirectory)/AppHostIntermediate
|
||||
</Properties>
|
||||
</AppHostTemplate>
|
||||
</ItemGroup>
|
||||
|
||||
<MSBuild
|
||||
BuildInParallel="False"
|
||||
Projects="@(AppHostTemplate)">
|
||||
</MSBuild>
|
||||
|
||||
</Target>
|
||||
|
||||
<Target Name="PublishLzmaArchive"
|
||||
Condition="'$(CLIBUILD_SKIP_LZMA)' != 'true'"
|
||||
DependsOnTargets="GetNuGetPackagesArchive"
|
||||
|
|
|
@ -1,116 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Configuration;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.DotNet.Cli.Utils;
|
||||
|
||||
namespace Microsoft.DotNet.Tools.Launcher
|
||||
{
|
||||
/// <summary>
|
||||
/// The app is simple shim into launching arbitrary command line processes.
|
||||
/// It is configured via app settings .NET config file. (See app.config).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Launching new processes using cmd.exe and .cmd files causes issues for long-running process
|
||||
/// because CTRL+C always hangs on interrupt with the prompt "Terminate Y/N". This can lead to
|
||||
/// orphaned processes.
|
||||
/// </remarks>
|
||||
class Program
|
||||
{
|
||||
private const string TRACE = "DOTNET_LAUNCHER_TRACE";
|
||||
private const int ERR_FAILED = -1;
|
||||
private static bool _trace;
|
||||
|
||||
public static int Main(string[] argsToForward)
|
||||
{
|
||||
bool.TryParse(Environment.GetEnvironmentVariable(TRACE), out _trace);
|
||||
|
||||
try
|
||||
{
|
||||
var appSettings = ConfigurationManager.AppSettings;
|
||||
|
||||
var entryPoint = appSettings["entryPoint"];
|
||||
if (string.IsNullOrEmpty(entryPoint))
|
||||
{
|
||||
LogError("The launcher must specify a non-empty appSetting value for 'entryPoint'.");
|
||||
return ERR_FAILED;
|
||||
}
|
||||
|
||||
var exePath = entryPoint;
|
||||
var runner = appSettings["runner"];
|
||||
|
||||
var args = new List<string>();
|
||||
|
||||
if (!string.IsNullOrEmpty(runner))
|
||||
{
|
||||
args.Add(entryPoint);
|
||||
exePath = runner;
|
||||
}
|
||||
|
||||
args.AddRange(argsToForward);
|
||||
|
||||
var argString = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(args);
|
||||
|
||||
using (var process = new Process
|
||||
{
|
||||
StartInfo =
|
||||
{
|
||||
FileName = exePath,
|
||||
Arguments = argString,
|
||||
CreateNoWindow = false,
|
||||
UseShellExecute = false,
|
||||
}
|
||||
})
|
||||
{
|
||||
LogTrace("Starting a new process.");
|
||||
LogTrace("filename = " + process.StartInfo.FileName);
|
||||
LogTrace("args = " + process.StartInfo.Arguments);
|
||||
LogTrace("cwd = " + process.StartInfo.WorkingDirectory);
|
||||
|
||||
try
|
||||
{
|
||||
process.Start();
|
||||
}
|
||||
catch (Win32Exception ex)
|
||||
{
|
||||
LogTrace(ex.ToString());
|
||||
LogError($"Failed to start '{process.StartInfo.FileName}'. " + ex.Message);
|
||||
return ERR_FAILED;
|
||||
}
|
||||
|
||||
process.WaitForExit();
|
||||
|
||||
LogTrace("Exited code " + process.ExitCode);
|
||||
|
||||
return process.ExitCode;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogError("Unexpected error launching a new process. Run with the environment variable " + TRACE + "='true' for details.");
|
||||
LogTrace(ex.ToString());
|
||||
return ERR_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
private static void LogError(string message)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.BackgroundColor = ConsoleColor.Black;
|
||||
Console.Error.WriteLine("ERROR: " + message);
|
||||
Console.ResetColor();
|
||||
}
|
||||
|
||||
private static void LogTrace(string message)
|
||||
{
|
||||
if (!_trace)
|
||||
return;
|
||||
|
||||
Console.ForegroundColor = ConsoleColor.DarkGray;
|
||||
Console.BackgroundColor = ConsoleColor.Black;
|
||||
Console.WriteLine("[dotnet-launcher] " + message);
|
||||
Console.ResetColor();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
<!--
|
||||
Generated by the .NET Core Command Line.
|
||||
-->
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v2.0.50727" />
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||
</startup>
|
||||
<appSettings>
|
||||
<!--
|
||||
To use this launcher, this value must be set. It is a file path or name of the new process being launched.
|
||||
<add key="entryPoint" value="%entrypoint%" />
|
||||
|
||||
This value may also be set. It is an path to another executable used to launch the entry point.
|
||||
It is treated as single argument.
|
||||
<add key="runner" value="%runner%" />
|
||||
-->
|
||||
</appSettings>
|
||||
</configuration>
|
|
@ -1,30 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<!-- Targets .NET Framework 3.5 because .NET Framework 4.5 is not bundled in Windows 7. -->
|
||||
<TargetFramework>net35</TargetFramework>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<OutputType>exe</OutputType>
|
||||
<IsPackable>false</IsPackable>
|
||||
<AssemblyName>Microsoft.DotNet.Tools.Launcher</AssemblyName>
|
||||
<Title>dotnet-tool-launcher</Title>
|
||||
<Description>
|
||||
A simple Windows-only shim for launching new processes.
|
||||
</Description>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- This project must not have any package references. It must be a standalone .exe file -->
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Workaround https://github.com/Microsoft/msbuild/issues/1333 -->
|
||||
<PropertyGroup>
|
||||
<FrameworkPathOverride>$(MSBuildProgramFiles32)\Reference Assemblies\Microsoft\Framework\.NETFramework\v3.5\Profile\Client</FrameworkPathOverride>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Microsoft.DotNet.Cli.Utils\ArgumentEscaper.cs" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -30,36 +30,12 @@ namespace Microsoft.DotNet.ShellShim.Tests
|
|||
_output = output;
|
||||
}
|
||||
|
||||
[WindowsOnlyTheory]
|
||||
[InlineData("my_native_app.exe", null)]
|
||||
[InlineData("./my_native_app.js", "nodejs")]
|
||||
[InlineData(@"C:\tools\my_native_app.dll", "dotnet")]
|
||||
public void GivenAnRunnerOrEntryPointItCanCreateConfig(string entryPointPath, string runner)
|
||||
{
|
||||
var pathToShim = GetNewCleanFolderUnderTempRoot();
|
||||
var shellShimRepository = new ShellShimRepository(new DirectoryPath(pathToShim));
|
||||
var tmpFile = new FilePath(Path.Combine(pathToShim, Path.GetRandomFileName()));
|
||||
|
||||
shellShimRepository.CreateConfigFile(tmpFile, new FilePath(entryPointPath), runner);
|
||||
|
||||
new FileInfo(tmpFile.Value).Should().Exist();
|
||||
|
||||
var generated = XDocument.Load(tmpFile.Value);
|
||||
|
||||
generated.Descendants("appSettings")
|
||||
.Descendants("add")
|
||||
.Should()
|
||||
.Contain(e => e.Attribute("key").Value == "runner" && e.Attribute("value").Value == (runner ?? string.Empty))
|
||||
.And
|
||||
.Contain(e => e.Attribute("key").Value == "entryPoint" && e.Attribute("value").Value == entryPointPath);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GivenAnExecutablePathItCanGenerateShimFile()
|
||||
{
|
||||
var outputDll = MakeHelloWorldExecutableDll();
|
||||
var pathToShim = GetNewCleanFolderUnderTempRoot();
|
||||
var shellShimRepository = new ShellShimRepository(new DirectoryPath(pathToShim));
|
||||
ShellShimRepository shellShimRepository = ConfigBasicTestDependecyShellShimRepository(pathToShim);
|
||||
var shellCommandName = nameof(ShellShimRepositoryTests) + Path.GetRandomFileName();
|
||||
|
||||
shellShimRepository.CreateShim(outputDll, shellCommandName);
|
||||
|
@ -69,12 +45,19 @@ namespace Microsoft.DotNet.ShellShim.Tests
|
|||
stdOut.Should().Contain("Hello World");
|
||||
}
|
||||
|
||||
private static ShellShimRepository ConfigBasicTestDependecyShellShimRepository(string pathToShim)
|
||||
{
|
||||
string stage2AppHostTemplateDirectory = GetAppHostTemplateFromStage2();
|
||||
|
||||
return new ShellShimRepository(new DirectoryPath(pathToShim), stage2AppHostTemplateDirectory);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GivenAnExecutablePathItCanGenerateShimFileInTransaction()
|
||||
{
|
||||
var outputDll = MakeHelloWorldExecutableDll();
|
||||
var pathToShim = GetNewCleanFolderUnderTempRoot();
|
||||
var shellShimRepository = new ShellShimRepository(new DirectoryPath(pathToShim));
|
||||
var shellShimRepository = ConfigBasicTestDependecyShellShimRepository(pathToShim);
|
||||
var shellCommandName = nameof(ShellShimRepositoryTests) + Path.GetRandomFileName();
|
||||
|
||||
using (var transactionScope = new TransactionScope(
|
||||
|
@ -95,7 +78,7 @@ namespace Microsoft.DotNet.ShellShim.Tests
|
|||
{
|
||||
var outputDll = MakeHelloWorldExecutableDll();
|
||||
var extraNonExistDirectory = Path.GetRandomFileName();
|
||||
var shellShimRepository = new ShellShimRepository(new DirectoryPath(Path.Combine(TempRoot.Root, extraNonExistDirectory)));
|
||||
var shellShimRepository = new ShellShimRepository(new DirectoryPath(Path.Combine(TempRoot.Root, extraNonExistDirectory)), GetAppHostTemplateFromStage2());
|
||||
var shellCommandName = nameof(ShellShimRepositoryTests) + Path.GetRandomFileName();
|
||||
|
||||
Action a = () => shellShimRepository.CreateShim(outputDll, shellCommandName);
|
||||
|
@ -111,7 +94,7 @@ namespace Microsoft.DotNet.ShellShim.Tests
|
|||
{
|
||||
var outputDll = MakeHelloWorldExecutableDll();
|
||||
var pathToShim = GetNewCleanFolderUnderTempRoot();
|
||||
var shellShimRepository = new ShellShimRepository(new DirectoryPath(pathToShim));
|
||||
var shellShimRepository = ConfigBasicTestDependecyShellShimRepository(pathToShim);
|
||||
var shellCommandName = nameof(ShellShimRepositoryTests) + Path.GetRandomFileName();
|
||||
|
||||
shellShimRepository.CreateShim(outputDll, shellCommandName);
|
||||
|
@ -140,7 +123,7 @@ namespace Microsoft.DotNet.ShellShim.Tests
|
|||
}
|
||||
else
|
||||
{
|
||||
shellShimRepository = new ShellShimRepository(new DirectoryPath(pathToShim));
|
||||
shellShimRepository = ConfigBasicTestDependecyShellShimRepository(pathToShim);
|
||||
}
|
||||
|
||||
Action a = () =>
|
||||
|
@ -182,7 +165,7 @@ namespace Microsoft.DotNet.ShellShim.Tests
|
|||
}
|
||||
else
|
||||
{
|
||||
shellShimRepository = new ShellShimRepository(new DirectoryPath(pathToShim));
|
||||
shellShimRepository = ConfigBasicTestDependecyShellShimRepository(pathToShim);
|
||||
}
|
||||
|
||||
Action intendedError = () => throw new ToolPackageException("simulated error");
|
||||
|
@ -219,7 +202,7 @@ namespace Microsoft.DotNet.ShellShim.Tests
|
|||
}
|
||||
else
|
||||
{
|
||||
shellShimRepository = new ShellShimRepository(new DirectoryPath(pathToShim));
|
||||
shellShimRepository = ConfigBasicTestDependecyShellShimRepository(pathToShim);
|
||||
}
|
||||
|
||||
Directory.EnumerateFileSystemEntries(pathToShim).Should().BeEmpty();
|
||||
|
@ -244,7 +227,7 @@ namespace Microsoft.DotNet.ShellShim.Tests
|
|||
}
|
||||
else
|
||||
{
|
||||
shellShimRepository = new ShellShimRepository(new DirectoryPath(pathToShim));
|
||||
shellShimRepository = ConfigBasicTestDependecyShellShimRepository(pathToShim);
|
||||
}
|
||||
|
||||
Directory.EnumerateFileSystemEntries(pathToShim).Should().BeEmpty();
|
||||
|
@ -273,7 +256,7 @@ namespace Microsoft.DotNet.ShellShim.Tests
|
|||
}
|
||||
else
|
||||
{
|
||||
shellShimRepository = new ShellShimRepository(new DirectoryPath(pathToShim));
|
||||
shellShimRepository = ConfigBasicTestDependecyShellShimRepository(pathToShim);
|
||||
}
|
||||
|
||||
Directory.EnumerateFileSystemEntries(pathToShim).Should().BeEmpty();
|
||||
|
@ -309,7 +292,7 @@ namespace Microsoft.DotNet.ShellShim.Tests
|
|||
}
|
||||
else
|
||||
{
|
||||
shellShimRepository = new ShellShimRepository(new DirectoryPath(pathToShim));
|
||||
shellShimRepository = ConfigBasicTestDependecyShellShimRepository(pathToShim);
|
||||
}
|
||||
|
||||
Directory.EnumerateFileSystemEntries(pathToShim).Should().BeEmpty();
|
||||
|
@ -358,17 +341,28 @@ namespace Microsoft.DotNet.ShellShim.Tests
|
|||
}
|
||||
else
|
||||
{
|
||||
var file = Path.Combine(cleanFolderUnderTempRoot, shellCommandName);
|
||||
processStartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "sh",
|
||||
Arguments = shellCommandName + " " + arguments,
|
||||
FileName = file,
|
||||
Arguments = arguments,
|
||||
UseShellExecute = false
|
||||
};
|
||||
}
|
||||
|
||||
_output.WriteLine($"Launching '{processStartInfo.FileName} {processStartInfo.Arguments}'");
|
||||
processStartInfo.WorkingDirectory = cleanFolderUnderTempRoot;
|
||||
processStartInfo.EnvironmentVariables["PATH"] = Path.GetDirectoryName(new Muxer().MuxerPath);
|
||||
|
||||
var environmentProvider = new EnvironmentProvider();
|
||||
processStartInfo.EnvironmentVariables["PATH"] = environmentProvider.GetEnvironmentVariable("PATH");
|
||||
if (Environment.Is64BitProcess)
|
||||
{
|
||||
processStartInfo.EnvironmentVariables["DOTNET_ROOT"] = new RepoDirectoriesProvider().DotnetRoot;
|
||||
}
|
||||
else
|
||||
{
|
||||
processStartInfo.EnvironmentVariables["DOTNET_ROOT(x86)"] = new RepoDirectoriesProvider().DotnetRoot;
|
||||
}
|
||||
|
||||
processStartInfo.ExecuteAndCaptureOutput(out var stdOut, out var stdErr);
|
||||
|
||||
|
@ -377,6 +371,47 @@ namespace Microsoft.DotNet.ShellShim.Tests
|
|||
return stdOut ?? "";
|
||||
}
|
||||
|
||||
private static FileInfo GetStage2DotnetPath()
|
||||
{
|
||||
string stage2DotnetPath;
|
||||
|
||||
var environmentProvider = new EnvironmentProvider();
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
stage2DotnetPath = environmentProvider.GetCommandPath("dotnet", ".exe");
|
||||
}
|
||||
else
|
||||
{
|
||||
stage2DotnetPath = environmentProvider.GetCommandPath("dotnet");
|
||||
}
|
||||
|
||||
var stage2Dotnet = new FileInfo(stage2DotnetPath);
|
||||
return stage2Dotnet;
|
||||
}
|
||||
|
||||
private static string GetAppHostTemplateFromStage2()
|
||||
{
|
||||
var environmentProvider = new EnvironmentProvider();
|
||||
string stage2DotnetPath;
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
stage2DotnetPath = environmentProvider.GetCommandPath("dotnet", ".exe");
|
||||
}
|
||||
else
|
||||
{
|
||||
stage2DotnetPath = environmentProvider.GetCommandPath("dotnet");
|
||||
}
|
||||
|
||||
var stage2Dotnet = GetStage2DotnetPath();
|
||||
|
||||
var stage2AppHostTemplateDirectory =
|
||||
new DirectoryInfo(new RepoDirectoriesProvider().Stage2Sdk)
|
||||
.GetDirectory("AppHostTemplate").FullName;
|
||||
return stage2AppHostTemplateDirectory;
|
||||
}
|
||||
|
||||
private static FilePath MakeHelloWorldExecutableDll()
|
||||
{
|
||||
const string testAppName = "TestAppSimple";
|
||||
|
|
|
@ -15,6 +15,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
|
|||
private static string s_buildRid;
|
||||
|
||||
private string _artifacts;
|
||||
private string _dotnetRoot;
|
||||
private string _builtDotnet;
|
||||
private string _nugetPackages;
|
||||
private string _stage2Sdk;
|
||||
|
@ -85,6 +86,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
|
|||
|
||||
public string Artifacts => _artifacts;
|
||||
public string BuiltDotnet => _builtDotnet;
|
||||
public string DotnetRoot => _dotnetRoot;
|
||||
public string NugetPackages => _nugetPackages;
|
||||
public string Stage2Sdk => _stage2Sdk;
|
||||
public string Stage2WithBackwardsCompatibleRuntimesDirectory => _stage2WithBackwardsCompatibleRuntimesDirectory;
|
||||
|
@ -106,6 +108,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
|
|||
previousStage.ToString(),
|
||||
BuildRid);
|
||||
_builtDotnet = builtDotnet ?? Path.Combine(_artifacts, "intermediate", "sharedFrameworkPublish");
|
||||
_dotnetRoot = Path.Combine(_artifacts, "dotnet");
|
||||
_nugetPackages = nugetPackages ?? Path.Combine(RepoRoot, ".nuget", "packages");
|
||||
_stage2Sdk = Directory
|
||||
.EnumerateDirectories(Path.Combine(_artifacts, "dotnet", "sdk"))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue