错误 MSB4018:"SignFile" 任务在生成服务器上意外失败
error MSB4018: The "SignFile" task failed unexpectedly on build server
我有一个 clickonce 解决方案,可以在安装了 VS 2015 的多台开发人员机器上运行。但是,它在我们的构建服务器上不起作用,它带有此 signFile 错误。我已经安装
- 构建工具 2015 更新 3
- .Net 4.6.2 SDK
- Windows 软件开发包
但显然 signtool.exe 的路径设置不正确。如果我禁用清单签名,它将继续,但会出现 setup.bin 丢失错误。
有人知道如何解决 SignFile 问题吗?
[_DeploymentComputeClickOnceManifestInfo] Using "SignFile" task from assembly "Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a".
[_DeploymentComputeClickOnceManifestInfo] SignFile
[SignFile] C:\Program Files (x86)\MSBuild.0\bin\Microsoft.Common.CurrentVersion.targets(3616, 5): error MSB4018: The "SignFile" task failed unexpectedly.
System.ArgumentNullException: Value cannot be null.
Parameter name: path1
at System.IO.Path.Combine(String path1, String path2, String path3)
at Microsoft.Build.Tasks.Deployment.ManifestUtilities.SecurityUtilities.GetPathToTool(ResourceManager resources)
at Microsoft.Build.Tasks.Deployment.ManifestUtilities.SecurityUtilities.SignPEFile(X509Certificate2 cert, Uri timestampUrl, String path, ResourceManager resources, Boolean useSha256)
at Microsoft.Build.Tasks.Deployment.ManifestUtilities.SecurityUtilities.SignFileInternal(X509Certificate2 cert, Uri timestampUrl, String path, Boolean targetFrameworkSupportsSha256, ResourceManager resources)
at Microsoft.Build.Tasks.Deployment.ManifestUtilities.SecurityUtilities.SignFile(X509Certificate2 cert, Uri timestampUrl, String path)
at Microsoft.Build.Tasks.Deployment.ManifestUtilities.SecurityUtilities.SignFile(String certThumbprint, Uri timestampUrl, String path, String targetFrameworkVersion)
at Microsoft.Build.Tasks.SignFile.Execute()
at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext()
错误正在 Microsoft.Build.Tasks.Deployment.ManifestUtilities.SecurityUtilities
的 line 195 上抛出,这是在以下方法中:
internal static string GetPathToTool()
{
string pathToDotNetFrameworkSdkFile = ToolLocationHelper.GetPathToDotNetFrameworkSdkFile(ToolName(), TargetDotNetFrameworkVersion.Version35);
if (pathToDotNetFrameworkSdkFile == null)
{
pathToDotNetFrameworkSdkFile = Path.Combine(Environment.CurrentDirectory, ToolName());
}
if (!File.Exists(pathToDotNetFrameworkSdkFile))
{
pathToDotNetFrameworkSdkFile = null;
}
return pathToDotNetFrameworkSdkFile;
}
直接原因是Environment.CurrentDirectory
返回了null
,但更突出的原因是ToolLocationHelper.GetPathToDotNetFrameworkSdkFile(ToolName(), TargetDotNetFrameworkVersion.Version35)
也返回了null
。
以上代码是 class 特定版本的唯一快照,但硬编码枚举值 TargetDotNetFrameworkVersion.Version35
告诉我问题在于 Build Tools 2015 更新3 取决于除 4.6.2 以外的 .Net SDK 版本。
更新:
为了帮助识别特定的 SDK 版本,我从 https://github.com/Microsoft/msbuild/releases 的 Update 3 版本中下载了源代码。
internal static string GetPathToTool(System.Resources.ResourceManager resources)
{
#pragma warning disable 618 // Disabling warning on using internal ToolLocationHelper API. At some point we should migrate this.
string toolPath = ToolLocationHelper.GetPathToWindowsSdkFile(ToolName, TargetDotNetFrameworkVersion.VersionLatest, VisualStudioVersion.VersionLatest);
if (toolPath == null)
toolPath = ToolLocationHelper.GetPathToWindowsSdkFile(ToolName, TargetDotNetFrameworkVersion.Version45, VisualStudioVersion.Version110);
if (toolPath == null)
toolPath = Path.Combine(ToolLocationHelper.GetPathToDotNetFrameworkSdk(TargetDotNetFrameworkVersion.Version40, VisualStudioVersion.Version100), "bin", ToolName);
if (toolPath == null)
toolPath = Path.Combine(Directory.GetCurrentDirectory(), ToolName);
if (!File.Exists(toolPath))
throw new ApplicationException(String.Format(CultureInfo.CurrentCulture, resources.GetString("SecurityUtil.SigntoolNotFound"), toolPath));
return toolPath;
#pragma warning restore 618
}
进一步研究该解决方案,我确定最新版本的构建工具(您安装的那个)不包括添加了对 Framework 4.6.2 支持的 change 到 Shared\FrameworkLocationHelper.cs
。因此,要回答您的后续问题,安装 4.6.1 SDK 应该可以解决问题。
更新 2:
OP 确定了一个替代解决方案:明确设置 TargetFrameworkSDKToolsDirectory
属性 的值,例如通过在从命令行调用 msbuild.exe
时添加 /p:TargetFrameworkSDKToolsDirectory=PATH TO SIGNTOOL.EXE(?)
作为参数。
我有一个 clickonce 解决方案,可以在安装了 VS 2015 的多台开发人员机器上运行。但是,它在我们的构建服务器上不起作用,它带有此 signFile 错误。我已经安装
- 构建工具 2015 更新 3
- .Net 4.6.2 SDK
- Windows 软件开发包
但显然 signtool.exe 的路径设置不正确。如果我禁用清单签名,它将继续,但会出现 setup.bin 丢失错误。
有人知道如何解决 SignFile 问题吗?
[_DeploymentComputeClickOnceManifestInfo] Using "SignFile" task from assembly "Microsoft.Build.Tasks.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a".
[_DeploymentComputeClickOnceManifestInfo] SignFile
[SignFile] C:\Program Files (x86)\MSBuild.0\bin\Microsoft.Common.CurrentVersion.targets(3616, 5): error MSB4018: The "SignFile" task failed unexpectedly.
System.ArgumentNullException: Value cannot be null.
Parameter name: path1
at System.IO.Path.Combine(String path1, String path2, String path3)
at Microsoft.Build.Tasks.Deployment.ManifestUtilities.SecurityUtilities.GetPathToTool(ResourceManager resources)
at Microsoft.Build.Tasks.Deployment.ManifestUtilities.SecurityUtilities.SignPEFile(X509Certificate2 cert, Uri timestampUrl, String path, ResourceManager resources, Boolean useSha256)
at Microsoft.Build.Tasks.Deployment.ManifestUtilities.SecurityUtilities.SignFileInternal(X509Certificate2 cert, Uri timestampUrl, String path, Boolean targetFrameworkSupportsSha256, ResourceManager resources)
at Microsoft.Build.Tasks.Deployment.ManifestUtilities.SecurityUtilities.SignFile(X509Certificate2 cert, Uri timestampUrl, String path)
at Microsoft.Build.Tasks.Deployment.ManifestUtilities.SecurityUtilities.SignFile(String certThumbprint, Uri timestampUrl, String path, String targetFrameworkVersion)
at Microsoft.Build.Tasks.SignFile.Execute()
at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext()
错误正在 Microsoft.Build.Tasks.Deployment.ManifestUtilities.SecurityUtilities
的 line 195 上抛出,这是在以下方法中:
internal static string GetPathToTool()
{
string pathToDotNetFrameworkSdkFile = ToolLocationHelper.GetPathToDotNetFrameworkSdkFile(ToolName(), TargetDotNetFrameworkVersion.Version35);
if (pathToDotNetFrameworkSdkFile == null)
{
pathToDotNetFrameworkSdkFile = Path.Combine(Environment.CurrentDirectory, ToolName());
}
if (!File.Exists(pathToDotNetFrameworkSdkFile))
{
pathToDotNetFrameworkSdkFile = null;
}
return pathToDotNetFrameworkSdkFile;
}
直接原因是Environment.CurrentDirectory
返回了null
,但更突出的原因是ToolLocationHelper.GetPathToDotNetFrameworkSdkFile(ToolName(), TargetDotNetFrameworkVersion.Version35)
也返回了null
。
以上代码是 class 特定版本的唯一快照,但硬编码枚举值 TargetDotNetFrameworkVersion.Version35
告诉我问题在于 Build Tools 2015 更新3 取决于除 4.6.2 以外的 .Net SDK 版本。
更新:
为了帮助识别特定的 SDK 版本,我从 https://github.com/Microsoft/msbuild/releases 的 Update 3 版本中下载了源代码。
internal static string GetPathToTool(System.Resources.ResourceManager resources)
{
#pragma warning disable 618 // Disabling warning on using internal ToolLocationHelper API. At some point we should migrate this.
string toolPath = ToolLocationHelper.GetPathToWindowsSdkFile(ToolName, TargetDotNetFrameworkVersion.VersionLatest, VisualStudioVersion.VersionLatest);
if (toolPath == null)
toolPath = ToolLocationHelper.GetPathToWindowsSdkFile(ToolName, TargetDotNetFrameworkVersion.Version45, VisualStudioVersion.Version110);
if (toolPath == null)
toolPath = Path.Combine(ToolLocationHelper.GetPathToDotNetFrameworkSdk(TargetDotNetFrameworkVersion.Version40, VisualStudioVersion.Version100), "bin", ToolName);
if (toolPath == null)
toolPath = Path.Combine(Directory.GetCurrentDirectory(), ToolName);
if (!File.Exists(toolPath))
throw new ApplicationException(String.Format(CultureInfo.CurrentCulture, resources.GetString("SecurityUtil.SigntoolNotFound"), toolPath));
return toolPath;
#pragma warning restore 618
}
进一步研究该解决方案,我确定最新版本的构建工具(您安装的那个)不包括添加了对 Framework 4.6.2 支持的 change 到 Shared\FrameworkLocationHelper.cs
。因此,要回答您的后续问题,安装 4.6.1 SDK 应该可以解决问题。
更新 2:
OP 确定了一个替代解决方案:明确设置 TargetFrameworkSDKToolsDirectory
属性 的值,例如通过在从命令行调用 msbuild.exe
时添加 /p:TargetFrameworkSDKToolsDirectory=PATH TO SIGNTOOL.EXE(?)
作为参数。