C# 获取产品代码为的已安装Windows Installer软件包的证书
我有几个产品代码从MsiEnumProducts中筛选出来,需要获得分配给它们的证书。 使用MsiOpenDatabase应该可以获得证书,但我不知道如何可靠地获得.msi文件的路径C# 获取产品代码为的已安装Windows Installer软件包的证书,c#,windows-installer,certificate,pinvoke,C#,Windows Installer,Certificate,Pinvoke,我有几个产品代码从MsiEnumProducts中筛选出来,需要获得分配给它们的证书。 使用MsiOpenDatabase应该可以获得证书,但我不知道如何可靠地获得.msi文件的路径 我希望避免使用外部程序集(如wix),而只使用pinvoke。给定产品代码,调用传递属性名称INSTALLPROPERTY\u LOCALPACKAGE将返回缓存的安装程序包在C:\Windows\installer中的位置 拥有缓存包后,调用可以检索证书 使用pInvoke的示例: using System; u
我希望避免使用外部程序集(如wix),而只使用pinvoke。给定产品代码,调用传递属性名称INSTALLPROPERTY\u LOCALPACKAGE将返回缓存的安装程序包在C:\Windows\installer中的位置 拥有缓存包后,调用可以检索证书 使用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);
}
}
}
我认为MSIAPI中没有任何东西可以做到这一点。大概您已经了解了如何在C:\Windows\Installer中获取缓存MSI的路径。您需要一些其他API来检查应用于此文件的证书。请注意,在Windows 7之前版本上,证书将无效,因为Windows在删除嵌入式CAB时修改了该文件。我相信,如果安装是从原始MSI中提取的文件运行的,则证书也将丢失。我不确定这是否会影响MSIDgitalSignature表及其关联表。只需找到一个签名的MSI文件,运行一个管理员映像并检查表。