Ver todos los certificados en tarjeta inteligente

Estoy tratando de crear una secuencia de comandos para eliminar todos los certificados excepto el más reciente de cualquier tarjeta inteligente (en el lector SC en ese momento). Esto es algo que tengo la intención de poder distribuir a los usuarios finales, por lo que debería ser autosuficiente. Mi primer problema es leer los certificados en la tarjeta. No quiero afectar ningún certificado que no esté en la tarjeta inteligente, por lo que busqué una solución que lea directamente de la tarjeta, y encontré esta joya:

Cómo enumerar todos los certificados en una tarjeta inteligente (PowerShell)

Es viejo, pero parece que debería hacer lo que necesito. Realmente parece funcionar en general, pero PowerShell ISE se bloquea cuando llego a la línea:

$store = new-object System.Security.Cryptography.X509Certificates.X509Store($hwStore)

Puedo crear una tienda genérica que por defecto sea la tienda 'Mi' excluyendo el($hwStore) desde esa línea sin problemas, pero al especificar que la tienda bloquea de forma confiable mi PowerShell ISE.

Aquí está la función de ese sitio, la línea con la que tengo problemas está cerca de la parte inferior.

function Get-SCUserStore {
[string]$providerName ="Microsoft Base Smart Card Crypto Provider"
# import CrytoAPI from advapi32.dll
$signature = @"
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
[return : MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptGetProvParam(
   IntPtr hProv,
   uint dwParam,
   byte[] pbProvData,
   ref uint pdwProvDataLen, 
   uint dwFlags); 

[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
[return : MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptDestroyKey(
   IntPtr hKey);   

[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
[return : MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptAcquireContext(
   ref IntPtr hProv,
   string pszContainer,
   string pszProvider,
   uint dwProvType,
   long dwFlags);

[DllImport("advapi32.dll", CharSet=CharSet.Auto)]
[return : MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptGetUserKey(
   IntPtr hProv, 
   uint dwKeySpec,
   ref IntPtr phUserKey);

[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptGetKeyParam(
   IntPtr hKey,
   uint dwParam,
   byte[] pbData,
   ref uint pdwDataLen,
   uint dwFlags);

[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
[return : MarshalAs(UnmanagedType.Bool)]

public static extern bool CryptReleaseContext(
   IntPtr hProv,
   uint dwFlags);
"@

$CryptoAPI = Add-Type -member $signature -name advapiUtils -Namespace CryptoAPI -passthru

# set some constants for CryptoAPI
$AT_KEYEXCHANGE = 1
$AT_SIGNATURE = 2
$PROV_RSA_FULL = 1
$KP_CERTIFICATE = 26
$PP_ENUMCONTAINERS = 2
$PP_CONTAINER = 6
$PP_USER_CERTSTORE = 42
$CRYPT_FIRST = 1
$CRYPT_NEXT = 2
$CRYPT_VERIFYCONTEXT = 0xF0000000

[System.IntPtr]$hProvParent=0
$contextRet = $CryptoAPI::CryptAcquireContext([ref]$hprovParent,$null,$providerName,$PROV_RSA_FULL,$CRYPT_VERIFYCONTEXT)

[Uint32]$pdwProvDataLen = 0
[byte[]]$pbProvData = $null
$GetProvParamRet = $CryptoAPI::CryptGetProvParam($hprovParent,$PP_CONTAINER,$pbProvData,[ref]$pdwProvDataLen,0)

if($pdwProvDataLen -gt 0) 
  {
    $ProvData = new-Object byte[] $pdwProvDataLen
    $GetKeyParamRet = $CryptoAPI::CryptGetProvParam($hprovParent,$PP_CONTAINER,$ProvData,[ref]$pdwProvDataLen,0)
   }

$enc = new-object System.Text.UTF8Encoding($null)
$keyContainer = $enc.GetString($ProvData)

 write-host " The Default User Key Container:" $keyContainer

[Uint32]$pdwProvDataLen = 0
[byte[]]$pbProvData = $null
$GetProvParamRet = $CryptoAPI::CryptGetProvParam($hprovParent,$PP_USER_CERTSTORE,$pbProvData,[ref]$pdwProvDataLen,0)
if($pdwProvDataLen -gt 0) 
  {
    $ProvData = new-Object byte[] $pdwProvDataLen
    $GetKeyParamRet = $CryptoAPI::CryptGetProvParam($hprovParent,$PP_USER_CERTSTORE,$ProvData,[ref]$pdwProvDataLen,0)
    [uint32]$provdataInt = [System.BitConverter]::ToUInt32($provdata,0)
    [System.IntPtr]$hwStore = $provdataInt
   }

 $store = new-object System.Security.Cryptography.X509Certificates.X509Store($hwStore)

# release smart card
$ReleaseContextRet = $CryptoAPI::CryptReleaseContext($hprovParent,0)

return $store
}

No tengo ninguna experiencia con P / Invoke (creo que dije eso bien), por lo que no estoy seguro de cómo solucionar los comandos derivados de las cosas importadas de esa manera.

Editar: Los proveedores que están listados porcertutil -scinfo -silent son:

Microsoft Base Smart Card Crypto Provider
Microsoft Smart Card Key Storage Provider

He probado ambos en el siguiente script con el mismo resultado final. El segundo de los cuales me da caracteres cuando el script me dice cuál es mi contenedor de clave de usuario predeterminado, por lo que tengo la sensación de que no es correcto.

También probé la versión x86 de PowerShell, como lo sugirió Vesper. La aplicación no se bloquea y devuelve una tienda válida con los certificados de mi tarjeta inteligente. Ahora el problema es que no puedo enviar eso a los usuarios, porque esperar que puedan navegar a la versión x86 de PowerShell y luego ejecutar un script con él es como esperar que mi perro me haga gofres ... supongo esopodría sucede, pero lo más probable es que algo salga mal y terminaré teniendo que hacerlo yo mismo de todos modos.

Edit2: Ok, entonces supongo que forzaré esa parte del script a ejecutarse en modo x86. Publicaré una respuesta con mi código actualizado y lo aceptaré. Si @Vesper publica una respuesta sobre la cosa de 64/32 bits (espero que con un poco más de información) aceptaré su respuesta para que obtenga crédito ya que su comentario es lo que me llevó a la solución.

Respuestas a la pregunta(3)

Su respuesta a la pregunta