Get dir setup install shield - installation

I want get dir my setup create by install shield.
I use command parametter Setup.exe /path=[SETUPEXEDIR]\log.txt
My setup location is Desktop\myapp\Setup.exe
When use [SETUPEXEDIR] return temp folder
I want when use [SETUPEXEDIR] return me my Setup.exe location.
I use installshield 2016 version 23 SP 2.
I use MSI Script.
I want get location and use in command parameter prerequisites.

A little hard to comprehend exactly what you are asking, but as far as I understand you want to know the location where setup.exe is running from?
Variables
The first question is: what version of Installshield are you using?
The second question is: are you using Basic MSI or Installscript MSI?
The third question is: what type of release media are you using?
There may be more relevant questions...
A word to the wise: if you are indeed using Installscript MSI you should know that it is a very buggy type of project, and you should seriously consider switching to Basic MSI to save yourself grief. I can provide more information on this if you like. I had to abandon Installscript MSI entirely to make my deployment problems go away.
Installshield Properties
It seems different versions of Installshield may behave differently and feature varying support for these folder properties / variables. It also seems the properties may not work with all types of release media. And finally they may only work in Basic MSI or Installscript MSI respectively. The properties I have found are: PACKAGE_LOCATION, SETUPEXEDIR and SRCDIR. There also appears to be an Installscript method called GetCurrentDir() available in recent versions of Installshield, but the documentation warns about using it (see link).
Please visit the links above in sequence and read in detail about each property's (or method's) limitations. It is very important that you use the option (if any) that matches your requirements and scenario. For example PACKAGE_LOCATION works only for Installscript MSIs, SETUPEXEDIR is set by Setup.exe. If the end user runs the .msi package directly, SETUPEXEDIR is not set.
MSI Built-in Property
It seems to me that getting the built-in MSI property SourceDir might be an option to try. My quick test indicates that it works for both InstallScript and Basic MSI. However, I do not know if this works for all versions of Windows Installer. Please test on various Windows versions to be sure.
You should also be aware of the potential problem using SourceDir which is described in the documentation for SETUPEXEDIR. This goes for setups that are compiled into a single, compressed setup.exe containing all files - this launcher will extract the MSI file to a temp location and run from there. When I tried with an uncompressed network image it worked fine to use SourceDir.
Finally, if you use a setup.exe to compress all files and enable the caching of the MSI on the system, then you will be running from somewhere inside: C:\WINDOWS\Downloaded Installations\{GUID}\.
All of this could be different on newer versions of Installshield. I am testing with an ancient version I have available. Please test thoroughly on your version.
I should also mention the OriginalDatabase built-in MSI property. Check the link for documentation on how it will be set.
Some links:
Installscript project - Get Setup.exe location.
How to find the setup.exe directory?
Installscript Function For Testing
And just for reference, here is a quick and dirty function to test these properties from an Installshield custom action (this is for other people who may find this without having tested as much as you):
function TestFolderProperties(hMSI)
STRING svName;
NUMBER nvSize;
begin
// MSI properties
nvSize = 256;
MsiGetProperty (hMSI, "SETUPEXEDIR", svName, nvSize);
MessageBox ("SETUPEXEDIR: " + svName, INFORMATION);
MsiGetProperty (hMSI, "SourceDir", svName, nvSize);
MessageBox ("SourceDir: " + svName, INFORMATION);
MsiGetProperty (hMSI, "OriginalDatabase", svName, nvSize);
MessageBox ("OriginalDatabase: " + svName, INFORMATION);
// System Variables
MessageBox ("SRCDIR: " + SRCDIR, INFORMATION);
// PACKAGE_LOCATION is not available in my version of Installshield, enable and test
//MessageBox ("PACKAGE_LOCATION: " + PACKAGE_LOCATION, INFORMATION);
end;
Remember to add the export to the top of the setup.rul file:
export prototype TestFolderProperties(HWND);
Test compile to verify, and then create an Installscript custom action and put it in a sequence. Make "Return Processing" Synchronous (Ignores exit code) for the custom action. I put it right before InstallFinalize in the sequence, using immediate mode execution. Rebuild your release and run it. Try different release build configurations (msi with external source files, MSI only with compressed files inside, setup.exe launcher with external files, setup.exe with all files compressed inside, setup.exe with caching, setup.exe without caching, etc... the behavior might be different).

Related

Change the value of a MSI property loaded from a DLL using a MSI transform

I need to modify the installation behavior of a MSI setup for "IBM i Access for Windows". The setup was created using InstallShield. During the installation the setup triggers two other MSI installations through "chaining". The parameters passed to MSIEXEC.EXE to execute those two installations get loaded by a custom action from a DLL that is included with the installation. The parameters end up in a MSI property.
I want to change the value in that property to manipulate the command line before the chained installation gets launched. Is this possible? If so, how? I have no problem to create an external DLL that reads and modifies the property, but I am at a loss on how to integrate this with the existing installation -- which tables do I have to modify and how, where should I put the DLL, ...
EDIT 1: To clarify this: I want to modify the parameters passed to the chained MSI installations. They are independent from the parameters I pass to the main installation and are loaded from a DLL that is part of the installation.
EDIT 2: I have uploaded the plain MSI + the relevant log file. I start the main installation with "/qn" to suppress all messages. That works without problems, the chained installations get executed without visible prompts. The problem arises when uninstalling the software (again with "/qn"). The remote custom action gets loaded from a DLL (line 6417):
MSI (s) (10:28) [09:00:45:643]: Invoking remote custom action. DLL: C:\Windows\Installer\MSIA4BD.tmp, Entrypoint: ISChainPackages
The command line loaded from the DLL specifies to call MSIEXEC.EXE with the parameter "/qb" instead of "/qn" (line 6958):
MSI (s) (10!60) [09:00:46:033]: PROPERTY CHANGE: Adding IS_CHAINER_POST_COMMANDLINE property. Its value is '/l"c:\temp\IBM_iAccess_7.1_Uninstall.log" /qb /x{CCA40632-843E-48C6-B14F-E1070015D87C} ...
And because the MSI installer has a lock on a file a messagebox pops up triggered by the uninstallation of the chained MSI (line 44046):
MSI (s) (10:C0) [09:01:05:553]: RESTART MANAGER: Did detect that the custom action server with process ID 2352 holds file[s] in use, so a reboot will be necessary.
MSI (s) (10:C0) [09:01:05:553]: Note: 1: 1610
MSI (s) (10:C0) [09:01:11:224]: RESTART MANAGER: The user chose to go on with the installation, although a reboot will be required.
The setup must update files or services that cannot be updated while the system is running. If you choose to continue, a reboot will be required to complete the setup.
The installation files for version 7.1 of this software are no longer available on the IBM website. Only the current version is, and I have not looked into whether the problem still exists with the latest version or not as I have been asked to package v7.1 by the business department.
One approach to this problem would be to create a new Custom Action that executes VBScript code stored in the Binary Table and place the new Custom Action right after ISChainPackagePrepare. The VBScript code will read the value of IS_CHAINER_POST_COMMANDLINE and replace it as specified in the Replace() function
The VBScript Code could look like this:
Option Explicit
Function ReplacePropVal()
dim propvalue
dim newvalue
propvalue = Session.Property("IS_CHAINER_POST_COMMANDLINE")
newvalue = Replace(propvalue,"/qb","/qn")
Session.Property("IS_CHAINER_POST_COMMANDLINE") = newvalue
End Function
You want to give your new Custom Action a Type of 6 to indicate that your Custom Action data is stored as a VBScript in the Binary table. Your Custom Action Source is a reference to the Name in the Binary Table. The Target value of your Custom Action will need to be the name of the VBScript Function which is ReplacePropVal in this case
Afterwards, you place your new Custom Action in the InstallExecutionSequence table using the same name for it as in the CustomAction table. Also make sure to give it a higher Sequence value as ISChainPackagePrepare. I would recommend placing it right after by incrementing the Sequence value of ISChainPackagePrepare by 1.
After you've changed the tables and generated a new transform, just run the package with the new transform being applied by specifying its path in the TRANSFORMS public property and your property value should be changed.
I think the ideal approach here would be to transform the chained package definition. The UI level (documentation) is stored in the first two bits of the Options column of the ISChainPackage table, so all your transform should have to do is alter that value. In particular, you can change those bits from ecoUIBasic (0) to ecoUINone (1), which should be as simple as adding 1 to the current value. Also available are ecoUIReduced (2) and ecoUIFull (3).
If ISChainPackage.Options is altered correctly, the desired IS_CHAINER_POST_COMMANDLINE will be generated for you, and you won't have to add a secondary custom action to alter the /qb to /qn afterward. (Kudos to sevi for suggesting that functional workaround.)
If this is an Advanced or Suite UI Setup.exe, please check that
link for how to pass a property.
Package Database Entries (Software Re-Packaging tips for iAccess and other software):
https://www.itninja.com/company/browse/i - look at the IBM entries
IBM i Access for Windows
IBM iAccess for Windows 7.1
How to perform silent upgrade for IBM I Access for Windows 7.1?
Making a silent package for IBM i Access for Windows 7.1 with latest patch
Approaches: What does this DLL custom action do? Does it create a license key? Often these things have been found and solved many times before. To check for this, I usually use these approaches to find solutions:
File Extraction: try extracting files from the setup and look for help files that describe proper deployment. "Large Scale Deployment.chm", "Installation Command Line Parameters.chm", etc... or ready-made transforms or command line file samples (Install.cmd).
Deployment Sites: Check https://www.itninja.com/company/browse/i (Software Re-Packaging tips - look at the IBM entries. Several entries that look relevant, here is one).
Forums: inspect their support forums or online support - if available.
Phone: get on the phone with the vendor. Sometimes very helpful, often a waste of time. Ask for deployment relevant information sent from support. Do this if you have a support agreement?
See section on file extraction below.
Setup.exe Switches: I have a similar or related answer here, where I also mention setup.exe command line switches: Silent run installer (.exe) with parameters on Windows.
Logging: If the custom action does not create something dynamic (unique license key, machine locking identity, etc...), then you can try to find what was generated by logging the setup and looking for the command line used in the log file. Mock-up sample:
MSI (s) (AC:00) [00:00:00:00]: Command Line: TARGETDIR=C:\ SHORTCUTDIR=C:\Documents and Settings\All Users\Start Menu\Programs\Test ACTION=INSTALL
File Extraction: Is this an Installshield Suite project? did you extract the embedded files and MSI files first?: Programmatically extract contents of InstallShield setup.exe.
What is in a Setup.exe?: Installshield setup.exe files can be lots of different things (explanation of different setup.exe flavors): Regarding silent installation using Setup.exe generated using Installshield 2013 (.issuite) project file.
Links:
Extract MSI from EXE
What is the purpose of administrative installation initiated using msiexec /a?

How ISSetup.dll is used in InstallShield?

I notice that every time I rebuild my InstallShield project the file PROJECT_ASSISTANT\Interm\ISSetup.dll is updated. As described in the documentation, it executes InstallScript custom actions.
I always deliver a single exe PROJECT_ASSISTANT\SINGLE_EXE_IMAGE\DiskImages\DISK1\Setup.exe to my customers, and the installation runs smoothly without this ISSetup.dll.
So is this ISSetup.dll packed into the single setup.exe somehow? If not, how the Installscripts are executed on client machine?
I would like to tell you the project type (be a Basic MSI, InstallScript, or InstallScript MSI), but since I build my project from command-line (InstallShield 2012 SpringSP1 SAB) and am not able to open the project in GUI mode to view the properties pane, I don't know how to get this information from an .ism (XML format) file.
I forget the exact mechanics of where the file is included in each project type that may use it (sometimes it's directly in setup.exe, sometimes it's indirect). Regardless, ISSetup.dll is always the compiled InstallScript engine (the C++ part), and often has the compiled setup.inx (InstallScript part) "streamed" onto it. Something (perhaps setup.exe, perhaps a Windows Installer custom action) calls into it to run InstallScript code that we provided, or that you wrote.
So the short answer to the original question is: yes.
To answer the unasked questions, the Interm folder is an intermediate folder used for staging some of the files that get built into setup.exe or into the .msi file, and ISSetup.dll definitely receives updated compiled script code for each build of a Basic MSI or InstallScript MSI that includes custom actions.
I believe the ISSetup.dll is compiled into the MSI's binary table and extracted as part of the launching of the msi via msiexec.exe - at least for Basic MSI files.
The setup.exe wrapper probably contains the whole ISSetup.dll - perhaps statically linked or embedded somehow. Michael Uhrman (Installshield developer) will probably comment if he sees this question.
UPDATE:
I found a version of this ISSetup.dll file, see a screen shot from Dependency Walker below. In addition to the exported functions seen, there are also COM register and unregister methods exported (DllRegisterServer, DllUnregisterServer, DllCanUnloadNow, DllGetClassObject). The f-functions must be the various Installscript functions. The first 5 functions must be related to Installscript MSI.

Where can I create a custom action that executes after 'installfinalize' in Installshield 2013 Express?

I've managed this in Wix but my colleague wants to replicate it in Installshield 2013 Express. We have found the 'custom actions' section in Installshield but we cannot see where we can make it run after Installfinalize, it needs to come after copyfiles AND have Execute="immediate". All of the options after copyfiles have Execute="Deferred".
In Wix I have a VBScript which reads the MSI Session.Property("OriginalDatabase") and then uses this to write to some config files which are installed by the MSI. The point being that if we rename the MSI then the config is adjusted to reflect the MSI filename.
I would have posted a screenshot of the IS custom actions UI but I need '10 reputation' to post images - So the link to the image is -> Here
Two possibilities here....
1) Since you say it's MyFile.cfg I'll assume it's not .INI or .XML format. In that case, use the InstallShield Text Files Changes view to author a search and replace on the files. The InstallShield custom actions support UAC and Rollback so you'll be good to go there. You will probably need a very simple InstallScript custom action to read the OriginalDatabase property, parse out the part you care about and assign it to another property. Then use that property in the Text Files Changes view.
2) Why have the entires in the .cfg file at all? What application reads these values? Refactor that to not need the cfg files. Windows Installer exposes an API that allows you to query the installer service for information related to installed products. You can ask MSI what the MSI name was for an installed application and then use that information for whatever you need it from. Put the logic in the application and simplify the deployment story for a more robust installer experience.
You are going about this all wrong. Custom actions that modify the machine state should always be deferred and scheduled between install initialize and install finalize. Failure to do so will break in an UAC environment and also not support transactional rollback on failure.
Are these XML files? I'd use immeadiate custom actions scheduled just after installinitialize to emit temporary records into various MSI tables. The concept is to leverage DuplicateFiles to clone the file to a name based on the MSI name. You'd also have some work if you need to modify the files. Done correctly and your installer will still have full rollback functionality and work in an advertised / UAC scenario.
Also, VB/JScript custom actions are not reliable.

Is it possible to detect if help file is contained in the setup file (msi or exe)?

I would like to know how can I detect if help file is contained in setup file for windows platform application (msi or exe). Is there any method to get this information without installing the software first ?
Of course setup file can be created by many setup makers like innosetup, installshield and so on. So I wonder if there is some universal method to solve this.
For an MSI based install it would be very easy. For example you can use the Microsoft.Deployment.WindowsInstaller interop via C# to open the MSI as an InstallPackageClass then access it's Files collection to see if it contains the file you care about.
For a Non-MSI based install, there is no universal way and in most cases, no way period. See, that's kind of the point of MSI: to have a standards based package rich in meta data to be able to see what it's doing. When you do some proprietary script driven installer you lose that openness.
If it's a MSI file, open it up using Orca, and you can view file names.
For both of them, you should be able to do an administrative install, which would extract the files, but not register anything. Depending on where the exe came from, doing an administrative install changes, since each vendor(installshield, innosetup, etc) has their own way to run an administrative install.
for a MSI it's simply
msiexec /a <msi_filename>
For an exe you'll have to look up how to pass the /a argument.

How to find the setup location in an VBScript custom action for InstallShield?

In an InstallShield project I have a VBScript custom action that conditionally needs to execute a certain file packaged with the install.
Normally I get the current directory of a vbs using code such as
sCurPath = CreateObject("Scripting.FileSystemObject").GetAbsolutePathName(".")
Which, if it returned the location of the Setup.exe that initiated the install, should work.
However when running the install, the current path (on XP) is C:\Windows\system32 instead of the location of the Setup.exe file I was expecting.
Assuming the output of my InstallShield build looks like the following
Disk1
->Setup.exe
->ISSetupPrerequisites
-->Req1
-->Req2
-->...
->OtherReqs
-->ConditionallyRunMe.exe
How could I run "\OtherReqs\ConditionallyRunMe.exe" from a VBScript custom action?
Thanks!!
(Note: I realize there are ways to conditionally run exe files from withing InstallShield, but in this case the requirements are not supported by InstallShield - unless there is a way to use a VBScript custom action return value as a condition to run another file?)
After a lot of messing around, I got it (actually found it in the InstallShield manual, and not Google, go figure :))!
This line of VBScript does the trick
disk1Path = Session.Property("SETUPEXEDIR")
The line above points to where ever the setup exe file was, so from there it's trivial to run any exe included with your install media.
Other useful ones I found, which I'll past here for reference are
'points to app data\downloaded install directory
MsgBox Session.Property("SourceDir")
'where the software wants to install to on the users system
MsgBox Session.Property("INSTALLDIR")
Not sure why it's so hard to find a good reference on MSI Standard properties (even just a list). The closest I found was this, but not all of them work (and not specifically for InstallShield at all). If anyone finds a good link with documentation about MIS Standard properties and their description please add a link here, so no one has to waste as much time on this as I did :).

Resources