why does $store.Open($openFlags)
throw an exception, and is there a better way than my "work around" to make it work?
<#
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store("Cert:\CurrentUser\My")
$openFlags = [System.Security.Cryptography.X509Certificates.OpenFlags]::MaxAllowed
$store.Open($openFlags) #Exception calling "Open" with "1" argument(s): "The parameter is incorrect.
#>
#Work Around:
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store("Cert:\CurrentUser\My")
$openFlags = [System.Security.Cryptography.X509Certificates.OpenFlags]::MaxAllowed
$startIndexOfStoreName = $store.Name.LastIndexOf("\") + 1
$lengthOfStoreName = $store.Name.Length - $startIndexOfStoreName
$storeNameString = $store.Name.Substring($startIndexOfStoreName, $lengthOfStoreName)
$storeName = [System.Security.Cryptography.X509Certificates.StoreName]$storeNameString
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store($storeName, $store.Location)
$store.Open($openFlags) #No Exception thrown!
Update: Seems as though when using the X509Store(String) constructor, you are NOT allowed to have any slashes (correct me if I'm wrong). So $store = New-Object System.Security.Cryptography.X509Certificates.X509Store("My")
works.
Define you certificate store using
$store = Get-Item "Cert:\CurrentUser\My"
instead of
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store("Cert:\CurrentUser\My")
To be honest I'm still trying to figure out why it works, or how.
The first method returns a $store called "My", so I'm assuming that it targets the store specifically and you can open it with
$store.Open($openFlags)
The second method returns a $store called "Cert:\\CurrentUser\\My". Open method on this will fail.
I wanted to comment on this, since, as is already pointed out, "the mixing of .NET Framework and the use of PowerShell Providers" in the previous examples. For me, I needed this to work as a pure .NET way of getting the certs to test out some C# equivalent code without the full development environment on a users computer.
Here's what I came up with, which worked:
$Location = [Security.Cryptography.X509Certificates.StoreLocation]::CurrentUser
$StoreName = [Security.Cryptography.X509Certificates.StoreName]::My
$Store = New-Object System.Security.Cryptography.X509Certificates.X509Store -ArgumentList $StoreName, $Location
$OpenFlags = [System.Security.Cryptography.X509Certificates.OpenFlags]::ReadOnly
$Store.Open($OpenFlags)
$Store.Certificates
Actually, you are mixing methods. One is via a provider (Cert:) the other is a .Net type (X509Store). Very different processes for attaching to the cert stores and pulling cert details.
Think of "Cert:" like a PSDrive (which it basically is). So you can get-childitem, etc. and don't need to "open" the store. In this mindset, the cert store locations are folders, and certs are individual objects:
# List the store locations
gci Cert:\
# List store names in CurrentUser store location
gci Cert:\CurrentUser
# List certs in the My store of CurrentUser store location
gci Cert:\CurrentUser\My | format-list
The catch to using the Cert: provider is that if you want to work with certs on remote systems, remoting (WinRM) needs to be enabled so you can "Invoke-Command". Not every environment allows this. That is where the .Net X509Store comes in. Not sure how well it works with "CurrentUser", but I've never been concerned about that - I am more interested in what is in the "LocalMachine" stores (specifically "My" since that is where the system holds web and auth certs). Modified snippet to list these certs (pulled from a script I built for interrogating all the servers in SharePoint farms).
# Change as necessary
$strTarget = $env:computername
$strCertStoreLocation = 'LocalMachine'
$strCertStoreName = 'My'
# Set up store parameters, connect and open store
[System.Security.Cryptography.X509Certificates.StoreLocation]$strStoreLoc = [String]$strCertStoreLocation
[System.Security.Cryptography.X509Certificates.StoreName]$strStoreName = [String]$strCertStoreName
$objCertStore = New-Object System.Security.Cryptography.X509Certificates.X509Store -ArgumentList "\\$($strTarget)\$($strStoreName)", $strStoreLoc
$objCertStore.Open('ReadOnly')
# List cert details in bulk
$objCertStore.Certificates | Format-List
# List specific props
foreach ($Cert in $objCertStore.Certificates) {
"Subject: $($Cert.Subject)"
"Issuer: $($Cert.Issuer)"
"Issued: $($Cert.NotBefore)"
"Expires: $($Cert.NotAfter)"
""
}
For a bit more details about each, hit up your favorite tech repository (MSDN, PowerShell.org, Hey Scripting Guy, etc.) :)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.