diff --git a/Microsoft.DotNet.Cli.sln b/Microsoft.DotNet.Cli.sln
index 4b341ed9a..0988307b9 100644
--- a/Microsoft.DotNet.Cli.sln
+++ b/Microsoft.DotNet.Cli.sln
@@ -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
diff --git a/build/AppHostTemplate.proj b/build/AppHostTemplate.proj
new file mode 100644
index 000000000..598f250b6
--- /dev/null
+++ b/build/AppHostTemplate.proj
@@ -0,0 +1,49 @@
+
+
+
+
+
+ .exe
+ AppHost$(NativeExecutableExtension)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ --runtime $(Rid)
+ $(AppHostTemplateRestoreAdditionalParameters) /p:TargetFramework=$(CliTargetFramework)
+ $(AppHostTemplateRestoreAdditionalParameters) /p:TemplateFillInPackageName=$(TemplateFillInPackageName)
+ $(AppHostTemplateRestoreAdditionalParameters) /p:TemplateFillInPackageVersion=$(TemplateFillInPackageVersion)
+ $(AppHostTemplateRestoreAdditionalParameters) /p:RestorePackagesPath=$(AppHostIntermediateDirectory)
+
+
+
+
+
diff --git a/build/DependencyVersions.props b/build/DependencyVersions.props
index c2271065a..5bf0a0e2c 100644
--- a/build/DependencyVersions.props
+++ b/build/DependencyVersions.props
@@ -2,7 +2,7 @@
2.1.0-preview2-30475
- 2.1.0-preview2-26314-02
+ 2.1.0-preview2-26330-03
$(MicrosoftNETCoreAppPackageVersion)
15.7.0-preview-000127
$(MicrosoftBuildPackageVersion)
@@ -28,8 +28,8 @@
$(MicrosoftTemplateEngineCliPackageVersion)
$(MicrosoftTemplateEngineCliPackageVersion)
$(MicrosoftTemplateEngineCliPackageVersion)
- 2.1.0-preview2-26314-02
- 2.1.0-preview2-26314-02
+ 2.1.0-preview2-26330-03
+ 2.1.0-preview2-26330-03
0.1.1-alpha-174
1.2.1-alpha-002133
$(MicrosoftDotNetProjectJsonMigrationPackageVersion)
diff --git a/src/Microsoft.DotNet.Cli.Utils/EmbedAppNameInHost.cs b/src/Microsoft.DotNet.Cli.Utils/EmbedAppNameInHost.cs
new file mode 100644
index 000000000..7a91b6f2f
--- /dev/null
+++ b/src/Microsoft.DotNet.Cli.Utils/EmbedAppNameInHost.cs
@@ -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
+{
+ ///
+ /// Embeds the App Name into the AppHost.exe
+ ///
+ 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;
+ }
+ }
+ }
+ }
+}
diff --git a/src/Microsoft.DotNet.Cli.Utils/EmbedAppNameInHostException.cs b/src/Microsoft.DotNet.Cli.Utils/EmbedAppNameInHostException.cs
new file mode 100644
index 000000000..a20432d42
--- /dev/null
+++ b/src/Microsoft.DotNet.Cli.Utils/EmbedAppNameInHostException.cs
@@ -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)
+ {
+ }
+ }
+}
diff --git a/src/Microsoft.DotNet.Cli.Utils/LocalizableStrings.resx b/src/Microsoft.DotNet.Cli.Utils/LocalizableStrings.resx
index 004d7a214..435a26de9 100644
--- a/src/Microsoft.DotNet.Cli.Utils/LocalizableStrings.resx
+++ b/src/Microsoft.DotNet.Cli.Utils/LocalizableStrings.resx
@@ -265,4 +265,10 @@
MSBuild arguments: {0}
-
\ No newline at end of file
+
+ 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.
+
+
+ Given file name '{0}' is longer than 1024 bytes
+
+
diff --git a/src/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.cs.xlf b/src/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.cs.xlf
index 015c486f0..e344ea524 100644
--- a/src/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.cs.xlf
+++ b/src/Microsoft.DotNet.Cli.Utils/xlf/LocalizableStrings.cs.xlf
@@ -249,6 +249,16 @@
MSBuild arguments: {0}
+
+ 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.
+ 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.
+
+
+
+ Given file name '{0}' is longer than 1024 bytes
+ Given file name '{0}' is longer than 1024 bytes
+
+