C# 在Sn.exe中自动输入密码
我需要创建生成后事件以执行以下操作:C# 在Sn.exe中自动输入密码,c#,signing,sn.exe,C#,Signing,Sn.exe,我需要创建生成后事件以执行以下操作: sn -i MyKey.pfx MyKeyContainerName tlbimp $(ConfigurationName)\MyCom.tlb /out:$(ConfigurationName)\NETMyCom.dll /keycontainer:MyKeyContainerName sn -d MyKeyContainerName 当VisualStudio执行第1条语句时,它需要密码,并等待用户指定密码后失败 Microsoft(R).NET框架强
sn -i MyKey.pfx MyKeyContainerName
tlbimp $(ConfigurationName)\MyCom.tlb /out:$(ConfigurationName)\NETMyCom.dll /keycontainer:MyKeyContainerName
sn -d MyKeyContainerName
当VisualStudio执行第1条语句时,它需要密码,并等待用户指定密码后失败
Microsoft(R).NET框架强大
名称实用程序版本2.0.50727.42
版权所有(c)微软公司。
版权所有
输入PKCS#12键的密码
文件:无法解析PKCS#12
mykey.pfx中的blob——句柄是
无效
我试图使用sn命令行参数指定密码,但找不到方法
请帮忙
问候,,
Hilmi.如果像我一样,您没有使用TFS或MSBUILD进行构建,那么至少还有两种其他方法: a)从脚本运行sn.exe,并将密码写入stdin 有关C#示例,请参见: 注意:对于.NET4版本的sn.exe,似乎不可能将其作为外部进程执行(至少在Windows XP上是这样),也不可能将密码写入stdin(我用python+和C#进行了尝试,sn.exe似乎只是在不等待密码输入的情况下退出) b)使用已安装的pfx,使用sn.exe重新签署密码。 如果您已经安装了pfx文件,那么您可能知道容器名称(通常VisualStudio使用类似VS_KEY_abab1234; abab1234的名称) 如果像我一样,您不知道或不记得容器名称,则只需重新安装pfx文件:
sn -i myPfxFile VS_KEY_ABAB1234ABAB1234
sn.exe将在pfx文件中安装证书时提示您输入密码
然后,您可以使sn.exe对程序集重新签名,而无需提示输入密码:
sn -Rca myAssembly.dll myVSkey
上述内容可以在构建脚本中使用,因为不需要交互:-)
注意:请记住检查签名是否有效:
sn -v myAssembly.dll
我今天遇到这个问题,我用了C++DLL,在CLIKONC C++应用程序中使用。 我在DLL上设置了延迟签名,然后使用生成后事件运行SN,如下所示:
ECHO <your-password-here> | sn.exe -R $(OutDir)$(TargetFileName) $(MSBuildProjectDirectory)<path-to-pfx-file>
ECHO | sn.exe-R$(OutDir)$(TargetFileName)$(MSBuildProjectDirectory)
我一定喜欢老式的批量生产方法ECHO
打印您的密码,管道|
将输出到SN.exe,它接受密码
你可能不会像我那样需要延迟签名和-R开关,但你明白了
编辑:这可能不再有效-我的答案是2013年的,当时我正在使用VS2010 我已经研究了差不多两天了。我尝试了旧版本的sn.exe(最早可以追溯到2.0!),但我无法让
echo密码
技巧发挥作用
最后,我做到了:
[void] [System.Reflection.Assembly]::LoadWithPartialName("'System.Windows.Forms")
Start-Process "C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\sn.exe " -ArgumentList "-i
`"Certificate.pfx`" VS_KEY_XXXXXXX" -NoNewWindow -Wait
[System.Windows.Forms.SendKeys]::SendWait("PASSWORDHERE~")
将密钥发送到当前激活的窗口。由于我们正在使用带有SendWait()
修饰符的-nonewindow
启动Start Process
sn.exe,因此我们的窗口已经聚焦
是一个特殊字符,表示回车按钮~
也可以,但这是键盘上numpad附近的ENTER按钮。可能没什么区别,但我只是想确定一下{ENTER}
AppActivate()
,因为-nonewindow
更新:使用
-Wait
参数时效果更好 我需要将其自动化并找到这个问题。下面的答案(非常感谢@Thomas Rijsewijk)我已经写了我的版本:
# Start the sn.exe process
Start-Process $SnExePath -ArgumentList "-i $PfxCertificatePath $LocalContainerName" -NoNewWindow
# Wait for the process to start
Start-Sleep 2
# This workaround allows to forward the password to the standard input
[void] [System.Reflection.Assembly]::LoadWithPartialName("'System.Windows.Forms")
[System.Windows.Forms.SendKeys]::SendWait("$($PfxCertificatePassword){ENTER}")
Start-Sleep 2
# This ENTER is to return from the sn.exe process
[System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
使用
启动进程
命令的-Wait
开关并没有解决问题,因为PS脚本正在等待sn.exe进程终止,然后再将密码转发给它。经过长时间的调查,我可以为各种自动化环境(如Azure devops)运行sn.ex。我的代码在这里:
Start-Process cmd.exe
Sleep 3
$WshShell = New-Object -ComObject WScript.Shell
Sleep 3
$WshShell.sendkeys(".\sn.exe -i $PfxCertificatePath VS_KEY_10D1C85C6387479B{Enter}");
Sleep 3;
$WshShell.sendkeys("**password**{Enter}");
Sleep 3;
$WshShell.sendkeys("{Enter}");
不幸的是,这里提到的任何方法都不适用于我。我必须在docker容器中注册几个PFX 所以我重新开发了
sn.exe-i
命令在C#中使用。源和应用程序位于GitHub上的
这个项目
该应用程序接受PFX密钥及其密码。它自动(借用MSBuild源代码)计算密钥容器名称(VS_key_*),并将其安装到强名称CSP
用法:
SnInstallPfx.exe <pfx_infile> <pfx_password>
SnInstallPfx.exe
使用WinAPI,我们可以这样做:
Param(
[string] $Password ,
[string] $CertFilePath
)
function ExecuteCommand([string]$message)
{
try{
foreach ($char in [char[]]$message) {
[void][WPIA.ConsoleUtils]::PostMessage($handle, [WPIA.ConsoleUtils]::WM_CHAR, [int]$char, 0)
}
[void][WPIA.ConsoleUtils]::PostMessage($handle, [WPIA.ConsoleUtils]::WM_CHAR, 13, 0)
Sleep 3
}catch{
}
}
Add-Type -Name ConsoleUtils -Namespace WPIA -MemberDefinition @'
[DllImport("user32.dll")]
public static extern int PostMessage(int hWnd, uint Msg, int wParam, int lParam);
public const int WM_CHAR = 0x0102;
'@
$Win32API = Add-Type -Name Funcs -Namespace Win32 -PassThru -MemberDefinition @'
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindow(string lpClassName, IntPtr lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindow(IntPtr lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);
[DllImport("kernel32.dll")]
public static extern uint GetLastError();
'@
[System.Reflection.Assembly]::Load("Microsoft.Build.Tasks.v4.0, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
[System.Reflection.Assembly]::Load("Microsoft.Build.Utilities.v4.0, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
$publish = New-Object Microsoft.Build.Tasks.ResolveKeySource
$publish.KeyFile=$CertFilePath
try
{
$publish.Execute()
}
catch{
$VsKey= [regex]::match($error[0].Exception,'VS_KEY_[A-F0-9]+').Value
$VsKey =$VsKey -replace "`n|`r"
}
$quotedCertPath='"'+$CertFilePath+'"'
Write-Host 'VsKey='$VsKey
start cmd
$proc=Get-Process | Where-Object {$_.Name -like "*cmd*"}
$proc.MainWindowTitle
$handle = $proc.MainWindowHandle
'1:'+$handle
if($handle -eq 0){
$handle=$Win32API::FindWindow([IntPtr]::Zero, 'C:\WINDOWS\system32\cmd.exe')
'2:'+$handle
}
if($handle -eq 0){
$handle=$Win32API::FindWindow('C:\WINDOWS\system32\cmd.exe', [IntPtr]::Zero)
'3:'+$handle
}
if($handle -eq 0){
$proc2 = Start-Process cmd.exe -PassThru
$proc2
Get-Process -id $proc2.Id
Sleep 3;
$handle = (Get-Process -id $proc2.Id).MainWindowHandle
$handle
$proc.MainWindowHandle
$proc.Refresh()
Sleep 3;
$proc.MainWindowHandle
}
Write-Host 'Handle='$handle
ExecuteCommand 'echo Starting > d:\a\1\s\Authenticode\log.txt'
$SnCommand=[string]::Format(".\sn.exe -i {0} {1}",$quotedCertPath,$VsKey)
ExecuteCommand $SnCommand
ExecuteCommand $Password
有什么原因不能使用VisualStudio自己的密钥签名功能吗?(检查项目的属性。)还有一件非常重要的事情需要知道,我现在才想起:如果您将此命令放入批处理文件中,并且您的密码包含一个
%
符号,则需要使用其中两个。如果您的密码是super%cool%guy
,则只需在批处理文件中使用super%%cool%%guy
。这个想法很好,但不适用于批处理文件sn.exe
不接受控制台输入重定向,并抱怨如下:控制台输入可能无法重定向密码输入
。有没有办法在批处理文件中实现这一点?我对此没有异议。您可以发布批处理文件内容吗?(我几年前就这么做了,也许最新的SN.exe不允许这样做)这是我的。试图在变量中设置密码并将其导入sn
命令,但没有成功:(你可能是对的。它在一个旧得多的SN.exe上工作,他们可能认为管道输入存在安全风险。谢谢你!非常有用。太好了,谢谢你的反馈!我已经更新了应用程序的cmdln参数。你可以选择传递容器名称。你简直是一个救世主。与cmd标准管道相同的错误,输入无法重做。)反恐执行局