This website uses cookies. By clicking Accept, you consent to the use of cookies. Click Here to learn more about how we use cookies.
Turn on suggestions
Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.
- Revenera Community
- :
- InstallShield
- :
- InstallShield Forum
- :
- Re: Populate Combobox dynamically with values from file
Subscribe
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Subscribe
- Mute
- Printer Friendly Page
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Jun 12, 2009
04:43 AM
Populate Combobox dynamically with values from file
Hi
In my Basic MSI project i have a combobox (could also be a listbox) that i would like to populate with items that are read in from a already existing file with a certain format. However, i only manage to populate the combobox via the InstallShield wizard, which - unfortunately - does fullfill the requirements..
Is there a way to populate the combobox items using a file (custom actions, events, etc....)? Any help is greatly appreciated.
Thanks in advance
Daniel
In my Basic MSI project i have a combobox (could also be a listbox) that i would like to populate with items that are read in from a already existing file with a certain format. However, i only manage to populate the combobox via the InstallShield wizard, which - unfortunately - does fullfill the requirements..
Is there a way to populate the combobox items using a file (custom actions, events, etc....)? Any help is greatly appreciated.
Thanks in advance
Daniel
(7) Replies
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Jun 12, 2009
03:42 PM
As far as the populating goes, please see the help topic "Windows Installer API Functions Example" for an example in InstallScript. (You'll find VBScript examples in the tips & tricks archive, and C examples here and there.) You should be able to mix in your file-reading code with that...
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Jun 12, 2009
04:17 PM
Are you having problems with opening a file, loading a combo, or both?
At a quick glance, there are methods called OpenFile() and GetLine().
There are also methods called ListCreate(STRINGLIST) & ListAddItem() to add them to a the list var, then use CtrlSetList() to set the values to a combobox.
It would look something like this:
szExampleFile = "Readme.txt";
szExampleDir = "C:\\Tester";
OpenFileMode (FILE_MODE_NORMAL);
if (OpenFile (nvFileHandle, szExampleDir, szExampleFile) < 0) then
MessageBox ("OpenFile failed.", SEVERE);
abort;
endif;
listID = ListCreate(STRINGLIST);
if (listID = LIST_NULL) then
MessageBox ("Unable to create list.", SEVERE);
abort;
endif;
while GetLine (nvFileHandle, svLine) = 0
ListAddString (listID, svLine, AFTER);
endwhile;
nResult = CtrlSetList (szDialogName, RES_DIALOG_COMBOBOX, listID);
ListDestroy (listID);
Hope that helps.
At a quick glance, there are methods called OpenFile() and GetLine().
There are also methods called ListCreate(STRINGLIST) & ListAddItem() to add them to a the list var, then use CtrlSetList() to set the values to a combobox.
It would look something like this:
szExampleFile = "Readme.txt";
szExampleDir = "C:\\Tester";
OpenFileMode (FILE_MODE_NORMAL);
if (OpenFile (nvFileHandle, szExampleDir, szExampleFile) < 0) then
MessageBox ("OpenFile failed.", SEVERE);
abort;
endif;
listID = ListCreate(STRINGLIST);
if (listID = LIST_NULL) then
MessageBox ("Unable to create list.", SEVERE);
abort;
endif;
while GetLine (nvFileHandle, svLine) = 0
ListAddString (listID, svLine, AFTER);
endwhile;
nResult = CtrlSetList (szDialogName, RES_DIALOG_COMBOBOX, listID);
ListDestroy (listID);
Hope that helps.
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Jun 12, 2009
05:05 PM
(Actually, going down that road, ListReadFromFile might be better.)
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Jun 12, 2009
05:07 PM
That sounds like a winner.. So many API's.. I can't keep up.
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Jun 15, 2009
04:42 AM
Thanks a lot for your replies. I have not yet found the time to include anything in my project. My initial goal was to have everything coded in C#, however, if this impossible i will resort to installScript.
Greetings
Greetings
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Jun 17, 2009
06:52 AM
Hi
i found a solution that works for me and populates that combobox in standard msi dialog. It makes use of an external dll to read in the file values. The crucial code parts are to be found in the function: AddListBoxRecord
#include "ifx.h"
// public functions
export prototype TestFillCombobox(HWND);
// helper functions
prototype string ReturnSupportFileDir(HWND); // returns location of current support file (dont use SUPPORTDIR or GetSupportDir function
prototype LoadInstallAssist( BOOL, HWND );
prototype InstallAssistError( SHORT, STRING, STRING );
prototype AddListBoxRecord(STRING, INT, STRING, STRING, HWND) ;
// external DLL's -----------------------------------------------------------
// InstallAssist
prototype CDECL SHORT InstallAssist.InstallAssist.GetNumberOfEntries();();
prototype CDECL SHORT InstallAssist.GetLanguageDescription( INT, BYREF
#define PROPERTY "LANGUAGEPROPERTY" // must comply with the property set for the combobox we want to set
function TestFillCombobox(hMSI)
//================================================================
STRING szLangName, szIdDotNet, szDllName, szHelpFileName, szHelpLangIdDotNet; // we only need szLangName, the rest is to comply with dll interface
NUMBER nResult;
SHORT nsResult, nReturn, nsNumberOfLanguages;
INT iCount;
STRING szQuery;
HWND hDataBase, hView;
begin
LoadInstallAssist(TRUE,hMSI); // via external dll we read the file that resides in the same folder as the InstallAssists dll ( // szFileName = ReturnSupportFileDir(hMSI) ^ "TestLanguageFile.TXT")
nsNumberOfLanguages = InstallAssist.GetNumberOfEntries();
// prepare access to msi db
szQuery = "SELECT * FROM ComboBox WHERE Property ='"+PROPERTY +"'";
hDataBase = MsiGetActiveDatabase(hMSI);
if(!hDataBase) then
return ERROR_INSTALL_FAILURE;
endif;
nReturn = MsiDatabaseOpenView(hDataBase, szQuery, hView);
if(nReturn != ERROR_SUCCESS) then
MsiCloseHandle(hDataBase);
return ERROR_INSTALL_FAILURE;
endif;
// now fill combobox
for iCount = 0 to ( nsNumberOfLanguages - 1 )
nsResult = InstallAssist.GetLanguageDescription( iCount, szLangName, szIdDotNet, szDllName, szHelpFileName, szHelpLangIdDotNet );
// MessageBox (szLangName, INFORMATION );
if ( nsResult = 0 ) then
InstallAssistError ( nsResult, "DialogEnterLanguage, GetLanguageDescription", "SEVERE" );
else
// add it to list
AddListBoxRecord(PROPERTY, iCount+1, szLangName, szLangName, hView);
endif;
endfor;
LoadInstallAssist(FALSE,hMSI);
end;
function string ReturnSupportFileDir(hMSI)
string supportDir;
number buffer;
begin
buffer=256;
MsiGetProperty(hMSI, "SUPPORTDIR", supportDir, buffer);
return supportDir;
end;
// helper functions
function LoadInstallAssist( bLoadIt, hMSI )
//===================================
begin
// MessageBox( SUPPORTDIR , SEVERE) ; //fails because files are not yet copied to support folder!!
// MessageBox( GetSupportDir() , SEVERE) ; //fails because files are not yet copied to support folder!! GetSupportDir();
// MessageBox( ReturnSupportFileDir(hMSI) ^ "InstallAssist.dll", SEVERE) ; // is ok
if bLoadIt then
if ( UseDLL ( ReturnSupportFileDir(hMSI) ^ "InstallAssist.dll" ) != 0 ) then
MessageBox ( @STR_CANNOT_LOAD_INSTALLASSIST_DLL, SEVERE );
abort;
endif;
else
UnUseDLL ( ReturnSupportFileDir(hMSI) ^ "InstallAssist.dll" );
endif;
end;
function InstallAssistError( nsResult, szFunction, szMessageType )
//================================================================
STRING szResult, szMsg;
begin
Sprintf (szMsg, @STR_INSTALLASSIST_ERROR, nsResult, szFunction);
if szMessageType = "Severe" then
MessageBox ( szMsg + @STR_INSTALLASSIST_MUST_EXIT, SEVERE );
abort;
elseif szMessageType = "Warning" then
MessageBox ( szMsg, WARNING );
else
MessageBox ( szMsg, INFORMATION );
endif;
end;
function AddListBoxRecord(szProperty, nOrder, szValue, szText, hView)
NUMBER nReturn;
HWND hRecord;
begin
hRecord = MsiCreateRecord(4);
if(!hRecord) then
return ERROR_INSTALL_FAILURE;
endif;
MsiRecordSetString(hRecord, 1, szProperty);
MsiRecordSetInteger(hRecord, 2, nOrder);
MsiRecordSetString(hRecord, 3, szValue);
MsiRecordSetString(hRecord, 4, szText);
nReturn = MsiViewModify(hView, MSIMODIFY_INSERT_TEMPORARY, hRecord);
if(nReturn != ERROR_SUCCESS) then
MsiCloseHandle(hRecord);
return ERROR_INSTALL_FAILURE;
endif;
MsiCloseHandle(hRecord);
return ERROR_SUCCESS;
end;
i found a solution that works for me and populates that combobox in standard msi dialog. It makes use of an external dll to read in the file values. The crucial code parts are to be found in the function: AddListBoxRecord
#include "ifx.h"
// public functions
export prototype TestFillCombobox(HWND);
// helper functions
prototype string ReturnSupportFileDir(HWND); // returns location of current support file (dont use SUPPORTDIR or GetSupportDir function
prototype LoadInstallAssist( BOOL, HWND );
prototype InstallAssistError( SHORT, STRING, STRING );
prototype AddListBoxRecord(STRING, INT, STRING, STRING, HWND) ;
// external DLL's -----------------------------------------------------------
// InstallAssist
prototype CDECL SHORT InstallAssist.InstallAssist.GetNumberOfEntries();();
prototype CDECL SHORT InstallAssist.GetLanguageDescription( INT, BYREF
#define PROPERTY "LANGUAGEPROPERTY" // must comply with the property set for the combobox we want to set
function TestFillCombobox(hMSI)
//================================================================
STRING szLangName, szIdDotNet, szDllName, szHelpFileName, szHelpLangIdDotNet; // we only need szLangName, the rest is to comply with dll interface
NUMBER nResult;
SHORT nsResult, nReturn, nsNumberOfLanguages;
INT iCount;
STRING szQuery;
HWND hDataBase, hView;
begin
LoadInstallAssist(TRUE,hMSI); // via external dll we read the file that resides in the same folder as the InstallAssists dll ( // szFileName = ReturnSupportFileDir(hMSI) ^ "TestLanguageFile.TXT")
nsNumberOfLanguages = InstallAssist.GetNumberOfEntries();
// prepare access to msi db
szQuery = "SELECT * FROM ComboBox WHERE Property ='"+PROPERTY +"'";
hDataBase = MsiGetActiveDatabase(hMSI);
if(!hDataBase) then
return ERROR_INSTALL_FAILURE;
endif;
nReturn = MsiDatabaseOpenView(hDataBase, szQuery, hView);
if(nReturn != ERROR_SUCCESS) then
MsiCloseHandle(hDataBase);
return ERROR_INSTALL_FAILURE;
endif;
// now fill combobox
for iCount = 0 to ( nsNumberOfLanguages - 1 )
nsResult = InstallAssist.GetLanguageDescription( iCount, szLangName, szIdDotNet, szDllName, szHelpFileName, szHelpLangIdDotNet );
// MessageBox (szLangName, INFORMATION );
if ( nsResult = 0 ) then
InstallAssistError ( nsResult, "DialogEnterLanguage, GetLanguageDescription", "SEVERE" );
else
// add it to list
AddListBoxRecord(PROPERTY, iCount+1, szLangName, szLangName, hView);
endif;
endfor;
LoadInstallAssist(FALSE,hMSI);
end;
function string ReturnSupportFileDir(hMSI)
string supportDir;
number buffer;
begin
buffer=256;
MsiGetProperty(hMSI, "SUPPORTDIR", supportDir, buffer);
return supportDir;
end;
// helper functions
function LoadInstallAssist( bLoadIt, hMSI )
//===================================
begin
// MessageBox( SUPPORTDIR , SEVERE) ; //fails because files are not yet copied to support folder!!
// MessageBox( GetSupportDir() , SEVERE) ; //fails because files are not yet copied to support folder!! GetSupportDir();
// MessageBox( ReturnSupportFileDir(hMSI) ^ "InstallAssist.dll", SEVERE) ; // is ok
if bLoadIt then
if ( UseDLL ( ReturnSupportFileDir(hMSI) ^ "InstallAssist.dll" ) != 0 ) then
MessageBox ( @STR_CANNOT_LOAD_INSTALLASSIST_DLL, SEVERE );
abort;
endif;
else
UnUseDLL ( ReturnSupportFileDir(hMSI) ^ "InstallAssist.dll" );
endif;
end;
function InstallAssistError( nsResult, szFunction, szMessageType )
//================================================================
STRING szResult, szMsg;
begin
Sprintf (szMsg, @STR_INSTALLASSIST_ERROR, nsResult, szFunction);
if szMessageType = "Severe" then
MessageBox ( szMsg + @STR_INSTALLASSIST_MUST_EXIT, SEVERE );
abort;
elseif szMessageType = "Warning" then
MessageBox ( szMsg, WARNING );
else
MessageBox ( szMsg, INFORMATION );
endif;
end;
function AddListBoxRecord(szProperty, nOrder, szValue, szText, hView)
NUMBER nReturn;
HWND hRecord;
begin
hRecord = MsiCreateRecord(4);
if(!hRecord) then
return ERROR_INSTALL_FAILURE;
endif;
MsiRecordSetString(hRecord, 1, szProperty);
MsiRecordSetInteger(hRecord, 2, nOrder);
MsiRecordSetString(hRecord, 3, szValue);
MsiRecordSetString(hRecord, 4, szText);
nReturn = MsiViewModify(hView, MSIMODIFY_INSERT_TEMPORARY, hRecord);
if(nReturn != ERROR_SUCCESS) then
MsiCloseHandle(hRecord);
return ERROR_INSTALL_FAILURE;
endif;
MsiCloseHandle(hRecord);
return ERROR_SUCCESS;
end;
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Jun 17, 2009
07:01 AM
I also found a vb solution. Be aware that this is for a msi project using msi dialogs (and not some created using installScript):
Function GetNetworkDrives()
Set objInstaller = Session.Installer
Set objDB = Session.Database
Set objView = objDB.OpenView("SELECT * FROM `ComboBox` WHERE `Property` = 'TESTPROPERTY'")
objView.Execute
j = GetStartingIndex(objView)
Set objRec = objInstaller.CreateRecord(4)
Set WshNetwork = CreateObject("WScript.Network")
Set objDrives = WshNetwork.EnumNetworkDrives
Const ForReading = 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.OpenTextFile _
("C:\InstallShield 2009 Projects\FilesForFillDialogTestProject\TESTFILE.TXT", ForReading)
Do Until objTextFile.AtEndOfStream
strNextLine = objTextFile.Readline
strTrimmed = Trim(strNextLine)
If Not strTrimmed = "" Then ' we dont handle empty strings
objRec.StringData(1) = "TESTPROPERTY"
objRec.IntegerData(2) = j
objRec.StringData(3) = CStr(j)
objRec.StringData(4) = strTrimmed
objView.Modify 7, objRec
objRec.ClearData
j = j + 1
END If
Loop
End Function
Function GetStartingIndex(view)
' The index will never be less than 1
j = 1
' We need to loop through the view to make sure
' that there are not any existing records
' for our particualr property
' There is no way to get the number of records
' in a view except to loop through the view
' and increment a counter
Do
Set rec = view.Fetch
j = j + 1
Loop Until rec Is Nothing
GetStartingIndex = j
End Function
I hope this may be of use to somebody.
I still would be glad if someone found a way to do this things in C#, but i believe this is not (yet) possible. I welcome any better solutions, remarks, suggestions.
Greetings
Function GetNetworkDrives()
Set objInstaller = Session.Installer
Set objDB = Session.Database
Set objView = objDB.OpenView("SELECT * FROM `ComboBox` WHERE `Property` = 'TESTPROPERTY'")
objView.Execute
j = GetStartingIndex(objView)
Set objRec = objInstaller.CreateRecord(4)
Set WshNetwork = CreateObject("WScript.Network")
Set objDrives = WshNetwork.EnumNetworkDrives
Const ForReading = 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.OpenTextFile _
("C:\InstallShield 2009 Projects\FilesForFillDialogTestProject\TESTFILE.TXT", ForReading)
Do Until objTextFile.AtEndOfStream
strNextLine = objTextFile.Readline
strTrimmed = Trim(strNextLine)
If Not strTrimmed = "" Then ' we dont handle empty strings
objRec.StringData(1) = "TESTPROPERTY"
objRec.IntegerData(2) = j
objRec.StringData(3) = CStr(j)
objRec.StringData(4) = strTrimmed
objView.Modify 7, objRec
objRec.ClearData
j = j + 1
END If
Loop
End Function
Function GetStartingIndex(view)
' The index will never be less than 1
j = 1
' We need to loop through the view to make sure
' that there are not any existing records
' for our particualr property
' There is no way to get the number of records
' in a view except to loop through the view
' and increment a counter
Do
Set rec = view.Fetch
j = j + 1
Loop Until rec Is Nothing
GetStartingIndex = j
End Function
I hope this may be of use to somebody.
I still would be glad if someone found a way to do this things in C#, but i believe this is not (yet) possible. I welcome any better solutions, remarks, suggestions.
Greetings
