3

I want to achieve something similar to Inno setup - skip installation if other program is not installed

But I do have the msiexec product code (like D3AA40C4-9BFB-4640-88CE-EDC93A3703CC). So how to detect if another program is installed based on this product code?

Community
  • 1
  • 1
ElkeAusBerlin
  • 565
  • 1
  • 4
  • 18

1 Answers1

4

There is the MsiQueryProductState function for this. Here is its import with a helper function for your task:

[Code]
#IFDEF UNICODE
  #DEFINE AW "W"
#ELSE
  #DEFINE AW "A"
#ENDIF
type
  INSTALLSTATE = Longint;
const
  INSTALLSTATE_DEFAULT = 5;

function MsiQueryProductState(szProduct: string): INSTALLSTATE; 
  external 'MsiQueryProductState{#AW}@msi.dll stdcall';

function IsProductInstalled(const ProductID: string): Boolean;
begin
  Result := MsiQueryProductState(ProductID) = INSTALLSTATE_DEFAULT;
end;

And its possible usage:

if IsProductInstalled('{D3AA40C4-9BFB-4640-88CE-EDC93A3703CC}') then
  MsgBox('The product is installed.', mbInformation, MB_OK);
TLama
  • 75,147
  • 17
  • 214
  • 392
  • Thanks. INSTALLSTATE_DEFAULT was unknown so simply used '5' for it: `MsiQueryProductState(ProductID) = 5; // from msi.h` – ElkeAusBerlin Jun 17 '15 at 13:44
  • 1
    You're welcome! But no, do not do that. Don't use magical constants. One day you, or someone else will come to your script and will wonder what the heck is that 5. Sorry, it's been my [`copy paste failure`](http://stackoverflow.com/a/11172939/960757). – TLama Jun 17 '15 at 13:51
  • 3
    Just if someone else has the same problem: I always got -2 (INSTALLSTATE_INVALIDARG) as return value from MsiQueryProductState. Its important to add the `{}` to the call, so `IsProductInstalled('{696C9E52-ADB6-42C8-B6E3-026EF21D369A}')` – ElkeAusBerlin Jun 17 '15 at 14:52
  • D'oh! Yet another mistake. I'm sorry. – TLama Jun 17 '15 at 14:54