【问题标题】:How does MsiQueryProductState determine VC++ is installedMsiQueryProductState 如何判断 VC++ 是否安装
【发布时间】:2019-09-18 00:14:37
【问题描述】:

这听起来可能跑题了,但请多多包涵,因为我认为它的核心是一个编程问题。

我有一个非常旧的应用程序的安装程序,我需要在我的 Windows 8.1 PC 上安装它。安装程序会检查 Visual C++ 2005 SP 1,如果没有,它会提示您安装它,并重定向您下载它,但下载页面重定向到 Microsoft 404。

我安装了 VC++ 2005 SP 1,同时安装了 x86 和 x64。

所以,我使用 JustDecompile 反编译了安装程序,安装程序在 WinForms 中,并使用下面的代码检查 VC++ 2005 SP 1。

基本上,如果这行代码是真的,它会显示一条消息,您需要获取 VC++。

if (Form1.MsiQueryProductState("{7299052B-02A4-4627-81F2-1818DA5D550D}") != 5)

我已经阅读过它,这是在恐龙时代检查 VC++ 2005 的一种可接受的方法,但我相信上面作为产品代码的 GUID 对于 Win 8.1 不再准确,因为我得到了VC++ 2005 SP 1 直接来自 Microsoft,但仍未找到。

现在,我想弄清楚如何解决这个问题。有谁知道MsiQueryProductState 方法如何确定您是否为给定的产品代码安装了某些东西?它是否在某个地方的注册表中查找?如果是这样,我也许可以通过在注册表中伪造它来解决这个问题。

任何其他建议表示赞赏!

编辑以回答来自 cmets 的问题

从我反编译这个安装程序时可以看出,它是一个自定义的 WinForms 应用程序。这是一个EXE,而不是一个MSI。它有一个名为 Form1 的表单,其中显示了您可以安装的产品列表。您选择您想要的产品并单击“安装”按钮,然后单击“安装”按钮会调用一个首先检查 VC++ 的方法。

它使用以下代码检查 VC++,其中包含 VC++ 的硬编码产品代码。如果 MsiQueryProductStatus 的返回值 != 5,那么它会提示你必须安装 VC++,并且不会让你继续。

Form1.MsiQueryProductState("{7299052B-02A4-4627-81F2-1818DA5D550D}") != 5

Form1 是如何定义 MsiQueryProductState 的。

[DllImport("msi.dll", CharSet=CharSet.None, ExactSpelling=false)]
private static extern int MsiQueryProductState(string szProduct);

所以我需要弄清楚如何在安装了产品代码 7299052B-02A4-4627-81F2-1818DA5D550D 的情况下获得 VC++,或者我需要弄清楚如何欺骗 MsiQueryProductState 让我认为我拥有带有该产品代码的 VC++已安装。

【问题讨论】:

  • 旧安装程序是 MSI 安装程序文件吗?或者它是一个setup.exe? MSI 文件很容易调整以避免该问题。应用名称? MsiQueryProductState 从 Windows Installer 数据库中检索信息,该数据库存储在注册表中的各个位置。您不应该直接读取 Windows Installer 数据库注册表项,而应通过解释这些项的 API 来避免依赖于实现细节(而不是适当的接口)。
  • 在出发之前,让我再添加一个指向VS Runtime 2010 question 的链接。也许可以略读一下,看看你是否得到了一些进一步的指示。当您提供更多详细信息时会跟进。
  • 安装程序是一个自定义的 WinForms 应用程序,我可以通过反编译来判断它。我将编辑问题以包含更多详细信息。
  • 您是想为未来和其他人制作安装程序,还是只是为了安装它? Extracting MSI files?
  • 我主要只是想安装它,并了解如何在 Win 8.1 上安装它,以便我可以写下未来的说明。我也主要是真的想提高自己对 MsiQueryProductState 功能的工作原理的了解。对迟到的回复表示歉意,我认为您在第二条评论中提供的链接可能对了解如何更改注册表以使其看起来像安装了此特定产品代码非常有帮助。

标签: c# .net windows-installer visual-c++-2005


【解决方案1】:

注意:即使您找到绕过相关检查的方法,如果没有正确的运行时,您安装的应用程序也可能无法运行。您应该没问题,因为此运行时与潜在的版本重定向(向后兼容 2.0)并行。 Just install the latest version - 并运行 Windows 更新! (进一步的安全修复)。


虚拟设置:我想知道您是否可以制作一个将产品代码硬编码在其中的虚拟设置,然后安装它以欺骗此检查你的。这实际上是欺骗 - 没有恶意。这种方法不是很好,但比入侵注册表更可取(这在几乎所有涉及一些复杂性的情况下都会导致问题)。如果您忘记卸载它或将其安装在现有安装之上,仍然可能会出现问题。 我绝对不会将其用于大规模部署

模型:我不想过多推荐这个“解决方案”——这有点疯狂,但这里有一个模型你可以尝试使用 WiX 工具包进行调整和测试。您还可以使用其他工具制作类似的 MSI 来创建 MSI 文件。您甚至可以使用 Orca 更改一个小型 MSI 以使用您需要的产品代码并安装它 - 然后您的设置应该通过检查器。确保尚未安装 MSI - 然后卸载它 - 是的,非常疯狂,仅用于解决问题 - 以后不要使用:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
 <Product Id="{7299052B-02A4-4627-81F2-1818DA5D550D}" Name="DummyRuntime" Language="1033"
          Version="1.0.0.0" Manufacturer="Someone" UpgradeCode="GUID-HERE">
  <Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />

  <MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
  <MediaTemplate EmbedCab="yes" />

  <!-- <UIRef Id="WixUI_Mondo" /> - standard GUI removed -->
  <Feature Id="ProductFeature" Title="DummyRuntime" Level="1" />

  <Directory Id="TARGETDIR" Name="SourceDir">
   <Component Feature="ProductFeature">
    <RegistryKey Root="HKLM" Key="Software\DummyRuntime">
      <RegistryValue Name="Flag" Value="1" Type="string" KeyPath="yes" />
    </RegistryKey>
   </Component>
  </Directory>

 </Product>
</Wix>

技术说明:如果您可以找到此运行时版本的 UpgradeCode,您可以将其作为 UpgradeCode 插入并在升级表中进行版本检查如果安装了真正的运行时会阻止安装(它会通过共享相同的升级代码来检测,然后您可以将升级表配置为中止)。任何其他升级代码 GUID 都应该可以工作,因为 MsiQueryProductState 方法只检查我相信的产品代码。

【讨论】:

    猜你喜欢
    • 2012-07-09
    • 1970-01-01
    • 2013-10-26
    • 1970-01-01
    • 2010-10-28
    • 2010-09-16
    • 2012-06-25
    相关资源
    最近更新 更多