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

Read cached MST file during major upgrade to preserve shortcut command


Best Answer Berto , 29 September 2015 - 15:07

Hi, this is very helpful. I was not aware of the existence of the "QueryProgItem" function ... this way i can make the implementation a lot easier. Great tip! Thx again

I can have function "FindAllFiles" look for the "*.lnk" files on the desktop and AllPrograms folder and use QueryProgItem to compare the command line with the exe name of my application to find a match.

 

In the meantime I managed to get my own implementation working. I'll just briefly explain the solution if anyone would be interested:

Using InstallScript I wanted to apply a transform (.MST file) to a copy of my cached MSI file so i could read the localized names of the shortcuts from the MSI's Shortcut table

The problem was that function "MsiDatabaseApplyTransform" did not seem to be working. According to the MSDN installer doc, it can not be used in a custom action.

It says "This function cannot be called from custom actions. A call to this function from a custom action causes the function to fail."

However using the Windows Installer COM object seems to be working, so I implement something like this:

 

try
set objObject1 = CoCreateObject("WindowsInstaller.Installer");
set objObject2 = objObject1.OpenDatabase(szCachedMSI,1);
objObject2.ApplyTransform(szTransformFile,0);
objObject2.Commit();
catch
MessageBox("ERROR",SEVERE);
endcatch;

 

That seems to work fine. Next, use functions like MsiOpenDatabase, MsiDatabaseOpenView, MsiViewExecute, MsiViewFetch & MsiRecordGetString to read the table you want from the transformed MSI.

 

Krgds

Berto

Go to the full post


4 replies to this topic

Berto

Berto
  • Full Members
  • 8 posts

Posted 24 September 2015 - 17:09

Hi,

 

The basic msi we're using is getting translated into 12 languages. This means that "shortcut" names to our binaries (the lnk files) will have different names depended on the language chosen for installation. Furthermore: We only do major upgrades. This is not a new project. We have about 8 versions in the field reaching thousands of customers since 2007.

 

The problem: when we do a major upgrade, I need to find back the currently installed shortcuts. This is to preserve the command line parameters so i can put them back once the upgrade is (nearly) finished. 

 

Example:

Shortcut = when i install for the first time, and would pick "Dutch", my shortcut = "Mijn Applicatie" (file will be "Mijn Applicatie.lnk")

However, when i do an upgrade and decide to change the language to e.g. English, the shortcut will be "My Application" (file will be "My Application.lnk")

 

Now: I was planning to read the localized name from the cached msi but found out that the String table is not part of an msi. Also the Shortcut table is not having the localized name ... it has the name of the shorcut in the language that is set default in the dev environment (and that's not Dutch).

 

So ... I guess that the only place left to find that localized name is in the transform stored in the windows installer directory (in the subdirectory with the <ProductCode> of the base install)

 

Question: Is there any way that i can read that MST content? I tried applying that MST to the cached MSI using "MsiDatabaseApplyTransform" via an InstallScript custom action ... but seems this is not allowed. Or is there some other way i could get to that info?

 

Thx

Berto

 

 

 

 

 

 



deramor

deramor
  • Full Members
  • 187 posts

Posted 24 September 2015 - 18:01

Berto,

 

I have not used localized settings for multi languages before but in your example, you mention an update selecting english and wanting to preserve the Dutch shortcuts.  Shouldn't the latest user selection take precidence over a prior one?  The user should know what language they want.  If that means shortcut names change, I would think that is expected and desired behavior.



Berto

Berto
  • Full Members
  • 8 posts

Posted 25 September 2015 - 09:47

Thx Deramor.

 

My apologies, i guess i did not explain very well. I'll try to clarify: I do not want to preserve the Dutch shortcut name ... i want to preserve the shortcut command line parameters.

Customers change these parameters to get customized logon settings.

 

Example:

After a clean install in Dutch, there's a shortcut on the desktop pointing to some exe with the shortcut name "Mijn Applicatie" and command line parameter "U=Admin"

Now ... a customer can change the command line parameters after the installation so the app will start up with other credentials .... e.g. he/she might have changed it to "U=DonaldDuck"

 

If we now would do a major upgrade (and we would choose "English" as language") the major upgrade would first remove the existing Dutch shortcut "Mijn Applicatie" and put back the English version ("My Application"). That's ok since the user choose to change the language to English ... but the command line parameters are also reset to "U=Admin" while the whole idea is to preserver "U=DonaldDuck".

 

Hence why I'm trying to find that Dutch shortcut name during the UI of a major upgrade to put aside the command line parameters. But ... the installer has no idea how the Dutch shortcut is called since the user selected "English" for the upgrade. Therefore I need to get to the Dutch transform file  (and maybe also the cached msi on the disk) somehow to be able to retrieve the name of the Dutch shortcut so i can find it on the desktop and read/store the command line parameters temporarily for later (I'll put them back at the end of the major upgrade). I'm trying to accomplish this through InstallScript custom actions in a basic msi.

 

Hm ... hope this clarifies the issue a bit better

 

Thanks



deramor

deramor
  • Full Members
  • 187 posts

Posted 25 September 2015 - 18:48

That clarifies things.  Fundimentally, the issue is the installer is ignoring user data.  I don't see a way to stop this from happening.  Rather than looking through a transform, would you be against having a CA that reads all the installed shortcuts, saves the command line data, then writes them back after the upgrade has happened?  Look at the IS help for QueryProgItem.

 

You might want to generate a list of start menu entries, iterate through them, and save them off to some sort of CustomActionData property.  The tricky part will be to get the order correct or to somehow save the order in the property.

 

I have only ever saved single variables in CustomActionData and not lists of data.   There is the good way which can handle a variable number of shortcuts or the more direct way of just knowing how many shortcuts there are and asking for them by name.



Berto

Berto
  • Full Members
  • 8 posts

Posted 29 September 2015 - 15:07   Best Answer

Hi, this is very helpful. I was not aware of the existence of the "QueryProgItem" function ... this way i can make the implementation a lot easier. Great tip! Thx again

I can have function "FindAllFiles" look for the "*.lnk" files on the desktop and AllPrograms folder and use QueryProgItem to compare the command line with the exe name of my application to find a match.

 

In the meantime I managed to get my own implementation working. I'll just briefly explain the solution if anyone would be interested:

Using InstallScript I wanted to apply a transform (.MST file) to a copy of my cached MSI file so i could read the localized names of the shortcuts from the MSI's Shortcut table

The problem was that function "MsiDatabaseApplyTransform" did not seem to be working. According to the MSDN installer doc, it can not be used in a custom action.

It says "This function cannot be called from custom actions. A call to this function from a custom action causes the function to fail."

However using the Windows Installer COM object seems to be working, so I implement something like this:

 

try
set objObject1 = CoCreateObject("WindowsInstaller.Installer");
set objObject2 = objObject1.OpenDatabase(szCachedMSI,1);
objObject2.ApplyTransform(szTransformFile,0);
objObject2.Commit();
catch
MessageBox("ERROR",SEVERE);
endcatch;

 

That seems to work fine. Next, use functions like MsiOpenDatabase, MsiDatabaseOpenView, MsiViewExecute, MsiViewFetch & MsiRecordGetString to read the table you want from the transformed MSI.

 

Krgds

Berto


Edited by Berto, 29 September 2015 - 15:11.