InstallShield: Dynamic File Linking

I have been using Dynamic File Linking (DFL) to keep my installation project simple by reducing the number of Components the project uses.  Unfortunately DFL is not very reliable. I have encounter undocumented problems such as the system font on the target system changes for no apparent reason. Sometime files and folders do not get removed correctly after an uninstall of the product. I have found DFL very useful for cases where the Developers added new data files to the product without letting the installer project know. With DFL, all contents get added in when the installer project is build. This method works if you DFL from the source root folder and include subfolders.

See DFL Limitation from Flexera Support page for additional information.

To fix the files left behind after uninstall, I had to create a separate Component per folder of the product. Each component uses DFL but do not include subfolders.

Calculate CPU Usage in C/C++

What you want:

You want to calculate the CPU usage during your application run?

The Problem:

There’s no simple one function call that will return the CPU usage.

The Solution:

The CPU usage is based on usage time of your CPU.  Windows API provide a way to get the system time and process time.  The usage percent is equal to the total process time divided by the total system time times one hundred.

CPU% = (100.0 * (ProcessKernelTime + ProcessUserTime))/(SystemKernelTime + SystemUserTime)

To get the system time you will need to call GetSystemTimes(), which returns the idle, kernel and user time.  This function call is supported in Windows XP or higher versions. More info here.

To get the process time you will need to call GetProcessTimes(), which returns the creation, exit, kernel, and user time given the process handle.

Notes: the source code provided was created using Visual Studio 2010 Pro on Windows 7 machine, which defined the _WIN32_WINNT macro by default.   You may need to #define _WIN32_WINNT 0×0501 before the #include <windows.h> for the GetSystemTimes() function to work on older Visual Studio version.

// CpuUsage.cpp : Defines the entry point for the console application.
//
 
#include <Windows.h>
#include "stdafx.h"
#include <iostream>
#include <iomanip>
 
using namespace std;
 
ULONGLONG subtractTime(const FILETIME &a, const FILETIME &b)
{
    LARGE_INTEGER la, lb;
    la.LowPart = a.dwLowDateTime;
    la.HighPart = a.dwHighDateTime;
    lb.LowPart = b.dwLowDateTime;
    lb.HighPart = b.dwHighDateTime;
 
    return la.QuadPart - lb.QuadPart;
}
 
float getUsage(FILETIME *prevSysKernel, FILETIME *prevSysUser,
               FILETIME *prevProcKernel, FILETIME *prevProcUser,
               bool firstRun = false)
{
    FILETIME sysIdle, sysKernel, sysUser;
    FILETIME procCreation, procExit, procKernel, procUser;    
 
    if (!GetSystemTimes(&sysIdle, &sysKernel, &sysUser) ||
        !GetProcessTimes(GetCurrentProcess(), &procCreation, &procExit, &procKernel, &procUser))
    {
        // can't get time info so return
        return -1.;
    }
 
    // check for first call
    if (firstRun)
    {
        // save time info before return
        prevSysKernel->dwLowDateTime = sysKernel.dwLowDateTime;
        prevSysKernel->dwHighDateTime = sysKernel.dwHighDateTime;
 
        prevSysUser->dwLowDateTime = sysUser.dwLowDateTime;
        prevSysUser->dwHighDateTime = sysUser.dwHighDateTime;
 
        prevProcKernel->dwLowDateTime = procKernel.dwLowDateTime;
        prevProcKernel->dwHighDateTime = procKernel.dwHighDateTime;
 
        prevProcUser->dwLowDateTime = procUser.dwLowDateTime;
        prevProcUser->dwHighDateTime = procUser.dwHighDateTime;
 
	return -1.;
    }
 
    ULONGLONG sysKernelDiff = subtractTime(sysKernel, *prevSysKernel);
    ULONGLONG sysUserDiff = subtractTime(sysUser, *prevSysUser);
 
    ULONGLONG procKernelDiff = subtractTime(procKernel, *prevProcKernel);
    ULONGLONG procUserDiff = subtractTime(procUser, *prevProcUser);
 
    ULONGLONG sysTotal = sysKernelDiff + sysUserDiff;
    ULONGLONG procTotal = procKernelDiff + procUserDiff;
 
    return (float)((100.0 * procTotal)/sysTotal);
}
 
int _tmain(int argc, _TCHAR* argv[])
{
    FILETIME prevSysKernel, prevSysUser;
    FILETIME prevProcKernel, prevProcUser;
    float usage = 0.0;
 
    // first call
    usage = getUsage(&prevSysKernel, &prevSysUser, &prevProcKernel, &prevProcUser, true);
 
    // do something to use some cpu
    for (int i=1; i<100000000; i++)
    {
        srand(i);
        int r = rand();
    }
    //wait 1 second
    Sleep(1000);
 
    // the actual cpu usage
    usage = getUsage(&prevSysKernel, &prevSysUser, &prevProcKernel, &prevProcUser);
    cout << "CPU% = " << setiosflags(ios::fixed) << setprecision(2) << usage;
 
    return 0;
}

InstallShield multiple versions installation problem

What you want:

You want to be able to install multiple versions of the same product of your software on the same machine?

The Problem:

You are getting the maintenance dialog when you tried to install another version or a message box telling you to uninstall the installed version?

The Solution:

You need to change the GUID of the Product Code, Package Code and Upgrade Code within your InstallShield project.  Also, you will need to change the GUID of every Components in  your project.   If you don’t change the GUID, you will have uninstall issues where files and shortcuts are left behind after an uninstall when multiple versions exists on the target machine.

Understanding the solution:

Product Code – this is a unique GUID that identify your product on the target machine.

Package Code – this is a unique GUID that identify your installation package.  By default, the project should always generate a new GUID for this property when you build your installation.

Upgrade Code – this is a unique GUID of an existing product that this product is an upgrade of.  If you are not doing an upgrade then always generate a new GUID for this property.

When you generate new GUIDs where a GUID is needed, this will ensured that you always have a unique product every time you build your installation.