Jump to content


This is a ready-only archive of the InstallSite Forum. You cannot post any new content here. / Dies ist ein Archiv des InstallSite Forums. Hier können keine neuen Beiträge veröffentlicht werden.
Photo

creating Component dynamicaly


7 replies to this topic

Thomas OD

Thomas OD
  • Members
  • 48 posts

Posted 30 July 2001 - 15:58

Do someone know if there is a way to create a component at runtime, reading the files in a directory for example ?
(creating the component table at runtime ? is it possible and if yes, how to do that ?)
Any idea is welcome.
Thanks,

Ian Blake

Ian Blake
  • Members
  • 483 posts

Posted 30 July 2001 - 21:52

Write a custom action to insert  temporary rows into the component and file tables.  

I have done this successfully in the admin sequence (so that setup.exe instmsia.exe instntmsiw.exe and setup.ini get copied).   I do not seee any reason this can not be done in the execute sequence.


Thomas OD

Thomas OD
  • Members
  • 48 posts

Posted 31 July 2001 - 08:24

Thanks Ian,
but could you tell me how to insert temporary row into a table? i saw function to create row,but i don't understand how to insert them in a table... I'm really new with installscript, so excuse my newbie question's
Thanks,


Ian Blake

Ian Blake
  • Members
  • 483 posts

Posted 31 July 2001 - 08:43

I do not use install scipt but this scrap of c++ code may help you.


///////////////////////////////////////////////////////////////////////////////
//
// Function    : ExectuteView
// Description :
//
///////////////////////////////////////////////////////////////////////////////
static UINT ExecuteView(
MSIHANDLE hInstaller, // Handle of installer
MSIHANDLE hInfo, // Handle of our message record
MSIHANDLE hDb, // Handle of installer database
LPSTR pQuery) // SQL Query
{
PMSIHANDLE hView;
char text[500];
UINT Result = ERROR_SUCCESS;
BOOL Once;

for (Once=TRUE; Once; Once=FALSE)
{
wsprintf(text, "SQL request = %s", pQuery);
MsiRecordSetString(hInfo, 1, text);
MsiProcessMessage(hInstaller, INSTALLMESSAGE_INFO, hInfo);

Result= MsiDatabaseOpenView(hDb, pQuery, &hView);
if (Result!=ERROR_SUCCESS)
{
if (Result==ERROR_BAD_QUERY_SYNTAX)
wsprintf(text, "Could not open view - Bad SQL Syntax");
else if (Result==ERROR_INVALID_HANDLE)
lstrcpy(text, "Could not open view - Invalid Handle");
else
wsprintf(text, "Could not open view 'Component'- Unexpected error 0x%08X", Result);
MsiRecordSetString(hInfo, 1, text);
MsiProcessMessage(hInstaller, INSTALLMESSAGE_INFO, hInfo);
Result = ERROR_INSTALL_FAILURE;
break;
}

Result = MsiViewExecute(hView, 0);
if (Result != ERROR_SUCCESS)
{
MsiRecordSetString(hInfo, 1, "Could not execute view");
MsiProcessMessage(hInstaller, INSTALLMESSAGE_INFO, hInfo);
MsiViewClose(hView);
Result = ERROR_INSTALL_FAILURE;
break;
}
} // end for Once
MsiViewClose(hView);

return Result;
}

///////////////////////////////////////////////////////////////////////////////
//
//  Function    : ExtraAdminComponent
//  Description : Add entries to the component and file table so that the
//                the file setup.exe, setup.ini, instmsiw.exe and instmsia,exe
//                are copied during an administrative installation
//
///////////////////////////////////////////////////////////////////////////////
UINT _stdcall ExtraAdminComponent(MSIHANDLE hInstaller)
{
PMSIHANDLE hDatabase;
BOOL Once;
PMSIHANDLE hInfo = MsiCreateRecord(2);
UINT Result = ERROR_SUCCESS;

MsiRecordSetString(hInfo, 0, "ExtraAdminComponent: [1]");

for (Once=TRUE; Once; Once=FALSE)
{
// Open Database
hDatabase = MsiGetActiveDatabase(hInstaller);
if (hDatabase==0)
{
MsiRecordSetString(hInfo, 1, "Could not open database");
MsiProcessMessage(hInstaller, INSTALLMESSAGE_INFO, hInfo);
Result = ERROR_INSTALL_FAILURE;
break;
}

//-----------------------------------------------------------------------
// Add an extra component
Result = ExecuteView(hInstaller, hInfo, hDatabase,
"INSERT INTO Component "
"(Component.Component,Component.ComponentId,Component.Directory_,Component.Attributes
,Component.Condition,Component.KeyPath) "
"VALUES ('ExtraComponent','{B93C9BF1-4C2D-4DD4-BB88-96927004842A}','TARGETDIR','0','1','FXXX_SETUP
.EXE') "
"TEMPORARY");
if (Result!=ERROR_SUCCESS)break;

//-----------------------------------------------------------------------
// Associate 'ExtraComponent' with our 'RequiredFiles' feature
Result = ExecuteView(hInstaller, hInfo, hDatabase,
"INSERT INTO FeatureComponents "
"(FeatureComponents.Feature_,FeatureComponents.Component_) "
"VALUES ('RequiredFiles','ExtraComponent') "
"TEMPORARY");
if (Result!=ERROR_SUCCESS)break;

//-----------------------------------------------------------------------
// Add Setup.exe to the file table
Result = ExecuteView(hInstaller, hInfo, hDatabase,
"INSERT INTO File "
"(File.File,File.Component_,File.FileName,File.FileSize,File.Sequence) "
"VALUES ('FXXX_SETUP.EXE','ExtraComponent','Setup.exe',102400,0) "
"TEMPORARY");
if (Result!=ERROR_SUCCESS)break;

//-----------------------------------------------------------------------
// Add Setup.ini to the file table
Result = ExecuteView(hInstaller, hInfo, hDatabase,
"INSERT INTO File "
"(File.File,File.Component_,File.FileName,File.FileSize,File.Sequence) "
"VALUES ('FXXX_SETUP.INI','ExtraComponent','Setup.ini',1024,0) "
"TEMPORARY");
if (Result!=ERROR_SUCCESS) break;

//-----------------------------------------------------------------------
// Add Instmsiw.exe to file table
Result = ExecuteView(hInstaller, hInfo, hDatabase,
"INSERT INTO File "
"(File.File,File.Component_,File.FileName,File.FileSize,File.Sequence) "
"VALUES ('FXXY_INSTMSIW.EXE','ExtraComponent','Instmsiw.exe',1526275,0) "
"TEMPORARY");
if (Result!=ERROR_SUCCESS) break;

//-----------------------------------------------------------------------
// Add InstMsiA.exe to the file table
Result = ExecuteView(hInstaller, hInfo, hDatabase,
"INSERT INTO File "
"(File.File,File.Component_,File.FileName,File.FileSize,File.Sequence) "
"VALUES ('FXXZ_INSTMSIA.EXE','ExtraComponent','Instmsia.exe',1513987,0) "
"TEMPORARY");
if (Result!=ERROR_SUCCESS) break;

} // end for Once

return Result;
}


Thomas OD

Thomas OD
  • Members
  • 48 posts

Posted 01 August 2001 - 09:49

thanks, i make installscript, inspired of your code, but i've got an error on uninstall, because the database is empty... Did i miss something? Is there a way to write in tables not "temporary"?
- Next, i would call a function from a dll ( CoCreateGuid) but i was unable to do this with installscript...
Is there someone who can help me please ?
Regards,

Ian Blake

Ian Blake
  • Members
  • 483 posts

Posted 01 August 2001 - 12:07

Yes it has to be temporary.  It is not possible to make permanent changes because the original/cached msi file is locked.   If you need to make a permanent change you will need to write your own setup.exe to make the changes to the file before it is executed.

You say the database is empty or do you just mean the additional component is missing? In which case just re-add it during uninstall.  

I had not thought of the uninstall update repair implications.  When MSI runs the cached copy and compares the registry info it will find it has a component that does not exist so it would not be surprising if it gets confused.

You may find it easier to take a step back and use the MoveFile table (dynamically) instead.  This should be a lot safer.  I think this may achieve what you want.


Scott Williams

Scott Williams
  • Members
  • 38 posts

Posted 08 August 2001 - 16:24

I found out the hard way about Components.  We have a web interface to our product, so I have an entire website I have to capture and create an install for.  So, I had a component for each directory of the web site, and since I didn't need to register anything (just files), I didn't put in a GUID for the ComponentID.  Well guess what, it installs, but will not uninstall without a ComponetID.

Also, if you ever update this product, you want that same ComponentID, or the Windows Installer will think it is a completely new component.

If you just need to move some files dynamically, I agree that the MoveFiles table is probably a better bet.