我正在尝试运行Powershell脚本以从C#应用程序内部创建和操作证书。我正在使用https://github.com/PowerShell/PowerShell/tree/master/docs/host-powershell的Powershell Github存储库中描述的库,可以访问在其中运行脚本的Powershell环境。
脚本如下:
$derPath = "C:\Certs\derRootCert.cer";
$cert = New-SelfSignedCertificate -Type Custom -KeySpec Signature -Subject "CN=P2SRootCert" -KeyExportPolicy Exportable -HashAlgorithm sha256 -KeyLength 2048 -CertStoreLocation "Cert:\CurrentUser\My" -KeyUsageProperty Sign -KeyUsage CertSign;
New-SelfSignedCertificate -Type Custom -DnsName P2SChildCert -KeySpec Signature -Subject "CN=P2SChildCert" -KeyExportPolicy Exportable -HashAlgorithm sha256 -KeyLength 2048 -CertStoreLocation "Cert:\CurrentUser\My" -Signer $cert -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.2");
Export-Certificate -FilePath $derPath -Type CERT -NoClobber -Cert $cert;
如果我自己在Powershell控制台中运行此脚本,则可以正常工作,并且我看到文件输出到该目录。
但是,如果我在以下C#中运行它,则不会看到创建的文件:
using (var ps = PowerShell.Create()) {
ps.AddScript(stringContainingScript).Invoke();
}
为什么在此托管上下文中运行时不写入文件,我该怎么做才能使其按预期显示?
谢谢!
编辑: 在评论的建议下,我查看了错误流并找到以下消息:
“ New-SelfSignedCertificate”一词不被识别为 cmdlet,函数,脚本文件或可操作程序。检查 名称的拼写,或者如果包含路径,请验证路径 是正确的,然后重试。
这引起了一个相关的问题-为什么非高架式PowerShell窗口能够找到该cmdlet,而我的托管控制台却无法找到该cmdlet?
答案 0 :(得分:0)
最终,我走上了另一条路。在探究为何无法使用New-SelfSignedCertificate时,我尝试在脚本的开头明确添加“ Import-Module pki”。这产生了另一个错误:
模块 'C:\ WINDOWS \ system32 \ WindowsPowerShell \ v1.0 \ Modules \ pki \ pki.psd1'确实 不支持当前的PowerShell版本“ Core”。受支持的版本 是“桌面”。使用“导入模块-SkipEditionCheck”忽略 该模块的兼容性。
因此,我修改了导入以添加-SkipEditionCheck以查看会发生什么。这次我有很多非特定的异常,表明各种模块无法加载。
我朝另一个方向前进。由于我的脚本不会将任何内容写到控制台,而只是将我的证书写到目录,因此我开始将脚本从程序中写到临时文件中,然后将Powershell作为进程启动,将脚本位置放入参数中,然后在继续处理脚本之前对其进行一些清理,如下所示:
var fileName = Path.GetFileNameWithoutExtension(Path.GetTempFileName()) + ".ps1";
var tempFile = Path.Combine(Path.GetTempPath(), fileName);
var sb = new StringBuilder();
//Build the script
using (var sw = new StreamWriter(tempFile)) {
sw.Write(sb.ToString());
}
var pi = new ProcessStartInfo("powershell.exe", $"-File {tempFile}") {
CreateNoWindow = true,
UseShellExecute = false
};
var p = Process.Start(pi);
p.WaitForExit();
var errorLevel = process.ExitCode; //If 0, the script ran without errors
p.Close()
File.Delete(tempFile);