.NET 3.5 を使用しています。
X509Certificate への参照を作成するときにメモリ リークが発生します。結果を分析するために ANTS プロファイラーを使用していますが、プライベート バイトが増加している一方で、ヒープ内のバイトは静的なままです (アンマネージ コードによるメモリ リークであることを示しています)。
CRYPT32 dll を使用して証明書を管理しています。内部ポインター (intptr) であるストア ハンドルを取得するために、証明書ストアへの参照を開きます。次に、このストア ハンドラーを使用して、ストア (ローカルに保存) 内の証明書を検索します。証明書を取得したら、証明書ストアを閉じて、証明書を呼び出し元のプログラムに返します。クローズストアが呼び出された後、開いているリソースを開いたままにする certclosestore でフラグ 0 を使用しています。ここで言及されているように、これがメモリリークの原因であると思います: http://msdn.microsoft.com/en-us/library/ms937035.aspx
ただし、閉じるフラグを次のように変更すると:
CertCloseStore(storeHandle, 2)
これにより、割り当てられたリソースが解放されるはずです。ただし、サービスが爆破されるだけです。
アプリケーションは、証明書などを検証するという意味で機能します。唯一の問題は、メモリ使用量が徐々に増加し、サービスを毎週かそこらで再起動する必要があることです。どんなアイデアや考えでも大歓迎です。
public static X509Certificate CreateFromRegistry(string certificateIdent)
{
X509Certificate certificate = null;
IntPtr storeHandle = CertificateStore.CertOpenStore(CERT_STORE_PROV_SYSTEM,
0, 0,CERT_SYSTEM_STORE_LOCAL_MACHINE, "MY");;
certificate = new X509Certificate(CertificateStore.
FindCertInStore(certificateIdent, storeHandle));
CertificateStore.CertCloseStore(storeHandle, 0);
return certificate;
}
public class CertificateStore
{
const int CERT_STORE_PROV_SYSTEM = 10;
private static int CERT_SYSTEM_STORE_LOCAL_MACHINE = (2 << 16);
const uint PKCS_7_ASN_ENCODING = 0x00010000;
const uint X509_ASN_ENCODING = 0x00000001;
const uint CERT_FIND_SUBJECT_STR = 0x00080007;
const uint CERT_FIND_ISSUER_STR = 0x00080004;
static uint MY_ENCODING_TYPE = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING;
[DllImport("CRYPT32", EntryPoint = "CertOpenStore",
CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr CertOpenStore(
int storeProvider, int encodingType,
int hcryptProv, int flags, string pvPara);
[DllImport("CRYPT32", EntryPoint = "CertCloseStore",
CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool CertCloseStore(
IntPtr storeProvider,
int flags);
}
public static X509Certificate FindCertInStore
(string trustedRootIssuerName, IntPtr storeHandle)
{
IntPtr hCertCntxt;
X509Certificate theActualCertificate = null;
if (storeHandle != IntPtr.Zero)
{
hCertCntxt = CertFindCertificateInStore(
storeHandle,
MY_ENCODING_TYPE,
0,
CERT_FIND_ISSUER_STR,
trustedRootIssuerName,
IntPtr.Zero);
if (hCertCntxt != IntPtr.Zero)
{
theActualCertificate = new X509Certificate(hCertCntxt);
}
}
return theActualCertificate;
}