Showing posts with label hacks. Show all posts
Showing posts with label hacks. Show all posts

Thursday, April 30, 2009

InstallShield Progress Bar

This ones been bothering me for a while and theres never been a great solution...UNTIL NOW.

The Problem: You create an Installer with InstallShield and add custom VBS actions to the execute sequence only to find out that the progress bar thingy doesnt move while they are being executed. This can cause users to think nothings happening possibly making them go insanse and smash the computer.

Resolution: Make the progress bar move.

Problem with Resolution: Cant figure it out. Every example I saw was using C++ code or whatever. This was no good.

Final Solution: Make the progress bar move using AutoIt

These are the exact steps I took:

1) Download AutoIt if you dont already have it. What you need is the ActiveX control.

2) Include this as a support file in your project

3) This one is optional but I know of no other way to do it.
Create an InstallScript Function to retrieve SUPPORTDIR and set your own property to this value. The reason is the InstallShield SUPPORTDIR and the MSI SupportDir are two different things.

If you retrieve SUPPORTDIR from a vbs custom action it will be a support dir created for that action only, it will not contain the support files. [InstallShield: Why not rename it to something else?]

But if you retrieve SUPPORTDIR with MSIGetProperty from an IS Function then set it to like MY_SUPPORT dir then you can retrieve that from a vbs. Mine looks like this:

function SetSupportDir(hMSI)
STRING strSupportDir;
NUMBER nLength;
begin
MsiGetProperty(hMSI, "SUPPORTDIR", strSupportDir, nLength);
MsiSetProperty(hMSI, "P_SUPPORTDIR", strSupportDir);
end;

4) In any event you need to RegSvr32 the AutoIT Control (in the supportdir from step 3) at the beginning of the install. I simply added this to the UI sequence before the Welcome Screen. There you have access to the AutoIt library.

5) Then you want to add some controls to the SetupProgress dialog that look like a progress bar, I used a combination of 2 bitmaps, one was all white and Sunken=True to make the background the other was all blue and not sunken to be the actual moving bar

Important: CREATE THE BACKGROUND ONE FIRST, if not you will never get the ZOrder right on the controls and youll never be able to see the bar. Once they are in place over the existing ProgressBar control, move the progressbar to the front so it covers them.

6) Once you have it all set up nice you need to add the VB code to move it. Mine looks like this:

Function ProgressBar()
strSilent = Session.Property("P_IS_SILENT")
If strSilent = "0" Then

Set oAutoIt = CreateObject("AutoItX3.Control")
'Hide the Progress Bar
oAutoIt.ControlHide "PRODUCT- InstallShield Wizard","","[CLASS:msctls_progress32;]"
'Make the new one visible
oAutoIt.ControlShow "PRODUCT - InstallShield Wizard","","[CLASS:Static;Instance:2;]"

'Find its coordinates and height
x = oAutoIt.ControlGetPosX("PRODUCT- InstallShield Wizard","","[CLASS:Static;Instance:2;]")
y = oAutoIt.ControlGetPosy("PRODUCT - InstallShield Wizard","","[CLASS:Static;Instance:2;]")
height = oAutoIt.ControlGetPosHeight("PRODUCT - InstallShield Wizard","","[CLASS:Static;Instance:2;]")

'Increment the bar
For width = 1 to 359
oAutoIt.ControlMove "PRODUCT- InstallShield Wizard","","[CLASS:Static;Instance:2;]",x,y,width,height
'Slow it down a bit
oAutoIt.Sleep(25)
Next
end if
End Function

The instance numbers may differ for you but once you figure them out they will always be constant as long as you dont add anything to the form. So i suggest getting this working last.

Believe me I know this is a complete hack but it works and no one could tell it was different.

Can also use this same method to update other dialogs. For instance giving them feedback about inputs etc. Which before now I always did with a popup.