2

This might sound off topic, but bear with me please because I think it's a programming question at its core.

I have an installer for a really old application that I need to get installed on my Windows 8.1 PC. The installer does a check for Visual C++ 2005 SP 1, and if you don't have it, it prompts you to install it, and it redirects you to download it, except that download page redirects to a Microsoft 404.

I have VC++ 2005 SP 1 installed with both x86 and x64.

So, I decompiled the installer using JustDecompile, and the installer was in WinForms and used this code below to check for VC++ 2005 SP 1.

Basically if this line of code was true, it would show a message that you need to get VC++.

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

I've read about it and that was an acceptable way to check for VC++ 2005 in the time of the dinosaurs, but I believe that GUID above which is a product code is no longer accurate for Win 8.1 because I've gotten VC++ 2005 SP 1 directly from Microsoft and it's still not finding it.

Now, I'd like to figure out how to work around this problem. Does anyone know how the method MsiQueryProductState determines if you have something installed for a given product code? Does it look in the registry somewhere? If so, I could maybe work around this by faking it in the registry or something.

Any other suggestions appreciated!

Edit to answer questions from comments

From what I can tell when I decompiled this installer, it's a custom WinForms application. It's an EXE, not an MSI. It has a single form named Form1, which displays a list of products you can install. You select which products you want and click the Install button, and on clicking the Install button it calls a method that first checks for VC++.

It checks for VC++ with the following code, which has a hard coded product code for VC++. If the return value of MsiQueryProductStatus != 5, then it prompts you that you have to install VC++ and won't let you continue.

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

And here's how Form1 defines MsiQueryProductState.

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

So I need to figure out either how to get VC++ with the product code 7299052B-02A4-4627-81F2-1818DA5D550D installed, or else I need to figure out how to trick MsiQueryProductState into thinking I have the VC++ with that product code installed.

Jim
  • 6,753
  • 12
  • 44
  • 72
  • Is the old installer an MSI installer file? Or is it a setup.exe? An MSI file is easy to tweak to avoid the problem. Application name? [MsiQueryProductState](https://learn.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msiqueryproductstatea) retrieves information from the Windows Installer database which is stored in the registry in various places. You should not read Windows Installer database registry keys directly, but go via the APIs that interpret those keys - in order to avoid depending on implementation details (rather than proper interfaces). – Stein Åsmul Sep 18 '19 at 00:56
  • Before heading off, let me add one more link to a [VS Runtime 2010 question](https://stackoverflow.com/a/53639128/129130). Maybe have a skim to see if you get some further pointers. Will follow up when you provide some more details. – Stein Åsmul Sep 18 '19 at 01:04
  • The installer is a custom WinForms application from what I can tell by decompiling it. I'll edit the question to include a few more details. – Jim Sep 18 '19 at 11:39
  • Are you trying to make an installer for the future and for others or just to get this installed? [Extracting MSI files](https://stackoverflow.com/questions/1547809/extract-msi-from-exe/24987512#24987512)? – Stein Åsmul Sep 18 '19 at 14:40
  • I'm mainly just trying to get this installed, and understand how to get it installed on Win 8.1 so that I can write up the instructions for the future. I'm also mainly just really wanting to improve my own knowledge of the workings of this MsiQueryProductState feature. Apologies for the late reply, I think the link you gave in your second comment might prove to be very helpful in finding out how I can make a registry change to make it look like I have this specific product code installed. – Jim Sep 19 '19 at 15:21
  • Suggest you eliminate the use of this launcher and remake it as a **`WiX bundle`** or something. They can chain together several **`MSI`** / **`EXE`** / **`MSP`** / or other types of packages in sequence and make a **`setup.exe`** out of it. Go standard whenever you can is my motto. – Stein Åsmul Sep 19 '19 at 19:59
  • I appreciate all the suggestions and feedback. Just to put some closure on this, I ended up finding someone who had a link to the correct VC++ installer with the product code that my installer was looking for. It was only available on web.archive.org, Microsoft doesn't host it anymore. Installing that very specific version of vcredist_x86.exe fixed my problem. – Jim Oct 03 '19 at 17:37
  • Please run windows update! That version might have flaws of caliber security wise! – Stein Åsmul Oct 03 '19 at 17:38

1 Answers1

1

Note: Even when you find a way to bypass the check in question, the applications you install could fail to run without the correct runtime. You should be fine since this runtime is side-by-side with potential version redirection (backwards compatible 2.0). Just install the latest version - and run Windows Update! (further security fixes).


Dummy Setup: I wonder if you could make a dummy setup that has that product code hard coded in it, and then install it as a way to fool this check of yours. This is in effect spoofing - without malice. This approach is not great, but would be preferable to hacking the registry (which causes problems in almost all cases involving some complexity). Problems can still result if you forget to uninstall it or install it on top of an existing installation. I would definitely not use this for large scale deployment.

Mock-Up: I don't want to recommend this "solution" too much - it is kind of crazy, but here is a mock-up you can try to adapt and test using the WiX toolkit. You can also make a similar MSI using other tools to create MSI files. You could even just change a small MSI - using Orca - to use the product code you need and install it - then your setup should pass the checker. Make sure that MSI is not already installed - and uninstall it afterwards - yes, all quite mad and only to be used to remove the problem - not to use going forward:

<?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>

Technical Note: If you could find the UpgradeCode for this version of the runtime, you could insert that as the UpgradeCode and make a version check in the Upgrade table that would prevent installation if the real runtime is installed (it would be detected by sharing the same upgrade code, and then you can configure the upgrade table to abort). Any other upgrade code GUID should work since the MsiQueryProductState method just checks product code I believe.

Stein Åsmul
  • 39,960
  • 25
  • 91
  • 164