使用提升的Start-Process运行时,Certutil.exe错误退出代码

时间:2015-09-22 13:02:41

标签: powershell certutil

我正在尝试使用脚本导入带有certutil.exe的证书。此脚本是由非管理员用户启动的,当达到Start-Process命令时,Windows UAC会要求提供管理员凭据。

$cmd="certutil.exe -addstore TrustedPeople C:\some_path\myCertif.cer"
$ret = Start-Process powershell -Verb RunAs -ArgumentList $cmd -Wait -PassThru
当我运行此代码时,

$ret.exitCode等于1,并且在商店中找不到证书。

但是,如果我在没有-ArgumentList的情况下运行Start-Process(然后打开PowerShell窗口),并从此处运行certutil.exe命令,我没有收到任何错误,并且证书已按预期添加到商店

区别在哪里?

1 个答案:

答案 0 :(得分:2)

在第一种情况下,您会出错:您调用PowerShell的新实例并传递$cmd字符串,该字符串不代表Powershell的有效输入。

你调用:

powershell.exe certutil.exe -addstore TrustedPeople C:\some_path\myCertif.cer

虽然PowerShell期望输入如下:

powershell.exe .\somescript.ps1

powershell.exe -Command 'some_command'

powershell.exe -EncodedCommand 'base64_command'

......等等......

在第二种情况下,您只需启动一个新的PowerShell升级实例,然后可以成功导入证书。

要从PowerShell导入证书,我建议根据您的示例提供三种解决方案:

1)直接使用certutil.exe

$arguments = '-addstore TrustedPeople C:\some_path\myCertif.cer'
$ret = Start-Process 'certutil.exe' -Verb RunAs -ArgumentList $arguments -Wait -PassThru

2)如果由于某种原因(以防万一)你想要调用另一个PowerShell实例,你可以使用Command这样的选项:

$cmd = 'certutil.exe -addstore TrustedPeople C:\some_path\myCertif.cer'
$ret = Start-Process 'powershell.exe' -Verb RunAs -ArgumentList "-Command $cmd" -Wait -PassThru

3)最后为了完整起见,您可以使用EncodedCommand

$cmd = 'certutil.exe -addstore TrustedPeople C:\some_path\myCertif.cer'
$bytes = [Text.Encoding]::Unicode.GetBytes($cmd)
$encodedCommand = [Convert]::ToBase64String($bytes)
$ret = Start-Process 'powershell.exe' -Verb RunAs -ArgumentList "-EncodedCommand $encodedCommand" -Wait -PassThru

同样在我的测试环境(使用PowerShell v.2的Windows 7 Enterprise x64)中,在使用非提升权限运行脚本时,我无法使用certutil.exe cmdlet实际获得Start-Process返回代码。我使用.Net函数来解决这个问题:

$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = 'certutil.exe'
$pinfo.UseShellExecute = $true
$pinfo.Verb = 'runas'
$pinfo.Arguments = '-addstore TrustedPeople C:\some_path\myCertif.cer'

$p = New-Object System.Diagnostics.Process
$p.StartInfo = $pinfo
$p.Start() | Out-Null
$p.WaitForExit()
Write-Host $p.ExitCode

我希望你能得到你想要的东西!