As I said in my comment this is still an issue in InstallShield 2018. Here's the workaround I came up with. I created two custom action scripts. One for translating from "0" and "1" to empty "" and "1" and another script for translating back to "0" and "1". I created custom actions TranslateChkBoxesZeroToEmptyAction and TranslateChkBoxesEmptyToZeroAction that call functions TranslateChkBoxesZeroToEmpty and TranslateChkBoxesEmptyToZero respectively.
I call TranslateChkBoxesZeroToEmptyAction In Behavior and Logic:Custom Actions and Sequences:Sequences:Installation:User Interface just after SetupCompleteSuccess and before AppSearch. I call TranslateChkBoxesEmptyToZeroAction just after MaintenanceWelcome and before SetupProgress.
So the affect is to convert "0" strings to empty"" before the dialog is opened and to convert empty "" to "0" after the dialog closes
===setup.rul====
export prototype ForceEmptyToZero(HWND, STRING);
export prototype ForceZeroToEmpty(HWND, STRING);
export prototype TranslateChkBoxesEmptyToZero(HWND);
export prototype TranslateChkBoxesZeroToEmpty(HWND);
// **********************************************************************
// function ForceEmptyToZero -- Convert "" to "0"
//
// This function must be called on each CheckBox property after closing
// the dialog that contains the checkbox. It converts empty "" string
// to "0" in order to be compatible with InstallShield logic for checkboxes.
//
// 2018Aug02jdn Created by Jon D. Newbill / www.bitworkssystems.com
// **********************************************************************
function ForceEmptyToZero(hMSI, propStr)
STRING valStr;
NUMBER strLen;
begin
strLen = 100;
MsiGetProperty(hMSI, propStr, valStr, strLen);
// If not "1" then assume false and force to "0"
if (valStr != "1") then
valStr = "0";
MsiSetProperty(hMSI, propStr, valStr);
endif;
end;
// **********************************************************************
// function ForceZeroToEmpty- Convert "0" to ""
//
// This function must be called on each CheckBox property before opening
// the dialog that contains the checkbox. It converts "0" string to
// empty "" in order to be compatible with InstallShield logic for
// checkboxes.
//
// 2018Aug02jdn Created by Jon D. Newbill / www.bitworkssystems.com
// **********************************************************************
function ForceZeroToEmpty(hMSI, propStr)
STRING valStr;
NUMBER strLen;
begin
strLen = 100;
MsiGetProperty(hMSI, propStr, valStr, strLen);
// If not "1" then assume false and force to empty string ""
if (valStr != "1") then
valStr = "";
MsiSetProperty(hMSI, propStr, valStr);
endif;
end;
// **********************************************************************
// function TranslateChkBoxesZeroToEmpty -- Convert "0" to ""
//
// This function must be called before the OptionSelection dialog is
// run. This function converts all CheckBox properties from values of
// "0" or "1" to empty string "" or "1" respectively. This is done to
// deal with an anomaly in the way InstallShield handles CheckBoxes
// assigned to properties. Checkboxes are unchecked only when
// associated property is an empty string "" and checked for any other
// non-empty string.
//
// https://mcmap.net/q/1635272/-how-to-initialize-checkbox-value-in-installshield
//
// So we must convert all "0" strings to "" empty string before the
// OptionSelection dialog runs and then convert all "" to "0" after the
// dialog closes.
//
// 2018Aug02jdn Created by Jon D. Newbill / www.bitworkssystems.com
// **********************************************************************
function TranslateChkBoxesZeroToEmpty(hMSI)
STRING valStr;
NUMBER strLen;
begin
ForceZeroToEmpty(hMSI,"TIMESTAMP");
ForceZeroToEmpty(hMSI,"HIDECAPWIN");
ForceZeroToEmpty(hMSI,"FINDVCP");
ForceZeroToEmpty(hMSI,"LCDACCEPT");
ForceZeroToEmpty(hMSI,"SERNUM");
ForceZeroToEmpty(hMSI,"TOPWIN");
ForceZeroToEmpty(hMSI,"ZOOM");
ForceZeroToEmpty(hMSI,"ACCEPTCLOSE");
end;
// **********************************************************************
// function TranslateChkBoxesEmptyToZero -- Convert "" to "0"
//
// This function must be called after the OptionSelection dialog closes.
// This function converts all CheckBox properties from values of empty
// string "" or "1" to "0" or "1" respectively. This is done to deal
// with an anomaly in the way InstallShield handles CheckBoxes assigned
// to properties. Checkboxes are unchecked only when associated
// property is an empty string "" and checked for any other non-empty
// string.
//
// https://mcmap.net/q/1635272/-how-to-initialize-checkbox-value-in-installshield
//
// So we must convert all "0" strings to "" empty string before the
// OptionSelection dialog runs and then convert all "" to "0" after the
// dialog closes.
//
// 2018Aug02jdn Created by Jon D. Newbill / www.bitworkssystems.com
// **********************************************************************
function TranslateChkBoxesEmptyToZero(hMSI)
STRING valStr;
NUMBER strLen;
begin
ForceEmptyToZero(hMSI,"TIMESTAMP");
ForceEmptyToZero(hMSI,"HIDECAPWIN");
ForceEmptyToZero(hMSI,"FINDVCP");
ForceEmptyToZero(hMSI,"LCDACCEPT");
ForceEmptyToZero(hMSI,"SERNUM");
ForceEmptyToZero(hMSI,"TOPWIN");
ForceEmptyToZero(hMSI,"ZOOM");
ForceEmptyToZero(hMSI,"ACCEPTCLOSE");
end;
FROM MICROSOFT LINK:
"This CheckBox_control is a two-state check box. To associate an integer or string property with this control, enter the property name into the Property column of the Control table. The selected state of the box sets the property either to the value specified in the Value column of the CheckBox table or to the initial value of the property specified in the Property table. If the property has no initial value, the checked state sets it to 1. The unselected state sets the property to null."
The terminology is confusing. What do they mean by "The selected state"? Do they mean the "Checked state"? And then it says it sets to EITHER the Value column or the initial [default] property value. Well which is it? It can't be both. From my experience the CHECKED state sets to the Value field of the CheckBox properties table and the UNCHECKED state always sets property to empty string "". The above text also fails to describe how the initial display state of the CHECKBOX is defined from the associated property by non-empty string = CHECKED and empty string = UNCHECKED. It only describes the action of setting the property on closing of dialog window.