<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
<channel>
<title>InstallTalk</title>
<link>http://blogs.flexerasoftware.com/installtalk/</link>
<description>InstallTalk is a blog for software installation developers and program managers that discusses the latest best practices, trends, events, and news impacting installation development. It is from the installation experts that bring you InstallShield and InstallAnywhere.</description>
<language>en-US</language>
<lastBuildDate>Thu, 16 Feb 2012 12:27:39 -0600</lastBuildDate>
<generator>http://www.typepad.com/</generator>

<docs>http://www.rssboard.org/rss-specification</docs>
<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/InstallTalk" /><feedburner:info uri="installtalk" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>InstallTalk</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item>
<title>ICE Validation Resolution (MICE)</title>
<link>http://feedproxy.google.com/~r/InstallTalk/~3/NyVfyKeBDus/by-matt-stclair-bishop-in-my-last-two-blog-articles-ice-validation-part-1-and-ice-validation-part-2-we-discussed-the-ne.html</link>
<guid isPermaLink="false">http://blogs.flexerasoftware.com/installtalk/2012/02/by-matt-stclair-bishop-in-my-last-two-blog-articles-ice-validation-part-1-and-ice-validation-part-2-we-discussed-the-ne.html</guid>
<description>By Matt St.Clair Bishop In my last two blog articles (ICE Validation: Part 1 and ICE Validation: Part 2) we discussed the need for validation of the MSI databases and a means by which you could include your own custom rules into the standard Internal Consistency Evaluator (ICE) validation checking mechanism. This time we will extend the thinking to provide a means of automatically resolving validation issues creating a Manipulating-ICE or MICE. Aim The obvious extension to the error flagging phase of the ICE validation is the error correction phase, which has, up until now, been a manual process. We...</description>
<content:encoded><![CDATA[<p><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;">By <a href="http://blogs.flexerasoftware.com/InstallTalk/authors.html" target="_blank">Matt St.Clair Bishop</a></span></p>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;">In my last two blog articles (<a href="http://blogs.flexerasoftware.com/installtalk/2012/01/ice-validation-why-bother-part-1-of-2.html" target="_blank">ICE Validation: Part 1</a> and <a href="http://blogs.flexerasoftware.com/installtalk/2012/01/ice-validation-why-bother-part-2-of-2.html" target="_blank">ICE Validation: Part 2</a>) we discussed the need for validation of the MSI databases and a means by which you could include your own custom rules into the standard Internal Consistency Evaluator (ICE) validation checking mechanism. This time we will extend the thinking to provide a means of automatically resolving validation issues creating a Manipulating-ICE or MICE.</span></p>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;"><strong>Aim<br /></strong>The obvious extension to the error flagging phase of the ICE validation is the error correction phase, which has, up until now, been a manual process. We need to remove the need for a technician performing validation to personally interpret the results. We seek to automate the resolution, fixing hundreds of instances in the same time it would take to resolve one issue manually.</span></p>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;">To do this we will perform the following steps:</span></p>
<ol>
<li><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;">Make a copy of the original MSI database.</span></li>
<li><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;">Inspect some element of the MSI database iterating through records as necessary.</span></li>
<li><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;">Perform resolution by updating the copy of the database.</span></li>
<li><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;">Commit all changes and compare to the original database to generate the transform.</span></li>
</ol>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;">This demonstration will be performed in Visual Basic Script for ease.</span></p>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;">During this demonstration we will take a very simple example of a custom packaging Best Practice, that of ensuring that all packages are deployed per-machine by setting the value of the property ALLUSERS to 1.</span></p>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;"><strong>Copy the Original Database<br /></strong>In the following code snippet we see (on line 18) the command line argument being processed to determine the working directory of the MSI which was dropped onto the VBScript. After that both the base MSI and the changed MSI are assigned names. The VBScript File System Object is used to duplicate the given MSI. Then, using the Windows Installer Object, both databases are opened (the base in read-only and the changed in read-write transact mode).</span></p>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;"><img alt="MICE1" class="asset  asset-image at-xid-6a010537097f24970b0168e776bfb0970c" src="http://blogs.flexerasoftware.com/.a/6a010537097f24970b0168e776bfb0970c-500wi" title="MICE1" /></span><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;"><strong>&#0160;</strong></span></p>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;"><strong>&#0160;</strong></span></p>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;"><strong>Inspect the Current Value of the ALLUSERS Property<br /></strong>In this snippet we see how to interact with the tables; it is quite similar to the way in which you talk to a SQL Database. First we create a view, then we execute that view and finally fetch records from the executed view.</span></p>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;"><a href="http://blogs.flexerasoftware.com/.a/6a010537097f24970b0163017fb28c970d-popup" onclick="window.open( this.href, &#39;_blank&#39;, &#39;width=640,height=480,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0&#39; ); return false" style="float: left;"><img alt="MICE2" class="asset  asset-image at-xid-6a010537097f24970b0163017fb28c970d" src="http://blogs.flexerasoftware.com/.a/6a010537097f24970b0163017fb28c970d-500wi" style="margin: 0px 5px 5px 0px;" title="MICE2" /></a></span></p>
<p>&#0160;</p>
<p>&#0160;</p>
<p>&#0160;</p>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;">&#0160;</span></p>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;">The key to getting this right is the types of quotes used on line 42. The double quotes (&quot; &quot;) enclose the entire Select statement. We sometimes break out of that literal string to include VBScript variables calculated or parameterised earlier, and in those cases we concatenate them into the line using the ampersand (&amp;). The single vertical quotes (&#39;&#39;) are used to refer to strings within the Select statement. In our example we are looking for the string value of a property to be ALLUSERS. Any columns which are defined as numeric, such as the Root column in the Registry table, do not use the single vertical quotes. Finally the single angled quotes (` `) are used to escape column and table names; this is not necessary unless the column of table name clashes with an internal MSI-SQL keyword—for example, in the Registry table there is a column called Key, which is also a MSI-SQL keyword.</span></p>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;">To highlight the problem of not escaping consider a somewhat contrived custom table called FROM containing a column called SELECT and wanting to read its value when a second column called WHERE has the value 1. The un-escaped Select statement would read:</span></p>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;">“SELECT SELECT FROM FROM WHERE WHERE=2” and would fail miserably, whereas the escaped equivalent:</span></p>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;">“SELECT `SELECT` FROM `FROM` WHERE `WHERE`=2” would work correctly.</span></p>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;">Although this is a contrived example unless we learn all MSI-SQL keywords this could also happen in more realistic examples. So to be on the safe side we should escape all column and table names.</span></p>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;"><strong>&#0160;</strong></span></p>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;"><strong>Perform the Resolution<br /></strong></span><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;">In this snippet we perform the change necessary to fix our issue. In this case we have some alternate cases: the ALLUSERS value may not exist or it may exist with the non-prescribed value of 1.</span></p>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;">The If statement on line 45 is true only if there is an ALLUSERS property in the MSI. We go on to extract its value using the “.StringData(1)” property. This extracts from the current record the value of the column in position 1 and returns it as a string representation. If the value does not already equal 1 we set it to 1 and then on line 56 we create a new view. The MSI-SQL statement here updates the property table and embeds the VBScript value of AllUsers. Note we must still execute that view but we do not proceed to fetch records from it.</span></p>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;"><a href="http://blogs.flexerasoftware.com/.a/6a010537097f24970b0163017fb736970d-popup" onclick="window.open( this.href, &#39;_blank&#39;, &#39;width=640,height=480,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0&#39; ); return false" style="float: left;"><img alt="MICE3" class="asset  asset-image at-xid-6a010537097f24970b0163017fb736970d" src="http://blogs.flexerasoftware.com/.a/6a010537097f24970b0163017fb736970d-500wi" style="margin: 0px 5px 5px 0px;" title="MICE3" /></a></span></p>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;">&#0160;</span></p>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;">&#0160;</span></p>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;">&#0160;</span></p>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;">&#0160;</span></p>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;">&#0160;</span></p>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;">&#0160;</span></p>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;">&#0160;</span></p>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;">&#0160;</span></p>
<p>&#0160;</p>
<p>&#0160;</p>
<p>&#0160;</p>
<p>The Else statement that begins on line 61 is true only if the earlier select statement failed to collect any records which means there is no ALLUSERS property (hence this is a non-standard per-user deployment). So in this case we should just insert the missing record into the property table.</p>
<p><strong>Commit Changes and Make a Transform<br /></strong>Technically, at this point, we have completed our changes but since we opened the database in transact mode just closing the database will rollback any un-committed changes. So before we do that we must commit our changes.</p>
<p><a href="http://blogs.flexerasoftware.com/.a/6a010537097f24970b0168e776e53e970c-popup" onclick="window.open( this.href, &#39;_blank&#39;, &#39;width=640,height=480,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0&#39; ); return false" style="float: left;"><img alt="MICE4" class="asset  asset-image at-xid-6a010537097f24970b0168e776e53e970c" src="http://blogs.flexerasoftware.com/.a/6a010537097f24970b0168e776e53e970c-500wi" style="margin: 0px 5px 5px 0px;" title="MICE4" /></a></p>
<p>&#0160;</p>
<p>&#0160;</p>
<p>&#0160;</p>
<p>&#0160;</p>
<p>In our last code snippet we see how to compare the changed database with the original read-only database to create a transform. This allows us to use this same script on a vendor MSI and express the same change without modifying the original vendor package. The line 149 shows how to make the transform more generic and not care too much when applying the transform.</p>
<p><a href="http://blogs.flexerasoftware.com/.a/6a010537097f24970b0168e776dc8a970c-popup" onclick="window.open( this.href, &#39;_blank&#39;, &#39;width=640,height=480,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0&#39; ); return false" style="float: left;"><img alt="MICE5" class="asset  asset-image at-xid-6a010537097f24970b0168e776dc8a970c" src="http://blogs.flexerasoftware.com/.a/6a010537097f24970b0168e776dc8a970c-500wi" style="margin: 0px 5px 5px 0px;" title="MICE5" /></a></p>
<p>&#0160;</p>
<p>&#0160;</p>
<p><strong>&#0160;</strong></p>
<p><strong>&#0160;</strong></p>
<p><strong>Summary<br /></strong>In this article we have seen how to perform a simple check against the MSI database and fix it. Although fairly trivial, this example can easily be extended to perform more complex checks on different and multiple tables retrieving sets of records instead. However the resolution is just as simple and when applied to large packages generate massive time savings over the same manual operation.</p><img src="http://feeds.feedburner.com/~r/InstallTalk/~4/NyVfyKeBDus" height="1" width="1"/>]]></content:encoded>


<category>Windows Installer Tips</category>
<category>Windows Software Installation Development</category>

<dc:creator>Flexera Software</dc:creator>
<pubDate>Thu, 16 Feb 2012 12:27:39 -0600</pubDate>

<feedburner:origLink>http://blogs.flexerasoftware.com/installtalk/2012/02/by-matt-stclair-bishop-in-my-last-two-blog-articles-ice-validation-part-1-and-ice-validation-part-2-we-discussed-the-ne.html</feedburner:origLink></item>
<item>
<title>Selecting Suite Packages to Match the Language of the Target Machine</title>
<link>http://feedproxy.google.com/~r/InstallTalk/~3/1ByYeq_VH7w/selecting-suite-packages-to-match-the-language-of-the-target-machine.html</link>
<guid isPermaLink="false">http://blogs.flexerasoftware.com/installtalk/2012/01/selecting-suite-packages-to-match-the-language-of-the-target-machine.html</guid>
<description>By Michael Urman I’ve heard several people ask how to conditionally select a package based on the target machine’s system language. While InstallShield 2012 didn’t include a way to do this with a few mouse clicks, it does allow us to create our own extension condition. Extension conditions can perform any check desired, including randomly returning TRUE or FALSE results (though I would never suggest it). In this article I will walk through using Visual C++ 2010 Express with InstallShield 2012 SP1 to add a set of conditions that check the target machine’s language settings. I start by creating a...</description>
<content:encoded><![CDATA[<p>By <a href="http://blogs.flexerasoftware.com/InstallTalk/authors.html" target="_blank">Michael Urman</a></p>
<p>I’ve heard several people ask how to conditionally select a package based on the target machine’s system language. While InstallShield 2012 didn’t include a way to do this with a few mouse clicks, it does allow us to <a href="http://blogs.flexerasoftware.com/installtalk/2011/12/extension-conditions.html" target="_blank">create our own extension condition</a>. Extension conditions can perform any check desired, including randomly returning TRUE or FALSE results (though I would never suggest it). In this article I will walk through using Visual C++ 2010 Express with InstallShield 2012 SP1 to add a set of conditions that check the target machine’s language settings.</p>
<p>I start by creating a new Win32 project, called LangCond, and I select DLL for the application type. Because I want minimal run-time dependencies, I edit the properties under Code Generation, changing Runtime Library to <strong>/MTd</strong> and <strong>/MT</strong> instead of <strong>/MDd</strong> and <strong>/MD</strong>. Then so the proper functions are exported, I create a module definition file LangCond.def and add it to my Linker Input properties by setting Module Definition File to LangCond.def. Finally it’s time to talk C++. Following the instructions on <a href="http://blogs.flexerasoftware.com/installtalk/2011/12/extension-conditions.html" target="_blank">Extension Conditions</a>, I import COM information from setupsuite.exe and create six functions:</p>
<p>&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;HRESULT __stdcall <strong>User_Validate</strong>(IDispatch *pCondition);<br />&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;HRESULT __stdcall <strong>User_Evaluate</strong>(IDispatch *pCondition, VARIANT_BOOL *pbResult);<br />&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;HRESULT __stdcall <strong>System_Validate</strong>(IDispatch *pCondition);<br />&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;HRESULT __stdcall <strong>System_Evaluate</strong>(IDispatch *pCondition, VARIANT_BOOL *pbResult);<br />&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;HRESULT __stdcall <strong>OS_Validate</strong>(IDispatch *pCondition);<br />&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;HRESULT __stdcall <strong>OS_Evaluate</strong>(IDispatch *pCondition, VARIANT_BOOL *pbResult);</p>
<p>I want these conditions to respectively allow a match of a match of a target machine’s user locale (User), its system locale (System), or the default UI language (OS). Since we expect to support versions of Windows before Windows Vista, we will accept <a href="http://msdn.microsoft.com/en-us/goglobal/bb964664" target="_blank">Locale IDs</a>&#0160; (LCIDs) instead of Language or Culture Names. Thus the condition will take an <strong>LCID</strong> attribute, where exactly one LCID must be specified. If it matches, the condition will yield a TRUE result; if it doesn’t match, it will yield a FALSE result.</p>
<p>Let’s implement this in LangCond.cpp. Each <strong><em>kind</em>_Validate</strong> call should verify the LCID attribute is an integer. Correspondingly each <strong><em>kind</em>_Evaluate</strong> call should retrieve the current setting corresponding to the <em>kind</em> of condition (using <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/dd318121(v=vs.85).aspx" target="_blank">GetUserDefaultLCID</a>, <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/dd318121(v=vs.85).aspx" target="_blank">GetSystemDefaultLCID</a>, or <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/dd318123(v=vs.85).aspx" target="_blank">GetSystemDefaultUILanguage</a>), and then verify if the one listed in the <strong>LCID</strong> attribute matches. We will use <strong>wcstoul</strong> to implement both checks. To avoid repeating too much code, each validation will call a helper function <strong>ValidateLCID</strong>; each evaluation will call <strong>MatchLCID</strong>.</p>
<p>Finally let’s wire it up. Start a new suite project and add a package with an eligibility condition. Also add LangCond.dll as a support file. Then save and close the project, and edit it in your favorite XML editor. Add namespace attribute <strong>xmlns:language=&quot;LangCond.dll&quot;</strong> to the root setup element, attribute <strong>Namespace=&quot;LangCond.dll&quot;</strong> to the Resources/Resource element referencing LangCond.dll, and element <strong>&lt;language:User LCID=&quot;1033&quot;/&gt;</strong> to the eligibility condition on the package. Once you build this suite, the package will run only on machines where the user has selected the US English locale. Swap <strong>1033</strong> out for <strong>1041</strong> to run only on a Japanese locale, or swap the whole <strong>language:User</strong> element for a <strong>language:System</strong> element to run only on machines that match the system locale. Or combine both conditions under an <strong>&lt;Any&gt;</strong> group to run on systems where the user is likely to understand the selected language, under the assumption that both the user and system languages that are selected on target systems reflect languages the user understands.</p>
<p>The attached <a href="http://blogs.flexerasoftware.com/files/LangCond.zip" target="_blank">LangCond.zip</a> file contains the sample source code described here, as well as a built copy of LangCond.dll and a sample suite project. In the sample project, there are three packages. One will run only on a machine with US English settings. The second will run on a machine with Japanese settings. The third will run on either.</p>
<p>You can use the language condition in any condition field, such as in an exit condition to allow installation on a specific locale, or in feature conditions to configure the default selection state of language-related subfeatures. The latter is useful in a feature tree that looks like this (with conditions referenced):</p>
<ul>
<li>Dictionaries 
<ul>
<li>…</li>
<li>English: &lt;Any&gt;&lt;language:System LCID=&quot;1033&quot;/&gt;&lt;language:User LCID=&quot;1033&quot;/&gt;&lt;/Any&gt;</li>
<li>French: &lt;Any&gt;&lt;language:System LCID=&quot;1036&quot;/&gt;&lt;language:User LCID=&quot;1036&quot;/&gt;&lt;/Any&gt;</li>
<li>German: &lt;Any&gt;&lt;language:System LCID=&quot;1031&quot;/&gt;&lt;language:User LCID=&quot;1031&quot;/&gt;&lt;/Any&gt;</li>
<li>…</li>
</ul>
</li>
</ul>
<p><em>Note that support for extension conditions is available in InstallShield 2012 SP1. To obtain SP1, see </em><a href="http://support.installshield.com/kb/view.asp?articleid=Q201298" target="_blank"><em>Q201298</em></a><em>: InstallShield 2012 Service Pack 1.</em></p><img src="http://feeds.feedburner.com/~r/InstallTalk/~4/1ByYeq_VH7w" height="1" width="1"/>]]></content:encoded>


<category>Suite Installations</category>
<category>Windows Installer Tips</category>
<category>Windows Software Installation Development</category>

<dc:creator>Flexera Software</dc:creator>
<pubDate>Fri, 27 Jan 2012 16:47:52 -0600</pubDate>

<feedburner:origLink>http://blogs.flexerasoftware.com/installtalk/2012/01/selecting-suite-packages-to-match-the-language-of-the-target-machine.html</feedburner:origLink></item>
<item>
<title>ICE Validation: Why Bother? (Part 2 of 2)</title>
<link>http://feedproxy.google.com/~r/InstallTalk/~3/4JCBkrBGHWM/ice-validation-why-bother-part-2-of-2.html</link>
<guid isPermaLink="false">http://blogs.flexerasoftware.com/installtalk/2012/01/ice-validation-why-bother-part-2-of-2.html</guid>
<description>By Matt St.Clair Bishop In my last article I discussed the basics of, and motivation for, validating your MSI packages. You may also be aware of the InstallShield internal consistency evaluators (ICEs) and the InstallShield Best Practice rules which were all authored by Flexera Software; these are essentially custom rules that can be used to check additional facets of your MSIs. In this article we show how we can implement our own custom rules within the standard validation process. Creating a Custom ICE Rule The entire Windows Installer technology also enjoys the benefit of being open and hence extensible. As...</description>
<content:encoded><![CDATA[<p>By <a href="http://blogs.flexerasoftware.com/InstallTalk/authors.html" target="_blank">Matt St.Clair Bishop</a></p>
<p>In my <a href="http://blogs.flexerasoftware.com/installtalk/2012/01/ice-validation-why-bother-part-1-of-2.html" target="_blank">last article</a> I discussed the basics of, and motivation for, validating your MSI packages. You may also be aware of the InstallShield internal consistency evaluators (ICEs) and the InstallShield Best Practice rules which were all authored by Flexera Software; these are essentially custom rules that can be used to check additional facets of your MSIs. In this article we show how we can implement our own custom rules within the standard validation process.</p>
<p><strong>Creating a Custom ICE Rule</strong></p>
<p>The entire Windows Installer technology also enjoys the benefit of being open and hence extensible. As such you are at liberty to write your own rules and add them to the Microsoft rules. Once you have gone to the trouble of creating them, satisfying these custom rules should be just as important as satisfying the original Microsoft evaluators, so let us review making our own.</p>
<p>The best place to start here is to take one of the Microsoft rules as an example and modify it to suit your purpose. Most all of the supplied rules in DARICE.CUB are in a DLL format which makes them impossible to refit; however, ICE08, ICE09, ICE32, and ICE61 are available as VBScript which means they can be extracted from the Binary table, modified and reinserted as new rules.</p>
<p><a href="http://blogs.flexerasoftware.com/.a/6a010537097f24970b016760ce4b5e970b-popup" onclick="window.open( this.href, &#39;_blank&#39;, &#39;width=640,height=480,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0&#39; ); return false" style="display: inline;"><img alt="Function ICE" class="asset  asset-image at-xid-6a010537097f24970b016760ce4b5e970b" height="260" src="http://blogs.flexerasoftware.com/.a/6a010537097f24970b016760ce4b5e970b-500wi" title="Function ICE" width="568" /></a><br /><br />This image shows the modification to the top part of one of those VBScripts to create a rule which checks the UpgradeCode of the MSI and ensures it has been changed from that value in the MSI template. Apart from the modifications of the script function name and descriptions, very little has been changed here, although near the bottom we are checking for existence of the Property table. Since the Property table is a mandatory table, this is technically unnecessary in this case but it does allow you to ensure a table exists before you inspect it. This is good practice, especially since the more recent versions of InstallShield drop empty tables, so you should not assume all your tables will always exist.</p>
<p><a href="http://blogs.flexerasoftware.com/.a/6a010537097f24970b0162ffd9dd32970d-popup" onclick="window.open( this.href, &#39;_blank&#39;, &#39;width=640,height=480,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0&#39; ); return false" style="display: inline;"><img alt="Process Table" class="asset  asset-image at-xid-6a010537097f24970b0162ffd9dd32970d" height="238" src="http://blogs.flexerasoftware.com/.a/6a010537097f24970b0162ffd9dd32970d-500wi" title="Process Table" width="585" /></a></p>
<p>The second part of this script is the business end and begins with an OpenView method being called on the Database object. The SQL syntax selects the Property and Value column entries of the row called UpgradeCode from the Property table. As with any SQL select view, we must execute it before we attempt to fetch records out of it. Between the Execute and the Fetch, though, there is a little error checking. Failure at this point often points to the SQL statement not correctly matching the SQL schema.</p>
<p>After the Fetch we ensure the record is not empty (although the UpgradeCode should exist it may not and in that case we need not check its value). Then we proceed to inspect the first nine characters of the value. Notice how we refer to the fields in the select statement: by index number matching their position in the SQL select statement.</p>
<p>In this case finding the record with these characteristics is an error condition, so we flag the error by posting a message with the correct parameters. These are crucial so let us review them in a little more detail.</p>
<p><span style="font-family: courier new,courier;"><span style="color: #ff0000;">recInfo</span>.StringData<span style="color: #0060bf;">(</span><span style="color: #c00000;">0</span><span style="color: #0060bf;">) =</span> <span style="color: #c00000;">&quot;ICE1007&quot;</span> <span style="color: #0060bf;">&amp; Chr(</span><span style="color: #c00000;">9</span><span style="color: #0060bf;">) &amp; </span><span style="color: #c00000;">&quot;1&quot;</span> <span style="color: #0060bf;">&amp; Chr(</span><span style="color: #c00000;">9</span><span style="color: #0060bf;">)&amp;</span> <span style="color: #c00000;">&quot;This package contains the UpgradeCode of the repackaging template, the GUID must be &#39;spun&#39;&quot;</span> <span style="color: #0060bf;">&amp; Chr(</span><span style="color: #c00000;">9</span><span style="color: #0060bf;">) &amp; <span style="color: #c00000;">&quot;&quot;</span> &amp; Chr(</span><span style="color: #c00000;">9</span><span style="color: #0060bf;">) &amp;</span> <span style="color: #c00000;">&quot;Property&quot;</span> <span style="color: #0060bf;">&amp; Chr</span>(<span style="color: #c00000;">9</span>) <span style="color: #0060bf;">&amp;</span> <span style="color: #c00000;">&quot;Value&quot;</span> <span style="color: #0060bf;">&amp; Chr(</span><span style="color: #c00000;">9</span><span style="color: #0060bf;">) &amp; </span><span style="color: #c00000;">&quot;[1]&quot;</span></span></p>
<p>The record has multiple parts delimited by the tab character <span style="font-family: courier new,courier;"><span style="color: #0060bf;">Chr(</span><span style="color: #c00000;">9</span><span style="color: #0060bf;">)</span>. </span>The first part denotes the rule name. The second “1” denotes an error, “2” is a warning. Then there is a description of the issue and suggestion of the resolution. The next part here is empty but could be used to point to a URL for a more detailed external explanation. The last three parts locate the error by Table, Column and Row; you can equate this to a Latitude, Longitude and Altitude of the problem. Note however that the Row value is not and cannot be coded directly into this message since the message doesn’t know which row the problem lies in. Instead it refers to “[1]” which in this case matches the parameter index from the earlier select statement. This bit of the record is really worth doing correctly since it then allows the operator to double-click on the error message and jump to the error automatically.</p>
<p><strong>Using Your Custom ICE Rules File</strong></p>
<p>Once you have created the new VBScript containing your custom rule code, you insert it back into the Binary table of your DARICE.CUB with a different name. A reference must also be made in the CustomAction table to refer it and then a new row added to the “_ICESequence” table. Your final step is to use it from within InstallShield. From the Build -&gt; Validate menu option you are able to browse for a new validation module (.cub).</p>
<p><a href="http://blogs.flexerasoftware.com/.a/6a010537097f24970b0162ffd9dffc970d-popup" onclick="window.open( this.href, &#39;_blank&#39;, &#39;width=640,height=480,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0&#39; ); return false" style="display: inline;"><img alt="Validate" class="asset  asset-image at-xid-6a010537097f24970b0162ffd9dffc970d" src="http://blogs.flexerasoftware.com/.a/6a010537097f24970b0162ffd9dffc970d-500wi" title="Validate" /></a></p>
<p>When you have selected it once, it will conveniently appear in the Recent Validation Modules list at the bottom of that same Validate submenu.</p>
<p><a href="http://blogs.flexerasoftware.com/.a/6a010537097f24970b0168e5cfa91f970c-popup" onclick="window.open( this.href, &#39;_blank&#39;, &#39;width=640,height=480,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0&#39; ); return false" style="display: inline;"><img alt="Valisdate MyIceCube" class="asset  asset-image at-xid-6a010537097f24970b0168e5cfa91f970c" src="http://blogs.flexerasoftware.com/.a/6a010537097f24970b0168e5cfa91f970c-500wi" title="Valisdate MyIceCube" /></a></p>
<p>Selecting the option will run your custom rules along with any existing rules, displaying errors and warnings as if they were native tests.</p>
<p><a href="http://blogs.flexerasoftware.com/.a/6a010537097f24970b0168e5cfaadb970c-popup" onclick="window.open( this.href, &#39;_blank&#39;, &#39;width=640,height=480,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0&#39; ); return false" style="display: inline;"><img alt="Tasks" class="asset  asset-image at-xid-6a010537097f24970b0168e5cfaadb970c" src="http://blogs.flexerasoftware.com/.a/6a010537097f24970b0168e5cfaadb970c-500wi" title="Tasks" /></a><br /><strong><br /></strong></p>
<p><strong>The Problem with ICE Rules</strong></p>
<p>So we have been able to demonstrate how custom checks or business logic could be incorporated into any quality assurance process. We could leave it at that and move on, but if we could understand what is wrong with this seemingly useful approach perhaps we could improve even on this.</p>
<p>The main problem with the ICE rules is that they are nothing more than what their name suggests: evaluators. They go to great lengths to detect inconsistencies in your MSI (some of them containing hundreds of lines of code); however, they do nothing to resolve the problem for you. This is unfortunate since they know exactly where the problems lie and apart from a rather dry error message, they leave you to solve the issues on your own.</p>
<p>Another problem with the ICE rules is that there is no clearly defined line where we can say these rules are important to deployment or functionality and these are not so important. They are classified into <em>warnings</em>, <em>errors</em> and even <em>failures</em> but these do not directly translate into whether or not you will have installation difficulty. Usually the best advice is that errors and failures should not be tolerated in an MSI, but warnings can often be ignored, but even this approach has drawbacks. For instance it is possible to distribute and even use a product that has errors and failures. Many software vendors are less than conscientious when it comes to MSI validation. There are even cases where a package that has nothing but warnings will not be able to deploy, install or function correctly.</p>
<p>Hence the dividing line between what we fix and what we tolerate is crooked and in the absence of any industry standard on what should be fixed, we are left with the rather woolly advice as given above: <em>Fix all errors and failures and as many warnings as you have time for.</em></p>
<p><strong>There Must Be a Better Solution</strong></p>
<p>The obvious extension to the error flagging phase of the ICE validation is the error correction phase, which has usually been a manual process. Once we have been around this iterative loop a number of times it soon becomes tedious and prone to being ignored or forgotten. Different validation operators may have different interpretations as to what needs fixing and what doesn’t. Even the same validation operator just before leaving for vacation may have a different opinion as to which issues need to be fixed and which do not. A systematic automated approach is required to reduce the human element during the cleanup process.</p>
<p>The mission statement of such an automated tool would be: <em>If you know what is wrong and you can fix it then do so.</em> Such a script would check a particular facet of the MSI based perhaps on an ICE rule or best practice and loop through the relevant tables seeking a problem. Once an issue has been identified, it would be resolved automatically if it can. The automated procedure would mean that hundreds of errors or warnings can be corrected in seconds, accurately, without the need for human intervention or specialised knowledge. The important thing to note here is that having built a custom ICE rule you have done 80% of the work in creating an automated fix.</p>
<p>Such resolution scripts exist today, I call them Manipulating Internal Consistency Evaluators (MICE), and in my next article we will create one from scratch, step by step.</p><img src="http://feeds.feedburner.com/~r/InstallTalk/~4/4JCBkrBGHWM" height="1" width="1"/>]]></content:encoded>


<category>Windows Installer Tips</category>
<category>Windows Software Installation Development</category>

<dc:creator>Flexera Software</dc:creator>
<pubDate>Thu, 19 Jan 2012 13:27:05 -0600</pubDate>

<feedburner:origLink>http://blogs.flexerasoftware.com/installtalk/2012/01/ice-validation-why-bother-part-2-of-2.html</feedburner:origLink></item>
<item>
<title>ICE Validation: Why Bother? (Part 1 of 2)</title>
<link>http://feedproxy.google.com/~r/InstallTalk/~3/YYXtBtxZ_jI/ice-validation-why-bother-part-1-of-2.html</link>
<guid isPermaLink="false">http://blogs.flexerasoftware.com/installtalk/2012/01/ice-validation-why-bother-part-1-of-2.html</guid>
<description>By Matt St.Clair Bishop The Microsoft Windows Installer format is a powerful and robust installation technology but, as is often the case in life, ultimate power does not come without certain responsibilities. Validation Is Your Responsibility The MSI database is often likened to the SQL database. Indeed when using the Windows Installer automation interface, the syntax statements are very SQL like, although it is not a full SQL implementation. Therein lies the problem; a full implementation of a relational database within the MSI file would have made the engine too large. Remember the first version had to be distributed on...</description>
<content:encoded><![CDATA[<p>By <a href="http://blogs.flexerasoftware.com/InstallTalk/authors.html" target="_blank">Matt St.Clair Bishop</a></p>
<p>The Microsoft Windows Installer format is a powerful and robust installation technology but, as is often the case in life, ultimate power does not come without certain responsibilities.</p>
<p><strong>Validation Is Your Responsibility</strong></p>
<p>The MSI database is often likened to the SQL database. Indeed when using the Windows Installer automation interface, the syntax statements are very SQL like, although it is not a full SQL implementation. Therein lies the problem; a full implementation of a relational database within the MSI file would have made the engine too large. Remember the first version had to be distributed on a 1.44Mb floppy disk. This means things like foreign key relationships are not being checked on entry, which in turn means the MSI tables, rows and columns can hide all manner of inconsistent entries. To counter this we validate the built MSI package.</p>
<p>Validation is not new by any means. It predates Windows Installer, though you may not have realised. Before the MSI tables structure, installations were generally controlled by a script which was, at least in part, compiled into an executable. As part of this compilation, the syntax of the script is checked. It was a mandatory part of building the installer and essentially is validation.</p>
<p>The Windows Installer equivalent is called validation and uses a slightly modified MSI file with the extension .CUB (pronounced <em>cube</em>) to hold a number of checking routines known as Internal Consistency Evaluator rules (ICE rules). Collections of these rules come in slightly different varieties covering logo compliance for Windows 2000, Vista and XP as well as the full suite of rules which includes all tests.</p>
<p>Validation can be done within the InstallShield 2012 tool from the build menu as well as from within AdminStudio tools such as Application Manager, Conflict Solver and Package Expert.</p>
<p><a href="http://blogs.flexerasoftware.com/.a/6a010537097f24970b0162ffbe5a0f970d-popup" onclick="window.open( this.href, &#39;_blank&#39;, &#39;width=640,height=480,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0&#39; ); return false" style="display: inline;"><img alt="IS Validation" class="asset  asset-image at-xid-6a010537097f24970b0162ffbe5a0f970d" src="http://blogs.flexerasoftware.com/.a/6a010537097f24970b0162ffbe5a0f970d-500wi" title="IS Validation" /></a><br /><br />If the validation options are not available on your build menu, either you have not yet built the package or the type of validation is not applicable to the type of project you are developing.</p>
<p><strong>Updating the Existing ICE Rules for Windows 7</strong></p>
<p>Although these ICE rules have been around since the inception of Windows Installer, some of the newer innovations have somewhat bypassed the older rule sets you may still be using. You may well have seen this being reported:</p>
<p><span style="font-family: courier new,courier;">ICE27&#0160; ERROR&#0160; Unknown action: &#39;MsiConfigureServices&#39; of InstallExecuteSequence table. Not a standard action and not found in CustomAction or Dialog tables</span></p>
<p>It says that the action MsiConfigureServices is unknown. Although it is a standard action “now” it is an extension of the standard services tables which became available in Windows Installer v5.0. Or perhaps you have seen this one:</p>
<p><span style="font-family: courier new,courier;">ICE45&#0160; WARNING&#0160;&#0160;&#0160;Row &#39;ReadyToInstall.InstallNow&#39; in table &#39;Control&#39; has bits set in the &#39;Attributes&#39; column that are reserved. They should be 0 to ensure compatibility with future installer versions.</span></p>
<p>It says that the InstallNow push button has some unknown attributes, even though those attributes are known “now”: they assign the UAC control icon to the button.</p>
<p>So unless we obtain an updated .CUB file, these appear to be problems we will just have to live with. However, in these instances, that is not the case. As mentioned earlier the .CUB file is just an MSI file with custom tables, so you can use your favourite MSI editor to open it. When we inspect the content we find that the ICE rules themselves have been written to retrieve their parameters and working values from these custom tables and are not using hard-coding inside the rule itself. We can use this to our advantage.</p>
<p>To update the ICE27 we add the MsiConfigureServices row into the _Action table:</p>
<p><a href="http://blogs.flexerasoftware.com/.a/6a010537097f24970b0168e5b4aea1970c-popup" onclick="window.open( this.href, &#39;_blank&#39;, &#39;width=640,height=480,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0&#39; ); return false" style="display: inline;"><img alt="MSIConfigure Services" class="asset  asset-image at-xid-6a010537097f24970b0168e5b4aea1970c" src="http://blogs.flexerasoftware.com/.a/6a010537097f24970b0168e5b4aea1970c-500wi" title="MSIConfigure Services" /></a></p>
<p>And to update the ICE45 we change the UsedBits column of the _ReservedBits table. Here we change the existing value 8126503 by adding the additional allowed attribute for the UAC shield icon 8388608, giving 16515111.</p>
<p><a href="http://blogs.flexerasoftware.com/.a/6a010537097f24970b0168e5b4b17d970c-popup" onclick="window.open( this.href, &#39;_blank&#39;, &#39;width=640,height=480,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0&#39; ); return false" style="display: inline;"><img alt="Control attributes" class="asset  asset-image at-xid-6a010537097f24970b0168e5b4b17d970c" src="http://blogs.flexerasoftware.com/.a/6a010537097f24970b0168e5b4b17d970c-500wi" title="Control attributes" /></a></p>
<p>Of course there are also some rules which are plain annoying. Understandably you may never want to fix or even know about them. Further inspecting the .CUB file we find that the _ICESequence table, which controls which rules are used and in which order, has a Condition column. Inserting a suitable logical condition which can never evaluate to true— for example, “1=0”—essentially turns off that rule.</p>
<p>You may also perform the same trick from InstallShield Tools -&gt; Options -&gt; Validation -&gt; Customize by turning off any rules you want to ignore.</p>
<p><a href="http://blogs.flexerasoftware.com/.a/6a010537097f24970b016760b383b8970b-popup" onclick="window.open( this.href, &#39;_blank&#39;, &#39;width=640,height=480,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0&#39; ); return false" style="display: inline;"><img alt="ICE71" class="asset  asset-image at-xid-6a010537097f24970b016760b383b8970b" src="http://blogs.flexerasoftware.com/.a/6a010537097f24970b016760b383b8970b-500wi" title="ICE71" /></a></p>
<p>In this article we have explored the motivation for MSI Validation and looked in more depth at the standard .CUB file. In my next article we will discover that we can extend this regime to cater for our own business rules by implementing our own custom logic.&#0160; Our ultimate aim is to improve our overall package quality.</p><img src="http://feeds.feedburner.com/~r/InstallTalk/~4/YYXtBtxZ_jI" height="1" width="1"/>]]></content:encoded>


<category>Windows Installer Tips</category>
<category>Windows Software Installation Development</category>

<dc:creator>Flexera Software</dc:creator>
<pubDate>Tue, 17 Jan 2012 16:04:41 -0600</pubDate>

<feedburner:origLink>http://blogs.flexerasoftware.com/installtalk/2012/01/ice-validation-why-bother-part-1-of-2.html</feedburner:origLink></item>
<item>
<title>Calling a Function in a DLL from a Wizard Page or Window in a Suite Installation</title>
<link>http://feedproxy.google.com/~r/InstallTalk/~3/UOAY41CXh_Y/calling-a-function-in-a-dll-from-a-wizard-page-or-window-in-a-suite-installation.html</link>
<guid isPermaLink="false">http://blogs.flexerasoftware.com/installtalk/2011/12/calling-a-function-in-a-dll-from-a-wizard-page-or-window-in-a-suite-installation.html</guid>
<description>By Hidenori Yamanishi In Suite installations, InstallShield lets you define actions that an end user triggers when using some of the various wizard interface controls. See the Configuring an Action for a Control on a Wizard Page or Window help topic for more details about the actions. If you need to perform an action in your Suite installation that is not natively supported by InstallShield, you can create an action that calls a function from a .dll file. This .dll file can perform any function that you require, such as verifying a serial number. The first step in creating an...</description>
<content:encoded><![CDATA[<p><span style="font-family: arial,helvetica,sans-serif;">By <a href="http://blogs.flexerasoftware.com/InstallTalk/authors.html" target="_blank">Hidenori Yamanishi</a></span></p>
<p><span style="font-family: arial,helvetica,sans-serif;">In Suite installations, InstallShield lets you define actions that an end user triggers when using some of the various wizard interface controls. See the <a href="http://helpnet.flexerasoftware.com/Robo/BIN/Robo.dll?tpc=/robo/projects/installshield18helplib/SteUIAction.htm" target="_blank">Configuring an Action for a Control on a Wizard Page or Window</a> help topic for more details about the actions. If you need to perform an action in your Suite installation that is not natively supported by InstallShield, you can create an action that calls a function from a .dll file. This .dll file can perform any function that you require, such as verifying a serial number.</span></p>
<p><span style="font-family: arial,helvetica,sans-serif;">The first step in creating an action that calls a function in a DLL is to write the DLL. InstallShield requires a precise prototype for an entry-point function in a DLL called as the result of an action. Flexera Software does not provide technical support for Windows programming or DLL debugging. You are responsible for correctly writing any DLL functions. Prototype your DLL functions as shown below. Any variation in return type or type and number of parameters can cause the action to fail.</span></p>
<p><span style="font-family: courier new,courier;">HRESULT __stdcall Foo(IDispatch*)</span></p>
<p><span style="font-family: arial,helvetica,sans-serif;">InstallShield uses the function prototype to pass the ISuiteUIExtension COM interface pointer to your DLL, which enables you to access the following functions available in the Suite bootstrap (Suite_UI.dll):</span></p>
<ul>
<li><span style="font-family: arial,helvetica,sans-serif;"><strong>BrowseFile</strong></span><br /><br /><span style="font-family: courier new,courier;"><em>HRESULT BrowseFile(BSTR bstrCaption, BSTR bstrInitialFile, BSTR* pbstrFile)<br /><br /></em></span><span style="font-family: arial,helvetica,sans-serif;">This function launches the Browse for Files or Folders dialog box when an end user clicks the control. The string of instructions that are displayed on this dialog box are typically the value of a string identifier that you specified </span>by the <em>bstrCaption</em> parameter.<br /><br /><span style="font-family: arial,helvetica,sans-serif;">The initial file that is selected on this dialog box is the full path and file name of the file that you specified by the <em>bstrInitialFile</em> parameter.<br /><br /></span><span style="font-family: arial,helvetica,sans-serif;">If the end user selects a file in this dialog box and clicks the OK button, the dialog box closes, and the function sets the <em>pbstrFile</em> parameter to the full path and file name of the file that the end user selected. If the end user clicks the Cancel button, the function returns E_FAIL.<br /><br /></span><span style="font-family: arial,helvetica,sans-serif;">If the function succeeds, it returns S_OK.<br /><br /></span></li>
<li><span style="font-family: arial,helvetica,sans-serif;"><strong>BrowseFolder<br /></strong><em><br /><span style="font-family: courier new,courier;">HRESULT BrowseFolder(BSTR bstrCaption, BSTR bstrInitialFolder, BSTR* pbstrFolder)</span></em></span><br /><br /><span style="font-family: arial,helvetica,sans-serif;">This function launches the Browse for Folder dialog box when an end user clicks the control. The string of instructions that are displayed on this dialog box is typically the value of a string identifier that you specified by the <em>bstrCaption</em> parameter. </span><br /><br /><span style="font-family: arial,helvetica,sans-serif;">The initial folder that is selected on this dialog is the full path of the folder that you specified by the <em>bstrInitialFolder</em> parameter<br /><br /></span><span style="font-family: arial,helvetica,sans-serif;">If the end user selects a folder in this dialog box and clicks the OK button, the dialog box closes, and the function sets the <em>pbstrFolder</em> parameter to the full path of the folder that the end user selected. If the end user clicks the Cancel button, the function returns E_FAIL.<br /><br /></span><span style="font-family: arial,helvetica,sans-serif;">If the function succeeds, it returns S_OK.<br /><br /></span></li>
<li><span style="font-family: arial,helvetica,sans-serif;"><strong>DoModal</strong></span><br /><br /><span style="font-family: courier new,courier;"><em>HRESULT DoModal(BSTR bstrDialogName, LONG* pnResult);</em></span><br /><br /><span style="font-family: arial,helvetica,sans-serif;">This function shows a secondary window that you specified by the <em>bstrDialogName</em> parameter as a modal window. <br /><br /></span><span style="font-family: arial,helvetica,sans-serif;">If the end user clicks the OK button, the modal window closes, and the function sets the <em>pnResult</em> parameter to IDOK. If the end user clicks the Cancel button, the function sets the <em>pnResult</em> parameter to IDCANCEL.<br /><br /></span><span style="font-family: arial,helvetica,sans-serif;">If the function succeeds, it returns S_OK.<br /><br /></span></li>
<li><span style="font-family: arial,helvetica,sans-serif;"><strong>MessageBox<br /><br /></strong></span><span style="font-family: arial,helvetica,sans-serif;"><span style="font-family: courier new,courier;"><em>HRESULT MessageBox(BSTR bstrMessage, BSTR bstrTitle, LONG nType, LONG* pnResult);<br /></em></span><strong><br /></strong>This function shows a modal dialog box that contains a system icon, and a brief message that you specified by the <em>bstrMessage</em> parameter.<br /><br /></span><span style="font-family: arial,helvetica,sans-serif;">When the end user closes the message box, the function returns and sets the <em>pnResult</em> parameter to an integer value that indicates which button the end user clicked.<br /></span><br /><br /></li>
<li><span style="font-family: arial,helvetica,sans-serif;"><strong>SetActivePage<br /><br /></strong></span><span style="font-family: courier new,courier;"><em>HRESULT SetActivePage(BSTR bstrPage);</em></span><br /><span style="font-family: arial,helvetica,sans-serif;"><span style="font-family: courier new,courier;"><strong><br /></strong><span style="font-family: arial,helvetica,sans-serif;">This function moves to a specific wizard page that you specified as the </span></span><em>bstrPage</em> parameter of this function. <br /><br /></span><span style="font-family: arial,helvetica,sans-serif;">If the function&#0160; succeeds, it returns S_OK.<br /><br /></span></li>
<li><span style="font-family: arial,helvetica,sans-serif;"><strong>OpenDocument</strong></span><br /><br /><span style="font-family: courier new,courier;"><em>HRESULT OpenDocument(BSTR bstrDocument, BSTR bstrVerb);<br /><br /></em></span><span style="font-family: arial,helvetica,sans-serif;">This function performs an operation on a file that you specified by the <em>bstrDocument</em> parameter. The bstrVerb parameter specifies the action to be performed.<br /></span><span style="font-family: arial,helvetica,sans-serif;"><br />It calls the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/bb762154(v=vs.85).aspx" target="_blank">ShellExecuteEx</a> Windows function. Typical verbs include <em>open</em>, <em>edit</em>, <em>print</em>, and <em>runas</em>. For details about the verb, refer to the lpVerb member of the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/bb759784(v=vs.85).aspx" target="_blank">SHELLEXECUTEINFO structure</a>.<br /><br /></span></li>
<li><span style="font-family: arial,helvetica,sans-serif;"><strong>LogInfo<br /></strong></span><br /><span style="font-family: arial,helvetica,sans-serif;"><em><span style="font-family: courier new,courier;">HRESULT LogInfo(BSTR bstrMessage);</span></em><span style="font-family: courier new,courier;"><strong><br /></strong></span><strong><br /></strong>This function writes a message that you specified as the <em>bstrMessage</em> parameter to a log file for your Setup.exe.<br /></span><span style="font-family: arial,helvetica,sans-serif;"><br />If the function succeeds, it returns S_OK.<br /></span><span style="font-family: arial,helvetica,sans-serif;"><strong>&#0160;</strong></span></li>
<li><span style="font-family: arial,helvetica,sans-serif;"><strong>get_Property<br /><br /></strong><span style="font-family: courier new,courier;"><em>HRESULT get_Property(BSTR bstrProperty, BSTR* pbstrValue);</em></span></span><br /><span style="font-family: arial,helvetica,sans-serif;"><span style="font-family: courier new,courier;"><strong><br /></strong><span style="font-family: arial,helvetica,sans-serif;">This function retrieves the value of a specific property that you specified as the </span></span><em>bstrProperty</em> parameter.</span><br /><span style="font-family: arial,helvetica,sans-serif;"><br />If the function succeeds, it returns S_OK.<br /></span><span style="font-family: arial,helvetica,sans-serif;"><strong>&#0160;</strong></span></li>
<li><span style="font-family: arial,helvetica,sans-serif;"><strong>put_Property<br /></strong></span><br /><span style="font-family: courier new,courier;"><em>HRESULT put_Property(BSTR bstrProperty, BSTR bstrValue);<br /></em></span><span style="font-family: arial,helvetica,sans-serif;"><br />This function sets a specific property that you specified as the <em>bstrProperty</em> parameter to a specific value.<br /><br /></span><span style="font-family: arial,helvetica,sans-serif;">If the function succeeds, it returns S_OK.<br /></span><span style="font-family: arial,helvetica,sans-serif;"><strong>&#0160;</strong></span></li>
<li><span style="font-family: arial,helvetica,sans-serif;"><strong>FormatProperty<br /><br /></strong><span style="font-family: courier new,courier;"><em>HRESULT FormatProperty(BSTR bstrValue, BSTR* bstrReturnValue);</em><strong><br /></strong></span><strong><br /></strong>This function substitutes properties using a format string in a string that you specified as the <em>bstrValue</em> parameter. When the function returns, the substituted string is set to the bstrReturnValue parameter.<br /><br /></span><span style="font-family: arial,helvetica,sans-serif;"><strong></strong></span></li>
<li><span style="font-family: arial,helvetica,sans-serif;"><strong>ResolveString<br /><br /></strong><span style="font-family: courier new,courier;"><em>HRESULT ResolveString(BSTR bstrStringId, BSTR* bstrReturnValue);<br /></em><em><br /></em></span>This function resolves a string identifier that you specified by the <em>bstrStringId</em> parameter. When the function returns, the value of the string identifier is set to the bstrReturnValue parameter.</span><br /><span style="font-family: arial,helvetica,sans-serif;"><strong>&#0160;</strong></span></li>
<li><span style="font-family: arial,helvetica,sans-serif;"><strong>get_Attribute<br /></strong></span><br /><span style="font-family: courier new,courier;"><em>HRESULT get_Attribute(BSTR bstrName, BSTR* pbstrValue);<br /><br /></em></span><span style="font-family: arial,helvetica,sans-serif;">The function is reserved for future use. It currently returns E_NOTIMPL.</span></li>
</ul>
<p><span style="font-family: arial,helvetica,sans-serif;"><br />To access the<span style="font-family: courier new,courier;"> ISuiteUIExtension </span>interface from your DLL, you need to incorporate the type library information from the SetupSuite.exe file that is installed with InstallShield. The default path is:</span></p>
<p><span style="font-family: courier new,courier;">C:\Program Files\InstallShield\2012\Redist\Language Independent\i386\SetupSuite.exe</span></p>
<p><span style="font-family: arial,helvetica,sans-serif;">The example below shows how to display a message box when an end user clicks a control:</span></p>
<p><span style="font-family: courier new,courier;">#include &quot;stdafx.h&quot;<br /></span><span style="font-family: courier new,courier;">#include &lt;atlstr.h&gt;<br /></span><span style="font-family: courier new,courier;">#import &quot;C:\Program Files\InstallShield\2012\ Redist\Language Independent\i386\SetupSuite.exe&quot; no_namespace raw_interfaces_only <br />named_guids<br /><br /></span></p>
<p><span style="font-family: courier new,courier;">HRESULT __stdcall Action(IDispatch *pDispSuiteUIExtension)<br />{<br />&#0160;&#0160;&#0160;&#0160;</span><span style="font-family: courier new,courier;">CComQIPtr&lt;ISuiteUIExtension&gt; spSuiteUIExtenstion = pDispSuiteUIExtension;</span></p>
<p><span style="font-family: courier new,courier;">&#0160;</span><span style="font-family: courier new,courier;">&#0160;&#0160;&#0160;long lResult = 0;<br /></span><span style="font-family: courier new,courier;">&#0160;&#0160;&#0160;&#0160;return spSuiteUIExtenstion-&gt;MessageBox(CComBSTR(L&quot;Hello&quot;), CComBSTR(L&quot;DLL Action&quot;), MB_OK, &amp;lResult);<br /></span><span style="font-family: courier new,courier;">}</span></p>
<p><span style="font-family: arial,helvetica,sans-serif;">Once your DLL is ready, you must add the DLL to your Suite installation, and design an action to call the entry-point function. The following is the syntax of the action statement that calls a DLL function.</span></p>
<p><span style="font-family: courier new,courier;">{<em>DLLName</em>::<em>FunctionName</em>}</span></p>
<p><span style="font-family: arial,helvetica,sans-serif;">For example, to call a function called <strong>Action</strong> in <strong>TestDLL.dll</strong> when an end user clicks the control, enter the following action statement:</span></p>
<p><span style="font-family: courier new,courier;">{<em>TestDLL</em>::<em>Action</em>}</span></p>
<p><span style="font-family: arial,helvetica,sans-serif;"><strong>To add a DLL action to your Suite project:</strong></span></p>
<ol>
<li><span style="font-family: arial,helvetica,sans-serif;">In the View List under <strong>Behavior and Logic</strong>, click <strong>Support Files</strong>.</span></li>
<li><span style="font-family: arial,helvetica,sans-serif;">In the <strong>Behavior and Logic</strong> explorer, select the <strong>Language Independent</strong> node and add <strong>TestDLL.dll</strong>.</span></li>
<li><span style="font-family: arial,helvetica,sans-serif;">In the View List under <strong>User Interface</strong>, click <strong>Wizard Interface</strong>.</span></li>
<li><span style="font-family: arial,helvetica,sans-serif;">In the <strong>Wizard Interface</strong> explorer, select the dialog that you want to modify.</span></li>
<li><span style="font-family: arial,helvetica,sans-serif;">Do one of the following:</span> 
<ul>
<li><span style="font-family: arial,helvetica,sans-serif;">To configure the action of one of the navigation controls (the Next, Back, Cancel, Install, or Finish buttons)—In the right pane, expand the settings for the control whose action you want to modify</span></li>
<li><span style="font-family: arial,helvetica,sans-serif;">To configure the action of any of the other controls—In the wizard editor, select the control whose action you want to modify.</span></li>
</ul>
</li>
<li><span style="font-family: arial,helvetica,sans-serif;">In the Action setting, enter the action statement to call a DLL function in <strong>TestDLL.dll</strong>.<br /></span><span style="font-family: courier new,courier;"><em>{TestDLL</em>::<em>Action</em>}</span></li>
</ol>
<p><span style="font-family: arial,helvetica,sans-serif;"><em>Note that actions that call a function in a DLL require InstallShield 2012 SP1. To obtain SP1, see </em><a href="http://support.installshield.com/kb/view.asp?articleid=Q201298" target="_blank"><em>Q201298</em></a><em>: InstallShield 2012 Service Pack 1. For information about the InstallShield 2012 release, see the </em><a href="http://www.demosondemand.com/DemoStage3/index.asp?sessID=FLEX002&amp;promotion_id=2635&amp;startTime=0&amp;reseller_id=undefined&amp;eo=1041161161120580470471191191190461021081011201011140971151111021161190971141010460991111090471121141111001170991161150471051101151160971" target="_blank"><em>InstallShield 2012 demo</em></a><em>.</em></span></p><img src="http://feeds.feedburner.com/~r/InstallTalk/~4/UOAY41CXh_Y" height="1" width="1"/>]]></content:encoded>


<category>Suite Installations</category>
<category>Windows Installer Tips</category>
<category>Windows Software Installation Development</category>

<dc:creator>Flexera Software</dc:creator>
<pubDate>Thu, 29 Dec 2011 14:52:01 -0600</pubDate>

<feedburner:origLink>http://blogs.flexerasoftware.com/installtalk/2011/12/calling-a-function-in-a-dll-from-a-wizard-page-or-window-in-a-suite-installation.html</feedburner:origLink></item>
<item>
<title>Using SQL Dialogs with DIM Projects</title>
<link>http://feedproxy.google.com/~r/InstallTalk/~3/D-_Lt04Gq_o/using-sql-dialogs-with-dim-projects.html</link>
<guid isPermaLink="false">http://blogs.flexerasoftware.com/installtalk/2011/12/using-sql-dialogs-with-dim-projects.html</guid>
<description>By John Cresswell With the new DIM projects we essentially support all the functionality offered from a Basic MSI project. This includes our built in SQL support; however, there are a few additional steps you will need to go through in order to configure the SQL dialogs. First a little background, so bear with me. The two dialogs used by our SQL support—SQLLogin and SQLBrowse—are added by default in a Basic MSI project when the first SQL connection is added to the project. For a DIM project this is not the case and the intended functionality is for the dialogs...</description>
<content:encoded><![CDATA[<p>By <a href="http://schmoss.acresso.com/eng/installshield/wiki/Wiki%20Pages/Writing%20Topics.aspxhttp:/blogs.flexerasoftware.com/InstallTalk/authors.html">John Cresswell</a></p>
<p>With the new DIM projects we essentially support all the functionality offered from a Basic MSI project. This includes our built in SQL support; however, there are a few additional steps you will need to go through in order to configure the SQL dialogs.</p>
<p>First a little background, so bear with me. The two dialogs used by our SQL support—SQLLogin and SQLBrowse—are added by default in a Basic MSI project when the first SQL connection is added to the project. For a DIM project this is not the case and the intended functionality is for the dialogs to be added when the DIM is consumed. Due to a problem discovered very late in the release cycle this process has a flaw that will need to be overcome. The basic idea is that the dialogs need to be added to the Basic MSI before building and the properties that the dialogs are associated with need changing to match the DIM project values.</p>
<p>When you add a SQL connection to a DIM project, the properties in the screen shot below are created and used by the SQL custom actions to connect to the intended server. As you can (barely) see they have GUIDs appended; this is necessary to ensure uniqueness with the Basic MSI projects that consume them.</p>
<p>&#0160;<a href="http://blogs.flexerasoftware.com/.a/6a010537097f24970b01543897ebc5970c-popup" onclick="window.open( this.href, &#39;_blank&#39;, &#39;width=640,height=480,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0&#39; ); return false" style="display: inline;"><img alt="Direct editor" class="asset  asset-image at-xid-6a010537097f24970b01543897ebc5970c" src="http://blogs.flexerasoftware.com/.a/6a010537097f24970b01543897ebc5970c-500wi" title="Direct editor" /></a></p>
<p>The SQL dialogs that are imported contain hard-coded properties and these properties do not have GUIDs associated with them. So by default, the dialogs that will be shown if you add a DIM file containing SQL connection data to a Basic MSI will not have the correct properties configured, and so the connection string used at runtime will be incorrect. The properties associated with controls on the dialog will be, for example, IS_SQLSERVER_USERNAME but the SQL connection will use IS_SQLSERVER_USERNAME.GUID.</p>
<p>To resolve this problem you can add the two SQL dialogs (SQLLogin and SQLBrowse) to the Basic MSI before building the project. Once the dialogs are in the project you will then need to modify certain controls , events and conditions associated to these dialogs to ensure that the correct properties are being modified by the dialogs.</p>
<p>There are two simple ways to add the dialogs to the project:</p>
<ul>
<li>Add a spurious SQL connection and then remove it.</li>
<li>Manually import the two isd files (SQLLogin.isd and SQLBrowse.isd) from the Dialogs view.</li>
</ul>
<p>In order for these dialogs to function correctly you will need to update the properties that the controls are associated with. &#0160;This can either be done from the Dialogs view or by direct editing of the tables. I created&#0160; <a href="http://blogs.flexerasoftware.com/files/SQL_DIM_Project.zip" target="_blank">sample DIM and Basic MSI projects</a> to accompany this blog and I preferred to modify the tables directly. Essentially you will need to find all instances of the properties used in the DIM&#39;s ISSQLConnection table and modify them (append the DIM GUID to them). For a default SQL Connection the following properties will need to be modified:</p>
<ul>
<li>IS_SQLSERVER_DATABASE*</li>
<li>IS_SQLSERVER_PASSWORD</li>
<li>IS_SQLSERVER_USERNAME</li>
<li>IS_SQLSERVER_AUTHENTICATION</li>
<li>IS_SQLSERVER_SERVER*</li>
</ul>
<p>*The default schema for the ControlEvent table for a Basic MSI project is a string of 50 characters. This limit is derived from Schema.msi that Microsoft ship with the platform SDK. The reason I mention this limit is that the ControlEvent table is used by the SQLBrowse dialog to set the values for the server you wish to connect to and the name database you want to use (using the properties of IS_SQLSERVER_SERVER and IS_SQLSERVER_DATABASE). The GUID is 32 characters long and so these property names with GUIDs appended will not fit the schema requirements. There are two possible approaches to work around this problem:</p>
<ul>
<li>Limit the length of the properties used for Database and Server to 15 characters or fewer. In my attached sample this is the approach I took, so you will see in the .dim file I used the properties SERVER. B7D178BF_A7D0_44DA_9246_30803A3EDB16 and DATABASE.B7D178BF_A7D0_44DA_9246_30803A3EDB16.</li>
<li>Modify the schema of the Event column in the ControlEvent table.&#0160; Note this is certainly a possible workaround and something that in and of itself will not cause a problem; however, due to issues this can create with patching (you can&#39;t change the schema of a table with a patch), I would not recommend this approach without extensive testing.</li>
</ul>
<p>From the Dialogs view you will need to modify the properties that controls on the SQLLogin dialog are using. The controls in question are:&#0160; cboServers, RadioButtonGroup1, Edtlogin, EdtPswd and EdtCatalog. The screen shot below shows the radio button group property modified to work with my sample DIM.</p>
<p><a href="http://blogs.flexerasoftware.com/.a/6a010537097f24970b01543897ecc5970c-popup" onclick="window.open( this.href, &#39;_blank&#39;, &#39;width=640,height=480,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0&#39; ); return false" style="display: inline;"><img alt="IS wizard" class="asset  asset-image at-xid-6a010537097f24970b01543897ecc5970c" src="http://blogs.flexerasoftware.com/.a/6a010537097f24970b01543897ecc5970c-500wi" title="IS wizard" /></a></p>
<p>Also on the SQLLogin dialog you will need to modify the properties used for control events for both BtnSQLBrowse and BtnDbBrowse buttons. Control events can be configured by selecting the Behavior section under the SQLLogin dialog and then selecting the Events tab on the right hand pane (the tabs are in the lower left corner of the lower right hand pane).</p>
<p><a href="http://blogs.flexerasoftware.com/.a/6a010537097f24970b01675f0d7efc970b-popup" onclick="window.open( this.href, &#39;_blank&#39;, &#39;width=640,height=480,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0&#39; ); return false" style="display: inline;"><img alt="Dialog Behavior" class="asset  asset-image at-xid-6a010537097f24970b01675f0d7efc970b" src="http://blogs.flexerasoftware.com/.a/6a010537097f24970b01675f0d7efc970b-500wi" title="Dialog Behavior" /></a></p>
<p>The final change for this dialog is for the enable disable condition. You will want to modify the conditions for lblPswd, EdtPswd, lblLoginID and EdtLogin.</p>
<p>Onto the SQLBrowse dialog; here you will need to change the events for the OK button as follows:</p>
<p><a href="http://blogs.flexerasoftware.com/.a/6a010537097f24970b01675f0d7f78970b-popup" onclick="window.open( this.href, &#39;_blank&#39;, &#39;width=640,height=480,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0&#39; ); return false" style="display: inline;"><img alt="Dialog Behavior1" class="asset  asset-image at-xid-6a010537097f24970b01675f0d7f78970b" src="http://blogs.flexerasoftware.com/.a/6a010537097f24970b01675f0d7f78970b-500wi" title="Dialog Behavior1" /></a></p>
<p>Assuming you update all the properties to match those in the DIM ISSQLConnection you should now be able to build and run and have the dialogs show up and function as you expect.</p>
<p>We will continue to refine this functionality to eventually avoid these manual steps, but in the meantime, you can follow the steps outlined above to obtain the usual SQL functionality from a DIM project.</p>
<p>The <a href="http://blogs.flexerasoftware.com/files/SQL_DIM_Project.zip" target="_blank">sample DIM and Basic MSI files</a> that I used are available for download.</p>
<p>As an alternative to this approach you can take advantage of the new UI offered with the Suite functionality that was also introduced with InstallShield 2012. For more information on how the SQL dialogs can be added to a Suite project, please take a look at Hidenori&#39;s upcoming blog article.</p>
<p><em>The ability to create DIM projects is available in the Premier edition of InstallShield. This support is also available in the InstallShield Developer Installation Manifest Editor, a new </em><a href="http://www.flexerasoftware.com/products/installshield/add-ons.htm" target="_blank"><em>collaboration add-on</em></a><em>. The ability to add DIM files to Basic MSI projects is available in the Premier edition of InstallShield.</em></p><img src="http://feeds.feedburner.com/~r/InstallTalk/~4/D-_Lt04Gq_o" height="1" width="1"/>]]></content:encoded>


<category>Suite Installations</category>
<category>Windows Installer Tips</category>
<category>Windows Software Installation Development</category>

<dc:creator>Flexera Software</dc:creator>
<pubDate>Tue, 20 Dec 2011 15:14:11 -0600</pubDate>

<feedburner:origLink>http://blogs.flexerasoftware.com/installtalk/2011/12/using-sql-dialogs-with-dim-projects.html</feedburner:origLink></item>
<item>
<title>Extension Conditions</title>
<link>http://feedproxy.google.com/~r/InstallTalk/~3/pNhVwYBcMgM/extension-conditions.html</link>
<guid isPermaLink="false">http://blogs.flexerasoftware.com/installtalk/2011/12/extension-conditions.html</guid>
<description>By Josh Stechnij InstallShield Suite installers provide a fairly robust condition system implementation, allowing for building conditions in a much more flexible manner than InstallShield prerequisites previously allowed. The Suite bootstrap uses conditions to determine what mode to run in, whether features should be selected by default, determining if a package is installed or can be allowed to install, etc. Conditions can be grouped in any combination of “none” (not), “any” (or), or “all” (and) groups. While the built-in condition types allow for checking a variety of situations (file exists; files with certain version, date/time, or contents; registry key/value exists;...</description>
<content:encoded><![CDATA[<p>By <a href="http://blogs.flexerasoftware.com/InstallTalk/authors.html" target="_blank">Josh Stechnij</a></p>
<p>InstallShield Suite installers provide a fairly robust condition system implementation, allowing for building conditions in a much more flexible manner than InstallShield prerequisites previously allowed. The Suite bootstrap uses conditions to determine what mode to run in, whether features should be selected by default, determining if a package is installed or can be allowed to install, etc. Conditions can be grouped in any combination of “none” (not), “any” (or), or “all” (and) groups. While the built-in condition types allow for checking a variety of situations (file exists; files with certain version, date/time, or contents; registry key/value exists; specific registry value data; etc.), some scenarios cannot be covered by these built-in types. For example, if the existence of a web site in IIS (or some other web server) needs to be determined, the built-in conditions cannot check for this type of system resource. In order to provide flexibility, an extension mechanism is provided by the Suite bootstrap to allow for custom conditions to be implemented through a C/C++ DLL.</p>
<p>Implementing an extension condition requires the following:<br />&#0160; - A namespace definition in setup.xml to define the resource that implements the condition<br />&#0160; - A resource definition in setup.xml to contain the extension DLL<br />&#0160; - One or more elements in a setup.xml condition block to describe the condition<br />&#0160; - A C/C++ DLL that implements the condition functionality and interfaces with a Suite installer</p>
<p><strong>Authoring Extension Conditions</strong><br />Built-in conditions are structured as follows in the setup.xml file that drives the Suite bootstrap:</p>
<p>&lt;GroupType&gt;<br />&#0160;&#0160;&#0160;&#0160; &lt;ConditionType Attribute1=&quot;…&quot; Attribute2=&quot;…&quot; /&gt;<br />&lt;/GroupType&gt;</p>
<p>A condition type is defined by the element name of the condition, and any parameters for the condition are provided through attribute name/value pairs. Extension conditions follow the same semantic definition but use XML namespace definitions to provide some additional information. The root setup element contains a namespace definition to indicate that a resource DLL implements the extension condition validation and evaluation functionality:</p>
<p>&lt;setup xmlns=&quot;installshield/2012/bootstrap&quot; <span style="color: #033d21;"><strong>xmlns:testext=&quot;testext.dll</strong>&quot;</span> SuiteId=&quot;…&quot;&gt;</p>
<p>In the above example setup element, the ‘testext’ namespace definition indicates testext.dll is a resource DLL that will implement any conditions residing in the ‘testext’ namespace. An extension condition can then be defined; it is implemented by testext.dll as follows:</p>
<p>&lt;<span style="color: #033d21;"><strong>testext:TestExtensionCondition </strong></span>Attribute1=&quot;value1&quot; Attribute2=&quot;value2&quot; /&gt;</p>
<p>The above extension condition defines a condition, TestExtensionCondition, and indicates this is implemented by the DLL defined by the ‘testext’ namespace defined in the setup element. The extension name (TestExtentionCondition) also defines the base names of the entry points the extension DLL must implement and export. The attributes are arbitrary names whose values can be retrieved when the bootstrap calls the extension DLL to validate and evaluate the condition.</p>
<p>A resource entry in setup.xml is the last item required to define an extension condition. Resources are normally streamed into a setup.exe at build time so that no external files are required to launch the setup. To define a resource for the extension DLL, a resource element in the Resources group is defined:</p>
<p>&lt;Resources&gt;<br />&#0160;&#0160;&#0160;&#0160; <span style="color: #033d21;"><strong>&lt;Resource Source=&quot;PathToResourceFile&quot; Namespace=&quot;testext.dll&quot; /&gt;</strong></span><br />&lt;/Resources&gt;</p>
<p>Note: in a Suite project file, there are multiple ‘resources’ groups. One group is defined for the user interface and another is defined for support files needed to run the setup. To define an extension DLL resource, ensure the new resource element is added to the correct group. To simplify this process, add the extension DLL to the Language Independent node in the Support Files view and then edit the project file in a text/XML editor to add the Namespace attribute to the resource element that the IDE created.</p>
<p>The resource element defines that this DLL is streamed into setup.exe with the name testext.dll. The Namespace attribute links the resource to the XML namespace defined for the extension DLL in the setup element.</p>
<p><strong>Implementing the Extension DLL</strong><br />With the setup.xml authored to use an extension DLL, the entry points in the DLL need to be authored. The Suite bootstrap expects two entry points per condition, one to validate the condition and one to evaluate the condition. Both entry points are based on the name of the extension condition. In the above setup.xml example, the extension condition is named TestExtensionCondition. The DLL implementing this condition must export the following entry points:</p>
<p>TestExtensionCondition_Validate<br />TestExtensionCondition_Evaluate</p>
<p>These functions should be defined as follows:</p>
<p>HRESULT __stdcall TestExtensionCondition_Validate(IDispatch *pCondition);<br />HRESULT __stdcall TestExtensionCondition_Evaluate(IDispatch*pCondition, VARIANT_BOOL *pbEvalResult);</p>
<p>The validation entry point is called while the bootstrap is parsing setup.xml conditions and provides an opportunity for the extension condition to ensure the condition attributes defined by setup.xml are suitable for the condition to evaluate in a predictable manner. This entry point is called any time an extension condition of this type is found in setup.xml. Returning S_OK from this entry point indicates to the Suite that the condition is valid. Returning a failed HRESULT status will cause the Suite to abort with an error for the condition that was last validated.</p>
<p>The evaluation entry point is called at any time an extension condition of this type is referenced by setup.xml. The evaluation is allowed to perform any action necessary to evaluate the condition** to a true or false result. The result is returned in the form of a VARIANT_BOOL in the pbEvalResult parameter. A result of VARIANT_TRUE is treated as a true result and a result of VARIANT_FALSE is treated as a false result. A success status (S_OK) should be returned from an evaluation function. A failure status will currently abort the evaluation of the current condition block being evaluated but will not cause the setup to abort.</p>
<p>** While any action is allowed by the bootstrap, extension conditions run with the privileges of the Suite setup that they are called from. Some actions may require administrator privileges (such as reading IIS 7.x configuration data). In such cases, the setup would need to be run with or be manifested to require administrator privileges for the condition to access needed data successfully.</p>
<p>The IDispatch interface passed to the validation and evaluation entry points implements the ISuiteExtension interface. A pointer to an ISuiteExtension can be obtained by calling the QueryInterface method on the IDispatch interface. The ISuiteExtension interface allows the condition functions to access the attribute parameters defined for the extension condition in setup.xml. Note that each condition in setup.xml will receive a different interface pointer that is specific to each condition instance. Therefore, the interface pointer passed to the entry point function should always be used and should not be saved across calls to the extension DLL.</p>
<p>The interface is currently defined as follows:</p>
<p><span style="color: #0000bf;">interface</span> ISuiteExtension : IDispatch {<br />&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160; [<span style="color: #0000bf;">propget</span>, <span style="color: #0000bf;">id</span>(1), <span style="color: #0000bf;">helpstring</span><span style="color: #c00000;"><span style="color: #111111;">(</span>&quot;Attribute&quot;<span style="color: #111111;">)]</span></span><br />&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;HRESULT Attribute([in]BSTR bstrName, [<span style="color: #0000bf;">out</span>, <span style="color: #0000bf;">retval</span>]BSTR *bstrValue);</p>
<p>&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160; [<span style="color: #0000bf;">id</span>(2), <span style="color: #0000bf;">helpstring</span>(<span style="color: #c00000;">&quot;method LogInfo&quot;</span>)]<br />&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160; HRESULT LogInfo([in]BSTR bstr);</p>
<p>&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160; &#0160;[<span style="color: #0000bf;">propget, id</span>(3), <span style="color: #0000bf;">helpstring</span>(<span style="color: #c00000;">&quot;Property&quot;</span>)]<br />&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160; HRESULT Property([in]BSTR bstrName, [<span style="color: #0000bf;">out</span>, <span style="color: #0000bf;">retval</span>]BSTR *bstrValue);</p>
<p>&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160; [<span style="color: #0000bf;">propput</span>, <span style="color: #0000bf;">id</span>(3), helpstring(<span style="color: #c00000;">&quot;Property&quot;</span>)]<br />&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160; HRESULT Property([<span style="color: #0000bf;">in</span>]BSTR bstrName, [<span style="color: #0000bf;">in</span>]BSTR bstrValue);</p>
<p>&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160; [<span style="color: #0000bf;">id</span>(4), <span style="color: #0000bf;">helpstring</span>(<span style="color: #c00000;">&quot;FormatProperty&quot;</span>)]<br />&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160; HRESULT FormatProperty([<span style="color: #0000bf;">in</span>]BSTR bstrValue, [<span style="color: #0000bf;">out</span>, <span style="color: #0000bf;">retval</span>]BSTR *bstrReturnValue);</p>
<p>&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160; [<span style="color: #0000bf;">id</span>(5), <span style="color: #0000bf;">helpstring</span>(<span style="color: #c00000;">&quot;ResolveString&quot;</span>)]<br />&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160; HRESULT ResolveString([<span style="color: #0000bf;">in</span>]BSTR bstrStringId, [<span style="color: #0000bf;">out</span>, <span style="color: #0000bf;">retva</span>l]BSTR *bstrReturnValue);<br />};</p>
<p>The following methods are provided by ISuiteExtension for use by an extension DLL:</p>
<p>HRESULT get_Attribute([in]BSTR bstrName, [out, retval]BSTR *bstrValue);</p>
<p>This method can be used to retrieve the value of an attribute for the current condition instance. The attribute name is passed in bstrName and its corresponding value is returned in bstrValue.</p>
<p>HRESULT LogInfo([in]BSTR bstr);</p>
<p>This method can be used to write any information needed to the setup Suite debug log that may be useful for debugging or other informational purposes. The bstr parameter contains the string to be written to the log.</p>
<p>HRESULT get_Property([in]BSTR bstrName, [out, retval]BSTR *bstrValue);</p>
<p>This method can be used to retrieve the value of any property currently defined in the running Suite. Properties that are not defined will return an empty value. The bstrName parameter specifies the name of the property to obtain the value for. The value for the property will be returned in the bstrValue parameter.</p>
<p>HRESULT put_Property([in]BSTR bstrName, [in]BSTR bstrValue);</p>
<p>This method can be used to set the value of a new property or change the value of an existing property in the currently running Suite. Passing an empty value effectively deletes the property. The bstrName parameter specifies the name of the property to set. The bstrValue parameter specifies the value to set for the specified property.</p>
<p>HRESULT FormatProperty([in]BSTR bstrValue, [out, retval]BSTR *bstrReturnValue);</p>
<p>This method can be used to format a string that contains embedded property references (in the form ‘[PROPERTYNAME]’) in the string provided in the bstrValue parameter. The formatted value is returned in the bstrReturnValue parameter. Note that only one level of property references is formatted. If one property’s formatted value contains another property reference, this method will not format the second property.</p>
<p>HRESULT ResolveString([in]BSTR bstrStringId, [out, retval]BSTR *bstrReturnValue);</p>
<p>This method can be used to resolve a Suite string identifier into the corresponding string value for the currently running Suite installation in the currently selected UI language. The bstrStringId parameter specifies the string identifier to resolve, and the resolved string is returned in bstrReturnValue. If no such string identifier exists, the returned string is empty.</p>
<p><strong>Building an Extension DLL</strong><br />An extension condition DLL can be built with any recent version of Visual C++ or any tool/language that supports COM and DLL exports. When any extension DLL is built with Visual C++, the interface definition for the ISuiteExtension interface can be obtained by using #import to import the type library provided with the setup Suite executable starting with InstallShield 2012 SP1. The following statement can be used to import the type library in a VC++ project (such as in stdafx.h):</p>
<p>#import &quot;C:\Program Files\InstallShield\2012\Redist\Language Independent\i386\SetupSuite.exe&quot; no_namespace raw_interfaces_only named_guids</p>
<p>Note that if InstallShield is installed to a different location, the path in the #import statement above needs to be adjusted to the correct location.</p>
<p>For a sample extension condition, download the <a href="http://blogs.flexerasoftware.com/files/SuiteExtensionSample.zip" target="_blank">SuiteExtensionSample.zip</a> file. This file contains a sample extension DLL project created with Visual Studio 2008 and an InstallShield Suite project that uses the extension DLL for an extension condition in the eligibility condition of a package in the Suite project. Note that to build the DLL project, Visual Studio 2008 or newer with ATL support is required. (Express editions of VC++ do not include ATL support.) The #import path to the setup Suite type library in stdafx.h may also need to be adjusted for the project to build correctly.</p>
<p><em>Suite support is available in <a href="http://learn.flexerasoftware.com/content/IS-EVAL-InstallShield-Premier" target="_blank">InstallShield 2012 Premier Edition</a>. For a list of additional Premier-only features, visit the <a href="http://www.flexerasoftware.com/products/installshield/editions.htm" target="_blank">InstallShield Editions </a>page.</em></p><img src="http://feeds.feedburner.com/~r/InstallTalk/~4/pNhVwYBcMgM" height="1" width="1"/>]]></content:encoded>


<category>Suite Installations</category>
<category>Windows Installer Tips</category>
<category>Windows Software Installation Development</category>

<dc:creator>Flexera Software</dc:creator>
<pubDate>Wed, 14 Dec 2011 15:30:59 -0600</pubDate>

<feedburner:origLink>http://blogs.flexerasoftware.com/installtalk/2011/12/extension-conditions.html</feedburner:origLink></item>
<item>
<title>Putting the “Wizard” in Wizard Pages</title>
<link>http://feedproxy.google.com/~r/InstallTalk/~3/ZnBKGKxnZDM/putting-the-wizard-in-wizard-pages.html</link>
<guid isPermaLink="false">http://blogs.flexerasoftware.com/installtalk/2011/12/putting-the-wizard-in-wizard-pages.html</guid>
<description>By Michael Urman While InstallShield makes it easy to change the UI of your Suite project in small ways, such as editing the text on a wizard page, or moving a control by a few pixels, sometimes that's not enough. Sometimes you need to add a new page to your wizard. There are three approaches you can take to adding a new page. I want to share them and tell you a way to make the third one even more powerful. The Role of an Intern The first way to add a page to the wizard is completely manually. In...</description>
<content:encoded><![CDATA[<p>By <a href="http://blogs.flexerasoftware.com/InstallTalk/authors.html" target="_blank">Michael Urman </a></p>
<p>While InstallShield makes it easy to change the UI of your Suite project in small ways, such as editing the text on a wizard page, or moving a control by a few pixels, sometimes that's not enough. Sometimes you need to add a new page to your wizard. There are three approaches you can take to adding a new page. I want to share them and tell you a way to make the third one even more powerful.</p>
<h2>The Role of an Intern</h2>
<p>The first way to add a page to the wizard is completely manually. In the Wizard Interface view, right-click the Wizard Pages node and select <strong>Add Blank Page</strong>. Set its title, turn on wizard buttons, add controls, and configure any additional settings to make the page do what you want.</p>
<p><img src="http://blogs.flexerasoftware.com/.a/6a010537097f24970b015393dc5394970b-pi" alt="" width="531" height="312" /></p>
<p>If the new page you want is similar to one you have, either because you just created one of several similar pages, or because InstallShield already provided one that was close, you can copy and paste in the list of pages to clone a page into a new one.</p>
<h2>The Role of a Development Tool</h2>
<p>The second way to add a page is through copy and paste in the project file (.issuite). Cloning a wizard page in the IDE can work wonders. However it comes with one major limitation: you can clone a page only within the same project. So if you need to go between two projects, you can open the project in an XML editor to copy pages from one project to another. Look for the <strong>Page</strong> elements with the <strong>Name</strong> attributes matching the pages you want to copy. They appear in the same order that you saw the pages in the Wizard Interface view, so they should be easy to find. Copy entire <strong>Page</strong> elements (from &lt;Page …&gt; to &lt;/Page&gt;) and paste them in your other project.</p>
<p><img src="http://blogs.flexerasoftware.com/.a/6a010537097f24970b015393dc539d970b-pi" alt="" width="570" height="261" /></p>
<p>If the page you copy uses only strings that are provided by InstallShield, you're done. However if it references any strings that you added yourself, you'll probably see things like ID_STRING17 when you run your Suite. To fix this you may need to copy the string definitions too. You can find them under the <strong>Languages</strong> element, one copy of your string in an element of the string ID's name, for each <strong>Language</strong> element.</p>
<h2>The Role of an Architect</h2>
<p>The third way to add a page to your wizard is by inserting it from the User Interface Wizard, which you access by right-clicking the Wizard Pages node and selecting <strong>Add Predefined Page…</strong>. InstallShield 2012 comes with six predefined pages that range from selecting a package's INSTALLDIR to accepting a supplemental EULA. The Wizard asks you where to sequence the new page, and may ask one more question such as which package's INSTALLDIR you want to change, or what EULA file you want to show.</p>
<p><img src="http://blogs.flexerasoftware.com/.a/6a010537097f24970b0162fd31c6ff970d-pi" alt="" width="579" height="398" /></p>
<p>But that's not all. If you want to change how a page looks in most of your Suites, including some you've already created, you can create your own template page with these changes in place. Start by modifying the InstallationWelcome page's layout to match what you want. For example, resize the labels to stretch the whole width, set the SS_CENTER Style on all the labels, and center the image above. Save the project, and go find its <strong>Page</strong> element, and copy it.</p>
<p><img src="http://blogs.flexerasoftware.com/.a/6a010537097f24970b0162fd31c704970d-pi" alt="" width="582" height="492" /></p>
<p>Then open <strong>&lt;InstallShield&gt;\Support\0409\SuiteTemplates.xml</strong>. This file contains definitions for all the templates shown in the wizard, in a format very similar to that in a project. Put in some boilerplate information, including a name and description for your new page template.</p>
<p><img src="http://blogs.flexerasoftware.com/.a/6a010537097f24970b015393dc53a6970b-pi" alt="" /></p>
<p>Paste your page definition inside the <strong>v:WizardPage</strong> element.</p>
<p><img src="http://blogs.flexerasoftware.com/.a/6a010537097f24970b015393dc53ae970b-pi" alt="" width="575" height="98" /></p>
<p>For simple pages, save it and you're done. Now you can add your custom welcome page to any project; just remove the original and your Suite is ready to go.</p>
<p>For more complex pages, you can tell the User Interface Wizard to ask for a package or a file by including a <strong>Variable</strong> element with a <strong>Choose</strong> attribute of <strong>Parcel</strong> or <strong>File</strong>; see a template that uses those to figure out how they work. Note that references to variables need to be in attributes that have a <strong>v</strong> prefix on their attribute name, and the reference uses double hashes. Some variable names also receive several sub-variables. You can see most of this in the <em>View and accept supplemental license agreement</em> template (the remaining capabilities show up in the <em>Browse for installation folder</em> template):</p>
<p><img src="http://blogs.flexerasoftware.com/.a/6a010537097f24970b015437afe0df970c-pi" alt="" width="581" height="191" /></p>
<p>Just remember that this is currently an implementation detail of <a href="http://learn.flexerasoftware.com/content/IS-Contact-Us-InstallShield-2012-Customer-Upgrade" target="_blank">InstallShield 2012</a>. We expect to have to change the project's XML format over time, and that will result in changes to the SuiteTemplates.xml format as well. If nothing else, expect the namespace to be updated, so be very careful about blindly copying any of your customizations of SuiteTemplates.xml to a new version of InstallShield.&nbsp;</p><img src="http://feeds.feedburner.com/~r/InstallTalk/~4/ZnBKGKxnZDM" height="1" width="1"/>]]></content:encoded>


<category>Software Deployment, Licensing, and Activation</category>
<category>Suite Installations</category>
<category>Windows Installer Tips</category>
<category>Windows Software Installation Development</category>

<dc:creator>Flexera Software</dc:creator>
<pubDate>Thu, 01 Dec 2011 15:30:18 -0600</pubDate>

<feedburner:origLink>http://blogs.flexerasoftware.com/installtalk/2011/12/putting-the-wizard-in-wizard-pages.html</feedburner:origLink></item>
<item>
<title>Using the Hyperlink Control in a Suite Installation</title>
<link>http://feedproxy.google.com/~r/InstallTalk/~3/kznAAGC3zeg/using-the-hyperlink-control-in-a-suite-installation.html</link>
<guid isPermaLink="false">http://blogs.flexerasoftware.com/installtalk/2011/11/using-the-hyperlink-control-in-a-suite-installation.html</guid>
<description>By Richard Woods Have you ever wanted to add a web link to your setup? It is quick and easy to do with the Suite project hyperlink control. Adding the Hyperlink Control Open up your Suite project. Browse to the Wizard Interface view. Select the wizard page you want to add a hyperlink to. Click on the hyperlink control on the toolbar: Size and position your new hyperlink control to the size and position you want. In the Text field, enter the text you would like to appear on the dialog. Ex: Support Page In the Target URL field, enter...</description>
<content:encoded><![CDATA[<p>By <a href="http://blogs.flexerasoftware.com/InstallTalk/authors.html" target="_blank">Richard Woods </a></p>
<p>Have you ever wanted to add a web link to your setup? It is quick and easy to do with the Suite project hyperlink control.</p>
<h2>Adding the Hyperlink Control</h2>
<ol>
<li>Open up your Suite project. </li>
<li>Browse to the Wizard Interface view. </li>
<li>Select the wizard page you want to add a hyperlink to. </li>
<li>Click on the hyperlink control on the toolbar:<br /><img alt="" src="http://blogs.flexerasoftware.com/.a/6a010537097f24970b0154379400aa970c-pi" /> </li>
<li>Size and position your new hyperlink control to the size and position you want. </li>
<li>In the Text field, enter the text you would like to appear on the dialog. Ex: Support Page </li>
<li>In the Target URL field, enter the URL that you want to navigate to when the hyperlink is clicked. Ex: http://www.MycompanyURL.Com/support </li>
<li>Build and run your project. </li>
</ol>
<p>You should see the hyperlink on your wizard page, and clicking it will navigate to the URL you specified.</p>
<p><img alt="" height="318" src="http://blogs.flexerasoftware.com/.a/6a010537097f24970b0162fd15f094970d-pi" width="564" /></p>
<h2>Using a Property for Target URL</h2>
<p>If you would like to use a property for your URL instead of hard coding the address, this is easy to do as well.</p>
<ol>
<li>Navigate to the Property Manager view. </li>
<li>Click the &quot;New&quot; button. </li>
<li>Specify a property name. Ex: SupportURL </li>
<li>Specify a web address in the Value field. Ex: http://www.MycompanyURL.Com/support </li>
<li>Navigate back to your wizard page in the Wizard Interface view. </li>
<li>Change the Target URL to the property name you specified, enclosed in brackets. Ex: [SupportURL] </li>
<li>Build and run the installation. </li>
</ol>
<p>The hyperlink will now navigate to the web page specified in your property.</p>
<h2>Using an Action with your Hyperlink</h2>
<p>What if in addition to browsing to a URL, you also wanted to perform an additional action when a hyperlink is clicked? You can do this too. The details of what actions you can perform are described in the help topic <a href="http://helpnet.flexerasoftware.com/Robo/BIN/Robo.dll?tpc=/robo/projects/installshield18helplib/SteUIAction.htm" target="_blank">Configuring an Action for a Control on a Wizard Page or Window</a>. But for now, let&#39;s walk through opening a file.</p>
<ol>
<li>In the action field, enter: {Open ReleaseNotesFile} </li>
<li>Browse to the Support Files view. </li>
<li>Add the file you would like to open. Ex: ReleaseNotes.txt </li>
<li>Browse to the Property Manager view. </li>
<li>Click the &quot;New&quot; button. </li>
<li>Specify a property name. Ex: ReleaseNotesFile </li>
<li>Specify the file location for the property&#39;s value. Ex: [SETUPSUPPORTDIR]\ReleaseNotes.txt </li>
<li>Build and run the installation. </li>
</ol>
<p>The hyperlink will now navigate to the web page specified, and open ReleaseNotes.txt.</p>
<p>If you want to open only a file with the hyperlink control, you just specify the path directly in the Target URL field and do not specify anything for Action. Ex: <span style="font-family: Courier New;">[SETUPSUPPORTDIR]\ReleaseNotes.txt</span></p>
<p>Or, if you wanted to open the file with a button instead of a hyperlink control, you could specify the same action you did for the hyperlink control in the button&#39;s Action field. Ex: <span style="font-family: Courier New;">{Open ReleaseNotesFile}</span></p>
<p><em>For more how-to information, review the <a href="http://www.flexerasoftware.com/resources/tips-tricks.htm" target="_blank">InstallShield Tips &amp; Tricks</a>.</em></p><img src="http://feeds.feedburner.com/~r/InstallTalk/~4/kznAAGC3zeg" height="1" width="1"/>]]></content:encoded>


<category>Software Deployment, Licensing, and Activation</category>
<category>Suite Installations</category>
<category>Windows Installer Tips</category>
<category>Windows Software Installation Development</category>

<dc:creator>Flexera Software</dc:creator>
<pubDate>Tue, 29 Nov 2011 12:31:06 -0600</pubDate>

<feedburner:origLink>http://blogs.flexerasoftware.com/installtalk/2011/11/using-the-hyperlink-control-in-a-suite-installation.html</feedburner:origLink></item>
<item>
<title>Using Active Setup to Repair User Settings</title>
<link>http://feedproxy.google.com/~r/InstallTalk/~3/R0sDU80efPA/using-active-setup-to-repair-user-settings.html</link>
<guid isPermaLink="false">http://blogs.flexerasoftware.com/installtalk/2011/11/using-active-setup-to-repair-user-settings.html</guid>
<description>By Alan Burns One of the things that we teach students in the InstallShield and AdminStudio training classes is to use advertised shortcuts if at all possible. A Windows Installer advertised shortcut causes Windows to verify that all of the application's component key paths are in place before launching the application. If a key path is missing, Windows Installer will try to repair the application before launching the program. This is an appropriate way to repair user-specific data, including files in the user's profile directories (e.g. "My Documents") and registry data in HKEY_CURRENT_USER. We often see the need to repair...</description>
<content:encoded><![CDATA[<p>By <a href="http://blogs.flexerasoftware.com/InstallTalk/authors.html" target="_blank">Alan Burns</a></p>
<p>One of the things that we teach students in the InstallShield and AdminStudio training classes is to use advertised shortcuts if at all possible.  A Windows Installer advertised shortcut causes Windows to verify that all of the application&#39;s component key paths are in place before launching the application.  If a key path is missing, Windows Installer will try to repair the application before launching the program.  This is an appropriate way to repair user-specific data, including files in the user&#39;s profile directories (e.g. &quot;My Documents&quot;) and registry data in HKEY_CURRENT_USER.  We often see the need to repair user-specific data if one user installs a program and then a different user logs onto the computer and tries to run it.</p>
<p>Advertised shortcuts work well for repairing user-specific data if the application has shortcuts.  What about programs that don&#39;t have shortcuts, such as add-ins for Microsoft Office?  For these cases, Windows offers the Active Setup registry keys.  These are two registry keys that Windows uses to decide whether an application is installed for a user as they are logging into Windows.</p>
<p>The basic idea is to create a per-machine registry key in HKEY_LOCAL_MACHINE and then compare that key with a similar key in HKEY_CURRENT_USER.  If the version information in the keys is different, then Windows runs a command specified in the HKEY_LOCAL_MACHINE key and updates the version data so that the command does not run again.  A flowchart of the process is shown in Figure 1.</p>
<p><img alt="" src="http://blogs.flexerasoftware.com/.a/6a010537097f24970b01543746bb23970c-pi" /></p>
<p><span style="color: #4f81bd; font-size: 9pt;"><strong>Figure 1: The process of executing Active Setup commands </strong></span></p>
<h2>Creating Active Setup keys in InstallShield</h2>
<p>To make Active Setup work with your setup, you must have the setup write values to the following registry key:</p>
<p style="margin-left: 18pt;"><span style="font-family: Courier New; font-size: 8pt;">HKEY_LOCAL_MACHINE\Software\Microsoft\Active Setup\Installed Components\[ProductCode] </span></p>
<p>The values are:</p>
<p style="margin-left: 18pt;"><span style="font-family: Courier New; font-size: 8pt;">&quot;@&quot;=[ProductName] </span></p>
<p style="margin-left: 18pt;"><span style="font-family: Courier New; font-size: 8pt;">&quot;StubPath&quot;=&quot;msiexec.exe /fou [ProductCode] /qb&quot; </span></p>
<p style="margin-left: 18pt;"><span style="font-family: Courier New; font-size: 8pt;">&quot;Version&quot;=&quot;1,0,0&quot; </span></p>
<p>This registry information is shown graphically in Figure 2, which shows an example InstallShield project with Active Setup data.  Note that the Version value is delimited with commas, not periods.</p>
<p><img alt="" height="306" src="http://blogs.flexerasoftware.com/.a/6a010537097f24970b0162fcc87bb5970d-pi" width="586" /></p>
<p><span style="color: #4f81bd; font-size: 9pt;"><strong>Figure 2: An InstallShield project showing the Active Setup data in HKEY_LOCAL_MACHINE </strong></span></p>
<p>When the end user logs into the computer, Active Setup will compare the registry key in HKLM with the corresponding key in HKCU.  If the version in HKCU is less than the one in HKLM or the HKCU key does not exist, Windows will copy some of the values from the HKLM key to the HKCU key and then execute the command in the &quot;StubPath&quot; value.</p>
<p>At some point, the user who originally ran the setup will log off and then log into the computer again.  If the setup did not write any Active Setup information to HKCU, Active Setup will run the repair unnecessarily for this user.  The solution in this case is to use the setup to write some additional registry data to the HKCU key.  The key and values are shown graphically in Figure 3 and the text of the values is shown below.  Note that this data does not include a StubPath value.</p>
<p style="margin-left: 18pt;"><span style="font-family: Courier New; font-size: 8pt;">HKEY_CURRENT_USER\Software\Microsoft\Active Setup\Installed Components\[ProductCode] </span></p>
<p>Value:</p>
<p style="margin-left: 18pt;"><span style="font-family: Courier New; font-size: 8pt;">&quot;Version&quot;=&quot;1,0,0&quot; </span></p>
<p><img alt="" height="283" src="http://blogs.flexerasoftware.com/.a/6a010537097f24970b01543746bb30970c-pi" width="592" /></p>
<p><span style="color: #4f81bd; font-size: 9pt;"><strong>Figure 3: An InstallShield project showing the Active Setup data in HKEY_CURRENT_USER </strong></span></p>
<p>After installing the program, the user who installed it will be able to log off of and back onto Windows without seeing a progress dialog from Windows Installer.  Any other users will see the Windows Installer progress window, show in Figure 4, the next time they log into Windows as the setup writes missing data to their profile.</p>
<p><img alt="" src="http://blogs.flexerasoftware.com/.a/6a010537097f24970b0153937326d0970b-pi" /></p>
<p><span style="color: #4f81bd; font-size: 9pt;"><strong>Figure 4: The Windows Installer </strong></span></p>
<h2>Considerations for Deploying Setups that use Active Setup</h2>
<p>One issue that system administrators frequently encounter with Active Setup is ensuring that Windows Installer can locate the source media to complete the repair invoked by Active Setup.  Windows Installer needs the source media to copy files into the user&#39;s profile folders.  In an environment where workstations are connected to the network, you can put the source media on a server and make sure that the SOURCELIST property points to the appropriate directory on the server.</p>
<p>In an environment where users don&#39;t have access to network servers, you may want to copy the source media to a location like:</p>
<p style="background: #f2f2f2; margin-left: 18pt;"><span style="font-family: Consolas; font-size: 10pt;">[CommonAppDataFolder]\[Manufacturer]\[ProductName] Setup\ </span></p>
<p>For example:</p>
<p style="background: #f2f2f2; margin-left: 18pt;"><span style="font-family: Consolas; font-size: 10pt;">C:\ProgramData\Sample Co\Sample App 3000 Setup\ </span></p>
<p>By putting the installation media in a commonly accessible location, you are ensuring that Windows Installer will succeed in repairing the application&#39;s per-user data regardless of which user initiates the repair.</p>
<h2>Links for More Information</h2>
<p>For those readers who would like to find more information about Active Setup, I&#39;ve included a few links below.</p>
<p><strong><a href="http://www.flexerasoftware.com/webdocuments/PDF/repackaging_questions.pdf?link_id=productsTipsTricks" target="_blank">3 Tips for Your Repackaging-Related Questions</a> (See Tip 1 – How to Repair User-Specific Data for Applications without Shortcuts or Executables) </strong></p>
<p><strong><a href="http://www.appdeploy.com/articles/activesetup.asp" target="_blank">AppDeploy.com - Active Setup </a></strong></p>
<p><strong><a href="http://www.symantec.com/community/node/6441" target="_blank">Forcing a Repair When Your Application Has No Entry Points [Active Setup]</a> </strong></p>
<p style="text-align: justify; margin-left: 18pt;"><span style="font-family: Verdana; font-size: 8pt;"> </span></p><img src="http://feeds.feedburner.com/~r/InstallTalk/~4/R0sDU80efPA" height="1" width="1"/>]]></content:encoded>


<category>Software Deployment, Licensing, and Activation</category>
<category>Windows Installer Tips</category>
<category>Windows Software Installation Development</category>

<dc:creator>Flexera Software</dc:creator>
<pubDate>Wed, 23 Nov 2011 10:34:41 -0600</pubDate>

<feedburner:origLink>http://blogs.flexerasoftware.com/installtalk/2011/11/using-active-setup-to-repair-user-settings.html</feedburner:origLink></item>

</channel>
</rss><!-- ph=1 -->

