获取已安装的Windows Installer程序包的证书以及产品代码

时间:2015-05-23 09:41:00

标签: c# windows-installer certificate pinvoke

我有几个从MsiEnumProducts过滤的产品代码,需要获取他们分配的证书。 应该可以使用MsiOpenDatabase获取证书,但我不知道如何可靠地获取.msi文件的路径。

我更愿意避免使用外部程序集(如wix),只需要pinvoke。

1 个答案:

答案 0 :(得分:2)

给定产品代码,调用MsiGetProductInfo传递属性名称INSTALLPROPERTY_LOCALPACKAGE将返回C:\ Windows \ Installer中缓存的安装程序包的位置。

获得缓存包后,对MsiGetFileSignatureInformation的调用可以检索证书。

使用pInvoke的示例:

using System;
using System.Text;
using System.Runtime.InteropServices;

class Program
{
    [DllImport("msi.dll", CharSet = CharSet.Ansi, SetLastError = false)]
    static extern int MsiEnumProducts(int iProductIndex, StringBuilder lpProductBuf);

    [DllImport("msi.dll", CharSet = CharSet.Ansi, SetLastError = false)]
    static extern int MsiGetProductInfo(string product, string property, [Out] StringBuilder valueBuf, ref Int32 len);

    [DllImport("msi.dll", CharSet = CharSet.Ansi, SetLastError = false)]
    static extern int MsiGetFileSignatureInformation(string fileName, int flags, out IntPtr certContext, IntPtr hashData, ref int hashDataLength);

    [DllImport("Crypt32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
    static extern int CertFreeCertificateContext( IntPtr certContext );

    [DllImport("Crypt32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
    static extern int CertGetNameString(IntPtr certContext, UInt32 type, UInt32 flags, IntPtr typeParameter, StringBuilder stringValue, UInt32 stringLength );

    static void Main(string[] args)
    {
        int index = 0;
        StringBuilder productCode = new StringBuilder();
        int result = MsiEnumProducts(index, productCode);
        while (result == 0)
        {
            Console.WriteLine("{0}", productCode);

            Int32 length = 1024;
            StringBuilder fileName = new StringBuilder();
            result = MsiGetProductInfo(
                        productCode.ToString(),
                        "LocalPackage",
                        fileName,
                        ref length );
            if (result == 0)
            {
                Console.WriteLine("{0}", fileName);

                IntPtr certContext = IntPtr.Zero;
                IntPtr hashData = IntPtr.Zero;
                int hashDataLength = 0;
                result = MsiGetFileSignatureInformation(
                            fileName.ToString(),
                            0,
                            out certContext,
                            hashData,
                            ref hashDataLength);
                if ( result == 0 )
                {
                    Console.WriteLine("Got Cert");

                    StringBuilder simpleDisplayType = new StringBuilder();
                    int ok = CertGetNameString(
                                certContext,
                                4,                      // == CERT_NAME_SIMPLE_DISPLAY_TYPE
                                0,
                                IntPtr.Zero,
                                simpleDisplayType,
                                1024 );
                    if (ok != 0)
                    {
                        Console.WriteLine("{0}", simpleDisplayType);
                    }

                    CertFreeCertificateContext(certContext);
                }
            }

            ++index;
            result = MsiEnumProducts(index, productCode);
        }
    }
}