3
votes

We use InstallShield 2008 for our product installation. Product consists of several components. When a component is installed, a batch-file with some post-install routines specific to this component is executed.

The problem: post-install batch files use some environment variables that are set during the installation of the product through InstallScript. But it seems that batch-files can't see immediate changes in registry (and newly created environment variables).

Is there a way to accomplish installation without a system reboot?

Potentially useful information: target system - Windows XP, currently logged in user is in Administrators group.

2
When the installer creates variables it likely creates them in the registry and not in its own process. When it spawns the batch file cmd inherits the caller's environment, namely the Installer's that didn't change. Admittedly, that's a bit poor design for an installer. - Joey

2 Answers

4
votes

I had the same problem with an earlier version of InstallShield. Here's the way I solved it (quick and dirty code).

#define HWND_BROADCAST          0xffff
#define WM_SETTINGCHANGE        0x001A
function UpdateEnvironmentVariable(szKey, szValue)
  NUMBER nResult;
  STRING szEnv;
  POINTER pEnv;
begin
  nResult = RegDBSetKeyValueEx(szKey, "PATH", REGDB_STRING, szValue, -1);

  szEnv = "Environment";                    
  pEnv = &szEnv;                  
  SendMessage (HWND_BROADCAST, WM_SETTINGCHANGE, 0, pEnv );
end;

The key is to use SendMessage. Hope it helps.

1
votes

InstallShield users using InstallShield 2010 or later.

Important: The InstallScript Engine has changed since Version 2010 for Unicode.

So using POINTER pEnv; will no longer work. You must use WPOINTER pEnv; instead. I personally use InstallShield 2013 and everything I found suggested the "POINTER approach", but this a piece of legacy code that does not translate to later versions.

I use the following InstallScript function in InstallShield 2013:

// Flush the NT registry to all applications.
function RefreshEnvironment()
    STRING szEnv;
    WPOINTER pEnv;
begin     
    szEnv = "Environment";
    pEnv = &szEnv;
    SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, pEnv);
end;

And for my defines I use:

// defines
#define WM_SETTINGCHANGE 0x001A
#define HWND_BROADCAST 0xffff

So the key here is broadcast WM_SETTINGCHANGE to all top-level windows. This way they are aware that a system-wide change has been made.