我正在开发自己的.NET应用程序以供私有企业使用,通过HTTP通过ClickOnce分发。我遇到的一个难题是SmartScreenFilter(内置于Win 8/10)干扰了更新。每次更新后,都需要管理员权限(密码)才能首次运行更新的应用程序。
参考这些链接 - Link1,Link2 - 以及一些试验和错误,我能够绕过SmartScreenFilter。
Essentialy我必须创建自签名的可信证书来签署我的应用程序,然后在首次运行时安装这些证书。现在没有远离它,但由于自签名证书,新机器将需要管理员权限(您实际上需要输入密码3次)。但对于企业用途,无论如何“你”自己设置机器并安装应用程序,这没关系。
详细信息在答案中:
答案 0 :(得分:0)
第1步:创建自签名证书
1)我们需要其中两个。第一个是证书颁发机构,第二个是用于签署应用程序的实际证书。有关更多信息,请参阅 Link2 。我使用了以下命令:
(以管理员身份打开Visual Studio Developer命令提示符)
makecert -sv c:\users\Marko\Desktop\CA.pvk -pe -r -n "CN=My Certificate Authority" -sky signature -a sha512 -e 12/31/2099 -cy authority -ss My -sr LocalMachine c:\users\Marko\Desktop\CA.cer
makecert -sv c:\users\Marko\Desktop\cert.pvk -ss My -sr Localmachine -pe -n "CN=MyPublisherName" -eku "1.3.6.1.5.5.7.3.3,1.3.6.1.4.1.311.10.3.13" -sky signature -a sha512 -e 12/31/2099 -in "My Certificate Authority" -is My -ir LocalMachine c:\users\Marko\Desktop\cert.cer
cert2spc c:\Users\Marko\Desktop\cert.cer c:\Users\Marko\Desktop\cert.spc
pvk2pfx -pvk c:\Users\Marko\Desktop\cert.pvk -pi mypassword -spc c:\users\Marko\Desktop\cert.spc -pfx c:\users\Marko\Desktop\cert.pfx -po mypassword
确保对所有密码提示使用相同的mypassword
。还可以在这些命令中相应地修改文件夹路径。
第2步:签署您的应用程序集,清单和.exe
在Visual Studio中,将 cert.pfx 文件导入/添加到您的解决方案中。转到项目属性 - > 签名标签。勾选Sign the ClickOnce manifests
复选框并使用cert.pfx文件进行签名(Select from file
按钮)。然后勾选Sign the assembly
复选框并从组合框中选择cert.pfx文件。
参考 Link1 ,添加一个Post-Build任务来签署.exe。我选择Post-Build选项,因为它是最简单的,我也没有任何问题,如'{3}}所描述的'签名哈希不匹配清单'。我在Visual Studio中使用了以下命令项目属性 - > 构建活动标签 - > 制作后部分:
"C:\Program Files (x86)\Windows Kits\10\bin\x64\signtool.exe" sign /f "$(ProjectDir)cert.pfx" /p mypassword /v "$(ProjectDir)obj\$(ConfigurationName)\$(TargetFileName)"
步骤3:首次运行导入证书绕过SmartScreenFilter
这是关键部分。我们需要将证书导入Local Machine\Root
和Local Machine\TrustedPublisher
商店。首先,将 CA.cer 和 cert.cer 文件添加到解决方案中。将构建操作设置为Content
,将复制到输出目录设置为Copy if newer
。然后在项目属性下 - > Pulish 标签 - > 应用程序文件按钮 - > (勾选Show all files
)将.cer文件设置为Publish Status = Data File
。
对于实际导入,我在Window_Loaded()事件处理程序中调用了PowerShell:
if (MyApp.Properties.Settings.Default.FirstRun) // I used a custom project setting called 'FirstRun'
{
try
{
using (System.Diagnostics.Process prcs = new System.Diagnostics.Process()) // import certificates
{
var dir = (ApplicationDeployment.IsNetworkDeployed ? ApplicationDeployment.CurrentDeployment.DataDirectory :
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location));
var filePath = System.IO.Path.Combine(dir, "CA.cer");
var filePath2 = System.IO.Path.Combine(dir, "cert.cer");
prcs.StartInfo.Verb = "runas";
prcs.StartInfo.FileName = "powershell.exe";
prcs.StartInfo.Arguments = "Import-Certificate -Filepath '" + filePath + "' -CertStoreLocation cert:\\LocalMachine\\Root;" +
"Import-Certificate -Filepath '" + filePath + "' -CertStoreLocation cert:\\LocalMachine\\TrustedPublisher;" +
"Import-Certificate -Filepath '" + filePath2 + "' -CertStoreLocation cert:\\LocalMachine\\Root;" +
"Import-Certificate -Filepath '" + filePath2 + "' -CertStoreLocation cert:\\LocalMachine\\TrustedPublisher";
prcs.Start();
prcs.WaitForExit();
}
MyApp.Properties.Settings.Default.FirstRun = false;
MyApp.Properties.Settings.Default.Save();
}
catch (Exception ex) // if you cancel the UAC dialog for instance
{
MessageBox.Show(ex.ToString());
this.Close();
}
}
最终结果:
在Win 10下,标准本地用户帐户 如果我去了我的应用程序的已发布URL(here),请单击“安装”按钮,下载Setup.exe。 Edge当然会警告,这个文件通常不会下载=无论如何都要运行。
第一次密码提示=运行setup.exe(SmartScreenFilter干扰)
第二个密码提示=运行已安装的应用程序(SmartScreenFilter干扰)
第三个密码提示=以管理员身份运行PowerShell。
但是,如果我现在发布我的应用程序的新版本,然后没有更多的密码提示,应用程序会更新并在没有SmartScreenFilter干扰的情况下运行:)
最后说明:
尽管cert.cer现在受到信任,但简单地导入CA.cer并没有帮助。但是导入CA.cer和cert.cer都没有。