xanax onlineAdderallLevitraCialis onlinepuppies for sale

Developing for SharePoint 2007

It can be very tricky getting a development environment set up for SharePoint 2007, as the path is strewn with pitfalls and blockades. Having recently completed a SharePoint 2007 project, I felt compelled to share some of the trouble I ran into along the way and the solutions I found.

In order to properly develop for SharePoint 2007, it is necessary for SharePoint 2007 and Visual Studio 2008 to be installed on the same machine. This allows Visual Studio to access local file storage on the SharePoint server for deployment purposes, and supports debugging of assemblies running in the SharePoint environment. In most corporate environments, IT would not look too fondly upon a developer installing Visual Studio on the production server, so a separate development server is generally used. These days, most servers are running a 64-bit operating system in order to take advantage of more than 4GB of memory. However, this is where the first pitfall is encountered.

Visual Studio 2008 does not support debugging SharePoint in a 64-bit environment.

Thus the development environment must be set up on a 32-bit server OS. Windows Server 2008 R2 is only available in a 64-bit version, so either the original release of Windows Server 2008 or Windows Server 2003 must be used. I used Windows Server 2003 SP2 for my development environment. I also set up my development environment using a virtual machine and would highly recommend this approach. There were numerous times where it was necessary to roll-back to a good snapshot point after getting SharePoint into a non-functional state.

To help get you set up with the necessary components, the following list includes all of the relevant software installed in my development environment. While you may not need all of these pieces depending on your development needs, it at least gives a fairly comprehensive listing:

Hopefully this information will be helpful for others trying to set up a functional SharePoint 2007 development environment.

RSS Feed Add to Technorati Favorites Add to Del.icio.us Stumble It! Submit to Slashdot Submit to Buzz! Digg It!

May 23, 2010 • Posted in: SharePoint • No Comments

Introducing OSoSLO EZTiler

OSoSLO is a new software company I founded which began online operations today. This company is an outgrowth of my consulting business, and will focus on the development of specialized tools for software engineering operations.

The debut product for OSoSLO is called EZTiler. This graphical application can produce high-quality seamless tile images quickly and easily from virtually any photograph or graphic design. EZTiler is distributed as a 30-day try-before-you-buy application, so please visit the OSoSLO web site for the free trial download.

RSS Feed Add to Technorati Favorites Add to Del.icio.us Stumble It! Submit to Slashdot Submit to Buzz! Digg It!

July 8, 2009 • Posted in: Announcements • No Comments

Practical Prioritization

I began this series of articles with a post titled “Issue Prioritization“, where I described some of the drawbacks of traditional prioritization schemes, and proposed a new scale for measuring priorities. The next post titled “Multidimensional Prioritization” explored how prioritization values could be derived a set of orthogonal factors, each of which could be measured objectively. The process for producing such prioritization values may have appeared quite daunting, especially when compared to a more typical method of subjectively assigning a number between 1 and 5. In this post, I will present methods for making the proposed prioritization process simpler and easier to implement.

Mapping ROI to Priority

Before getting into the process simplification discussion, I would like to address one other issue that came up in the previous post. As discussed earlier, the scaled ROI value is the composite of the Impact, Frequency and Scope factors. The ROI value is expected to represent a proportional measure of priority. The problem is that the scaled ROI value spans a range from -13…27, while the desired range for the priority value is 0…10. The challenge is how to best map ROI values to the desired range for priority values.

To start with, let’s revisit what the ROI value actually represents. The Return On Investment is equal to (Added Value) / (Implementation Cost). Given this, a full-scale ROI value of 1 would indicate that the implementation cost would be recouped in a one year period. For all practical purposes, any issue with an ROI of 0.1% or less would not be worth consideration. This corresponds to a scaled ROI value of -3, so any values below this level could be treated as equivalent to -3.

Similarly, issues with very high ROI values (let say of 1,000,000,000%) would be so rare that there is no point in extending the range that high. Thus the upper end of the scaled ROI range could be effectively capped at 7. This clipped range of -3…7 for scaled ROI can now be easily mapped to the target range of 0…10 for the scaled prioritization value by simply adding 3 to the scaled ROI value.

Simplifying the Prioritization Process

The one area where computers are far superior to human beings is in the capacity to perform calculations. In consideration of this, the first step toward simplifying the described prioritization process will be to shift the burden of mathematical computation to the computer. The human operator need only be responsible for entering in a few values that are relatively easy to assess, while the computer will handle the entire process of scaling, shifting and combining values to produce the final scaled prioritization value as described previously.

Ideally, the computational logic for generating the prioritization value would be integrated directly with the issue tracking system, and would thus be virtually transparent to the human operator. Lacking that, a separate application designed solely for performing such calculations could be produced and later utilized by the human operator while entering details about the relevant issue. Even a spreadsheet with a few formulas could serve as a suitable tool for calculating priorities.

For the human operator, the data entry should be limited to estimating the implementation cost and describing one or more use case scenarios, specifying the impact, frequency and scope for each. In most cases, a given issue will be limited to a single use case. For situations where multiple use-case scenarios apply, there will often be a dominant use case scenario that may overshadow the minor use case scenarios to such an extent that their inclusion will not materially affect the overall prioritization of the issue. For those situations, only the dominant use case scenario need be described.

The frequency factor will normally be the easiest of the three factors to quantify. In fact, for standard test cases, the frequency factor can be determined once when the test is defined, and then used whenever an issue arises from that test case. The value of the frequency factor is generally determined by answering the question “How often will the participant likely encounter this issue on an annual basis?” The answer will typically depend on such things as the role of the participant, the reproducible frequency of the issue and how common the use case scenario is.

Both the impact and scope factors depend in large part upon the role of the participant involved in the use case scenario. For instance, the role can directly determine the scope, as the number of participants for a given role can generally be well defined in advance. Also, for each role, an hourly rate can be predefined, and that rate used in the determination of impact.

Impact can be a little tricky to quantify since in some cases, the impact is a loss of productivity, in others it will be an increase in service costs, while in other cases it may be a loss of sales. For cases where a loss of productivity is involved, the impact can be assessed as the amount of productive time lost due to the occurrence of the issue multiplied by the hourly rate of the role of the participant. Similarly, for an issue that increases service costs, the impact can be assessed as the amount of extra time spent servicing the issue multiplied by the hourly rate for the participant.  For cases where the loss of a sale is involved, the impact is the amount of the lost sale.

Based on the foregoing, in order to adequately describe the factors involved in a use case scenario, values will need to be entered for the following fields:

Role – Type of participant involved in the use case. Typical values would be Software Engineer, QA Engineer, Project Manager and End User.

Frequency – Average number of annual occurrences on a scale of 0…10 where 0=once/1000 years and 10=once every few seconds.

Extra Time – Productive time lost or additional time required for responding to the issue. Measured per occurrence on a scale of 0…10 where 0=a few seconds and 10=1000 years.

Lost Income – Represents amount of lost revenue. Measured per occurrence on a scale of 0…10 where 0=1 cent and 10=$100 million

To produce the three factors (impact, frequency and scope) used in calculating the prioritization value, a computer would use formulas like the following:

Impact = Role.HourlyRate * ExtraTime + LostIncome

Frequency = Frequency

Scope = Role.Count

The calculation of the final prioritization value would then proceed as described previously using the three factors above in conjunction with the implementation cost estimate. While the implementation cost may not be known at the time the issue is first encountered, a reasonable placeholder estimate can be entered until a detailed analysis of the issue can be completed.

Summary

The proposed arrangement simplifies the prioritization process to the setting of five fields (role, frequency, extra time, lost income and implementation cost). While this is certainly more complex than setting a single priority value, it is still reasonably simple and provides a vastly superior model of priority. Also, many of the factor values can be determined in advance when test cases are designed, so that it is simply of matter of using those predefined values rather than attempting to quantify each ad-hoc.

Keeping everyone focused on true priorities has always been a challenge, especially when varying subjectivity and personal interests get in the way. The prioritization scheme that I have laid out in this series aims to address that challenge, providing a reliable source of accurate priorities.

RSS Feed Add to Technorati Favorites Add to Del.icio.us Stumble It! Submit to Slashdot Submit to Buzz! Digg It!

July 7, 2009 • Posted in: Work Management • No Comments

Multidimensional Prioritization

In my previous post titled Issue Prioritization, I presented a scheme for measuring prioritization values that overcomes many of the drawbacks of more traditional prioritization schemes. The gist of the proposal is to use a logarithmic scale (comparable to the Richter scale for earthquakes) to represent priority values. The main benefits of this approach include a wider dynamic range of values that better represents real world priorities, finer resolution between values to provide a more continuous range, and numerically higher priority values corresponding to truly higher priorities.

The proposed scheme thus far addresses three of the four criteria outlined in the Issue Prioritization post that were necessary to avoid the problems associated with traditional prioritization schemes. This post will focus on addressing the final criterion of setting prioritization values based on solely objective factors. The mechanism for setting the prioritization value must be purely logical, and operate on a complete set of relevant input factors that can be objectively assessed. Also, recall from earlier that the goal of prioritization is to ensure that everyone is focused on work that will maximize their possible contributions. Another way to state this is:

The goal of prioritization is to maximize the return on investment.

When it comes to software development work, the overwhelming majority of investment is in the form of employee compensation, so we can equate investment with time spent on a task. To determine the return received by completion of the task, it is necessary to assess the added value produced. In this way, the return on investment (ROI) can be computed roughly as (added value / amount invested). Since the prioritization goal is to maximize the ROI, issues should thus be ranked in order of their return on investment. As such, it is clear then that the prioritization value should be in direct proportion to the ROI for an issue.

As mentioned, computing the ROI for an issue is simply a matter of taking the ratio of “added value” and “amount invested” for the issue. While “amount invested” is fairly straightforward to estimate or measure based on the time needed to complete the task, determining “added value” will take some more analysis.

Determining Added Value

Added value represents a change that positively impacts the software organization, either through increasing revenues or by decreasing operational costs. Increased revenues are typically obtained through changes to a software product that make a meaningful positive impact to the consumers. For instance, both a bug fix and a new feature provide a benefit to the user of the application. In one case, it may be the removal of an annoyance, while in the other it is the addition of a new capability. Both changes increase the perceived value of the product, which should result in an increase in sales.

Decreased operational costs are normally achieved through changes that reduce future or ongoing effort. For example, a software engineer may refactor a particularly troublesome code module for the sole purpose of reducing the maintenance requirements of the module. Such changes do not even have to affect a software product. Changes to internal processes, or the creation of internal tools and automation can profoundly decrease operational costs.

Use Case Scenarios

Whether a change results in increasing revenue, decreasing operational costs, or both, the challenge still remains on how to objectively quantify the value added by the change. The best way to do this is by examining the use case scenarios where the change will have an effect. Multiple use case scenarios may need to be evaluated for a given changed in order to arrive at a complete assessment of the value added.

Each use case scenario should involve one type of participant. This may be an end-user, an intermediary (such as an OEM or VAR), or an employee of the software company. A monetary rate should then be assigned to the time of that participant. For employees, the rate can be derived from typical wage data. For end-users and intermediaries, a standardized rate can be decided upon. Generally, the rate used for non-employees should be on the order of 10% that used for employees. The reason for this is that employee time is a direct expense and the full cost of their time will be borne by the company. Time for non-employees is indirect, and only a small portion of it will impact company revenues.

Assessing the Impact of a Change

The first step is to determine the impact of a given change. Given that many types of changes are ones that will save time in some fashion, the monetary rate for the use case participant along with an estimate of the time saved by the change for each occurrence of the use case scenario can be used to quantify the incremental value added. So if a given change saves the participant 5 minutes and their monetary rate is $60/hr, then the value added is $5/use case occurrence. Rather than estimate value added in actual dollars, the following scale should be used to quantify impact:

Value

Description

0

0.01 cents or less per occurrence

1

0.1 cents per occurrence

2

1 cent per occurrence

3

10 cents per occurrence

4

1 dollar per occurrence

5

10 dollars per occurrence

6

100 dollars per occurrence

7

1,000 dollars per occurrence

8

10,000 dollars per occurrence

9

100,000 dollars per occurrence

10

1,000,000 dollars per occurrence

Assessing the Use Case Frequency

Next, an estimate should be made of the frequency of occurrence of the use case scenario for a given participant. This should factor in such things as:

The frequency should then be quantified on a scale of 0…10 like the following:

Value

Description

0

One occurrence every thousand years

1

One occurrence every hundred years

2

One occurrence every ten years

3

One occurrence a year

4

10 occurrences per year (every 1.2 months)

5

100 occurrences per year (twice per week)

6

1,000 occurrences per year (3 times per day)

7

10,000 occurrences per year (once every 48 minutes)

8

100,000 occurrences per year (once every 5 minutes)

9

1,000,000 occurrences per year (once every 30 seconds)

10

10,000,000 occurrences per year (once every 3 seconds)

Assessing the Scope

The next step is to determine the scope of distinct participants that will be affected by the use case. For instance, if the software product is used by 1 million end users, and the use case scenario participant is an end-user, then the scope of participants affected will be 1 million. Note that not every end user will actually be affected, since some may not even use the product regularly. However, such considerations should be factored into the frequency value instead of here. The scope should be quantified on a scale of 0…10 like the following:

Value

Description

0

1 participant

1

10 participants

2

100 participants

3

1,000 participants

4

10,000 participants

5

100,000 participants

6

1,000,000 participants

7

10,000,000 participants

8

100,000,000 participants

9

1,000,000,000 participants

10

10,000,000,000 participants

Representing the Added Value Factors

The three factors defined above (impact, frequency and scope) can now be used to form a multi-dimensional prioritization value. Each factor represents an axis in a multi-dimensional coordinate system as shown here.

 3D Priority

The added value for the change is represented by the volume of the box in the diagram, where each dimension of the box is determined by the respective value of each of the three factors. Note that the factor value used is the full range value (1…10 billion for the scope factor) rather than the scaled valued (0…10). As an example, a given change is expected to have an Impact value of $0.10 per occurrence, a Frequency value of daily occurrence, and a Scope value of 1 million. The following chart shows these values along with the combined result (Added Value = Impact x Frequency x Scope).

 

Impact

Frequency

Scope

Added Value

Full Range

$0.10

365 (Daily)

1,000,000

$3,650,000

Scaled

3

5.5

6

14.5

The above chart also shows the scaled values for each of the factors. Note that the scaled added value is equivalent to the sum of scaled factor values. This is because the scaled values are base-10 logarithms of the full range values, and adding logarithmic values is equivalent to multiplying the full range values.

Assessing the Investment

To arrive at the final prioritization value, it is necessary to divide the Added Value by the Investment (or cost to implement the change). As with the Impact, Frequency and Scope factors, the Investment factor will be represented on a scale of 0…10 as follows:

Value

Description

0

1 cent

1

10 cents

2

1 dollar

3

10 dollars

4

100 dollars

5

1,000 dollars

6

10,000 dollars

7

100,000 dollars

8

1,000,000 dollars

9

10,000,000 dollars

10

100,000,000 dollars

Continuing the example from above, let’s assume that the implementation cost of the associated change is $10,000. The following chart shows the calculated return (Added Value) on investment (Implementation Cost):

 

Added Value

Implementation Cost

ROI

Full Range

$3,650,000

$10,000

365

Scaled

14.5

6

8.5

One caveat of this that you might have noticed is that this has the potential of expanding the scaled range for the ROI to -10…30, since three added value factors each of the range 0…10 are being summed and the investment factor is being subtracted. In practice though, the priority values will form a normal distribution curve with a mean at 10 and a standard deviation of about 4. Given this, nearly all ROI values will fall within the range of -2…22. This is still a significantly larger dynamic range that the proposed range of 0…10 for the final prioritization value. I will defer the discussion of how to compress the range to a later post.

Adjusting the Scales

In order for the scaled ROI value to be truly meaningful, some adjustments would need to be made to the scales for the other factors. If we standardize on one dollar equaling a scaled value of 0, then the Impact factor scale would change to the range of -4…6, while the Investment factor scale would change to -2…8. Likewise, standardizing on a frequency of once per year equaling a scaled value of 0, the frequency factor scale would change to -3…7. This would shift the range for the resulting ROI to -13…27. Using the data from the example above, the scaled values would change as follows:

 

Original Scaled

New Scaled

Impact

3

-1

Frequency

5.5

2.5

Scope

6

6

Investment (subtracted)

6

5

ROI

9.5

2.5

Note that the new scaled ROI value is very close to the base-10 logarithm of the full range ROI value (log10(365) = 2.56). This is no accident. The adjusted ranges are set such that the scaled values are equal to the base-10 logarithm of the full range values. This way, when the scaled values are summed, they produce a scaled ROI value that can be used to compute the true full range ROI.

Coming Up

If all of this seems exceedingly complicated when compared with the traditional prioritization schemes, don’t worry. In my next post, I will examine how this process can be simplified into something a bit more reasonable. I will also discuss how the scaled ROI value can be transformed into a prioritization value matching the scheme discussed earlier.

 Please visit my main web site at danielbrannonconsulting.com

RSS Feed Add to Technorati Favorites Add to Del.icio.us Stumble It! Submit to Slashdot Submit to Buzz! Digg It!

June 24, 2009 • Posted in: Work Management • No Comments

Issue Prioritization

Software development is driven almost entirely by priorities. Executive managers set priorities for product lines. Product managers set priorities for feature development. Development managers set priorities for tasks. Project managers set priorities software bugs. In turn, software engineers focus on the highest priority tasks and bugs assigned to them. When prioritization is done well, it ensures that everyone is focused on work that will maximize their possible contributions. Conversely, inadequate prioritization can result in misdirected attention, significantly impeding progress toward a company’s goals.

While prioritization exists at all levels in a software organization, it is often most visible in defect tracking and project tracking systems. Here numeric values are often assigned to issues to represent priority levels. In a typical prioritization scheme, the highest priority issues might be represented by the number 1, while the lowest priority issues are represented by the number 5. Usually, only whole numbers between these values are permitted. While such a prioritization scheme is simple to implement and use, it suffers from some serious deficiencies which hamper its effectiveness.

Such a prioritization scheme relies heavily upon subjectivity. The individual responsible for setting the priority must make an educated decision based on the facts of the issue to determine an appropriate priority level. The problem with this is that it provides too much freedom for personal choice to intervene. No two individuals are likely to prioritize a given set of issues in the same way. Each will be swayed by personal preferences, office politics and other distractions from the goal of proper prioritization.

Another significant problem is the use of discrete priority buckets. In the example prioritization scheme, there are five priority buckets (numbered 1 through 5). All priority 1 issues get put into the same bucket. When a software engineer is ready to start a new task, if there are multiple issues in the priority 1 bucket, then the engineer can arbitrarily choose one. Again, the problem here lies in having too much personal choice freedom in the process. The software engineer may choose an issue based on factors entirely unrelated to maximizing productivity, thus thwarting the prioritization goals.

Prioritization schemes, such as the one discussed here, cannot adequately represent the true dynamic range of prioritization values. A software bug that is actively wiping out all data on the hard drives of millions of customers is a billion times more important than an off-by-one-pixel UI bug. Yet there is no way to express such an extreme prioritization difference when the scheme is limited to a handful of whole numbers.

Finally, the example prioritization scheme uses reverse numbering, where 1 is highest priority and 5 is lowest, even though 5 is a higher number than 1. While not all prioritization schemes suffer from this problem, it is a commonplace arrangement and can be a source of confusion.

In order for a prioritization scheme to avoid the problems outlined above, it would need to meet the following criteria:

To design a better prioritization scheme, I’ll address each of the above criteria beginning with the last one (since it is the easiest). All that is necessary to ensure that higher priority values are numerically higher is to reverse the priority order in the previous example. So, in the new scheme, 1 represents the lowest priority, while 5 represents the highest.

Moving on to address the possible range of prioritization values, the range 1…5 certainly does not span several orders of magnitude. That can easily be fixed by changing the range to 1…10,000,000,000, which spans 10 orders of magnitude.

The criterion for having a continuous set of possible prioritization values is an attempt to limit the cases where two issues have identical priority values. Such cases introduce ambiguity in the decision of which issue to address first. In practice, using at least 100 discrete priority buckets will sufficiently approximate a continuous value set, and will prevent duplicate priority values in most cases. Even when duplicate priority values are encountered, the actual difference in true priority of the affected issues will be so small, that it should not matter significantly as to which issue is addressed first.

The next problem is how to distribute the priority buckets over the range of possible values. If the 100 buckets are distributed at evenly spaced intervals (every 100,000,000), then the lower 8 orders of magnitude will contain a single priority bucket, while the highest order of magnitude will contain 90% of the priority buckets. A better distribution would be one in which each order of magnitude of prioritization values contains the same number of priority buckets. To accomplish this, the following formula could be used to determine the prioritization value of each bucket:

Px = 10(x/10), where x = 0…100

Using this distribution scheme, the first ten priority values would be:

  1. 1.00
  2. 1.26
  3. 1.58
  4. 2.00
  5. 2.51
  6. 3.16
  7. 3.98
  8. 5.01
  9. 6.31
  10. 7.94

Each subsequent set of ten priority values would be a factor of 10 greater than the previous set of priority values. When plotted on a logarithmic scale, the set of prioritization values will form a straight line as shown in the chart here:

Figure 1

Figure 1

The main problem remaining with this scheme is the prioritization values themselves. In the extreme case, they could reach as many as eleven digits in length. Even the mid-range values are about six digits long. In any case, such large numbers are difficult to deal with, both in the data entry aspect as well as when evaluating and comparing values. Humans are generally more comfortable with smaller numbers.

To make the prioritization values more manageable, we can transform them to the logarithmic scale (base-10). With this scale, the prioritization values would span the range of 0.0…10.0, and would be evenly spaced at intervals of 0.1. This is exactly like how earthquake magnitudes are represented. In this scale, a prioritization value of 6.5 would be considered to be ten times higher priority than a value of 5.5.

The proposed prioritization value scheme produces manageable 1-3 digit values, using a familiar logarithmic scale to represent a wide dynamic range. It also uses higher numeric values to represent higher priorities, and has a sufficient number of discrete priority buckets to approximate a continuous value set.

The only criterion remaining to be addressed is where the prioritization value must be set based solely upon objective factors. For now, I will leave the discussion of that criterion for a later post.

 Please visit my main web site at danielbrannonconsulting.com

RSS Feed Add to Technorati Favorites Add to Del.icio.us Stumble It! Submit to Slashdot Submit to Buzz! Digg It!

June 16, 2009 • Posted in: Work Management • 1 Comment

Windows Installer Logging

Windows Installer log files can be very useful resources when debugging installer issues. They contained detailed information about the progress of an installation, including descriptive error information. For instructions on how to enable Windows Installer logging, check out this Microsoft support article.

Once you have created a log file, you can use the WILogUtl program from the Windows SDK Components for Windows Installer Developers to assist with the analysis of the log file. This tool can quickly identify the errors recorded in the log file and provide suggested solutions to fix the problems.

For more information on the content of Windows Installer log files, including a fully annotated log file, see Richard MacDonald’s blog post titled “How to Interpret Windows Installer Logs”.

Another source of potentially useful information when debugging installer issues is the Application event log. This log can be accessed via the Event Viewer (this can be found under Administrative Tools in the Control Panel). All event log entries related to the Windows Installer will have the Source field set to MsiInstaller. Look for such entries with a type of Error or Warning, and double-click the event to display more details.

One particular scenario where I have found the event log especially useful is for identifying what triggered a repair installation. The Windows Installer will initiate a repair installation automatically when it detects a problem with a product installation. In this case, the Windows Installer log file provides little useful information, but the event log can tell you exactly what caused the repair installation to run. Here is an example event log entry demonstrating this scenario.

Event Type:    Warning
Event Source:    MsiInstaller
Event Category:    None
Event ID:    1004
Date:        2009.06.01
Time:        13:48:48
User:        WORKGROUP\user1
Computer:    TEST1
Description:
Detection of product '{331A6A4B-593B-4577-AF26-86352AFB7F38}',
  feature 'Main', component '{CB379CF2-BD09-4aab-BC3C-649E50B3DC33}' failed.
  The resource 'C:\Program Files\My Application\program.exe' does not exist.

In the above example, the Description entry provides the important information. It indicates that the Windows Installer detected a problem with the product installation identified by the product code {331A6A4B-593B-4577-AF26-86352AFB7F38}. The problem is a missing key path resource (‘C:\Program Files\My Application\program.exe) for the Windows Installer component identified by the component code {CB379CF2-BD09-4aab-BC3C-649E50B3DC33}.

Windows Installer log files and the Application event log are so useful for debugging installer problems, that in many cases, the cause of the problem can be identified solely using this information. Because of this, I highly recommend a QA policy of always generating logs during testing, and attaching them to all reports of bugs suspected to be installation-related.

RSS Feed Add to Technorati Favorites Add to Del.icio.us Stumble It! Submit to Slashdot Submit to Buzz! Digg It!

June 1, 2009 • Posted in: Windows Installer • No Comments

Defining Windows Installer Custom Actions

The Windows Installer provides a large amount of built-in functionality for handling most common installation tasks. Such functionality is accessible via a host of database tables as described Windows Installer Database Reference on MSDN. Although the built-in functionality is quite extensive, there are still many cases where some custom functionality needs to be used. To support such cases, the Windows Installer provides an extensibility mechanism known as custom actions.

By and large, the Windows Installer utilizes declarative programming as the means for directing the actions of an installation. By this, I mean that the install author describes the content and desired results for an installation, rather than specifying the control flow of the steps for performing the installation. In other words, the installation is data-driven, rather than code-driven. Custom actions are a departure from this paradigm, as they provide a mechanism for an install author to invoke custom code at certain points in the installation process.

CustomAction Table

The install author describes a custom action using the CustomAction table. This table has 4-5 columns depending on the target version of the Windows Installer. The columns of this table are described below:

Column Name Description
Action Represents the name given to the custom action. It is the primary key for this table, and is the value used when referencing the custom action from other tables.
Type This is a numeric field of bit flags which specify the custom action type along with a variety of execution and return processing options.
Source Usage dependent on the custom action type
Target Usage dependent on the custom action type
ExtendedType Introduced with Windows Installer 4.5. Provides space for additional bit flags.

The Action field for a custom action must be a unique name that does not conflict with the names of any standard actions or other custom actions. The remaining fields are described in detail in the following sections.

Basic Custom Action Types

The type of a custom action is defined by a basic custom action type value plus a set of bit flags. For Windows Installer 4.0 and earlier, the custom action type is specified in the Type field of the Custom Action table. In Windows Installer 4.5, an additional field named ExtendedType was introduced to accommodate additional bit flags for the custom action type. The basic custom action type describes the implementation form of a custom action, while the bit flags define such things as how to interpret return codes from the custom action, and what points in the installation process the custom action can be scheduled to run.

Basic custom action types can be broadly classified into three primary categories:

The majority of custom action types fall into the first category. These types permit the execution of compiled code in DLL and EXE files, as well as interpreted scripts in the form of JScript or VBScript.

Running a DLL Function

A custom action can call a function in a DLL file. The DLL file can either be stored in the Binary table of the MSI package, or it can be among those files that are being installed. The DLL function that is called must conform to a specific API format, as follows:

UINT __stdcall CustomAction(MSIHANDLE hInstall);

The MSIHANDLE that is automatically passed to the DLL function can be used within the function to access the current running installation, and to query or modify the attributes of the installation session.

DLL File Stored in a Binary Table Stream

The DLL file containing the function called by the custom action can be stored in the Binary table of the MSI package. This is the best place to put the DLL if it only needs to be used during the installation, or a subsequent uninstallation. When the DLL is stored in the Binary table, any custom actions which call functions in it may be scheduled at virtually any point in the installation process.

CustomAction Table Entry
Basic Custom Action Type 1 decimal (0×01 hex)
Source Column Key to the Binary table identifying the binary data stream that represents the DLL file.
Target Column The name of the DLL entry point function. This function must conform to the standard API format defined for MSI custom actions.

DLL File Installed With a Product

The custom action can also call a function in a DLL file which is installed as part of the product. This makes sense to do in cases where the DLL contains functionality that is used by the installed application, in addition to the custom action. This restricts the custom action to being scheduled at a point in the installation process where installed files are present on the target system. This is at any point following the processing of the InstallFiles standard action during a normal installation, or before the processing of the RemoveFiles standard action during an uninstallation.

CustomAction Table Entry
Basic Custom Action Type 17 decimal (0×11 hex)
Source Column Key to the File table identifying the DLL file that is installed as part of the product.
Target Column The name of the DLL entry point function. This function must conform to the standard API format defined for MSI custom actions.

Running an Executable File

Another method for executing custom code is the launch an executable file, optionally specifying command line parameters. There is not an easy way to pass a handle to the installation session to such an executable file, so EXE files are best used in cases where their actions are independent of the installation processing.

EXE File Stored in a Binary Table Stream

If the given executable file is only used by a custom action, then it is probably best to store it in the Binary table of the MSI package. This makes the EXE file available for virtually any point in the installation process, and protects it from being run directly by an end-user.

CustomAction Table Entry
Basic Custom Action Type 2 decimal (0×02 hex)
Source Column Key to the Binary table identifying the binary data stream that represents the EXE file.
Target Column Any command line arguments to pass to the executable when launching it. Since the Target column uses the Formatted data type, its value may contain references to properties, files, directories, etc.

EXE File Installed With a Product

If the custom action runs an executable file that is also used as part of the installed application, the install author can avoid having to store an extra copy in the Binary table under certain conditions. Instead, the custom action can be configured to run the executable file directly from the location where it is installed. This can only work if the custom action is called from a point in the installation process where the product files are present on the target system. Anytime after the processing of the InstallFiles standard action during a normal installation or prior to the processing of the RemoveFiles standard action during an uninstallation will work.

CustomAction Table Entry
Basic Custom Action Type 18 decimal (0×12 hex)
Source Column Key to the File table identifying the EXE file that is installed as part of the product.
Target Column Any command line arguments to pass to the executable when launching it. Since the Target column uses the Formatted data type, its value may contain references to properties, files, directories, etc.

EXE File Having a Path Referencing a Directory

For this custom action type, the working directory for running the executable can be explicitly specified. All other forms of running an executable use a default working directory.

CustomAction Table Entry
Basic Custom Action Type 34 decimal (0×22 hex)
Source Column Key to the Directory table identifying the directory to use as the working directory when running the executable.
Target Column The complete command line for launching the executable, including the full path and filename of the executable file, along with any command line options. Quotation marks must be used around long file names or paths. Since the Target column uses the Formatted data type, its value may contain references to properties, files, directories, etc.

EXE File Having a Path Specified By a Property Value

The property referenced by this custom action type must resolve to the full path and filename of the executable file to launch. A typical case for using this custom action type would be to launch an EXE file that was discovered using the searching functionality of the AppSearch table. It can also be used to launch an EXE that resides on the source installation media.

CustomAction Table Entry
Basic Custom Action Type 50 decimal (0×32 hex)
Source Column Key to the Property table identifying the property containing the full path and file name of the target executable file. The path need not be enclosed in double quotes.
Target Column Any command line arguments to pass to the executable when launching it. Since the Target column uses the Formatted data type, its value may contain references to properties, files, directories, etc.

Running a JScript Function

Custom actions can be implemented in JScript as long as the install author can guarantee that the scripting engine is available on the target system. JScript custom actions have access to the installation session via the Session object. They can use this object to query or modify the attributes of the installation session.

JScript File Stored in a Binary Table Stream

As with compiled binaries, JScript files can be stored in the Binary table of the MSI package. This option is suitable for non-trivial scripts that are only utilized during installation or uninstallation. Such scripts will be available for use at virtually any point in the installation process, and storing them in the Binary table will help to hide the scripts from end-users.

CustomAction Table Entry
Basic Custom Action Type 5 decimal (0×05 hex)
Source Column Key to the Binary table identifying the binary data stream that represents the JScript.
Target Column The name of an optional script function.

JScript File Installed With a Product

In cases where the installed product may use the same JScript file, it may make sense to avoid duplication, and run the JScript custom action using the installed file. This does restrict the points in the installation process where the custom action may be used. Mainly this includes any point after the InstallFiles standard action during a normal installation, or prior to the RemoveFiles standard action during an uninstallation.

CustomAction Table Entry
Basic Custom Action Type 21 decimal (0×15 hex)
Source Column Key to the File table identifying the JScript file that is installed as part of the product.
Target Column The name of an optional script function.

JScript Text Stored in This Sequence Table

For cases where the JScript custom action consists of a relatively small amount of script text, it may be easier to store the script directly in the definition of the custom action. This basic custom action type facilitates this feature, storing the JScript text in the Target field of the custom action. Due to field size restrictions, the JScript text is limited to a maximum length of 255 characters.

CustomAction Table Entry
Basic Custom Action Type 37 decimal (0×25 hex)
Source Column null
Target Column Literal JScript text

JScript Text Specified by a Property Value

An alternative method for storing the JScript text for a custom action is to place it in an entry in the Property table. That property can then be referenced by the custom action. Property values can accommodate longer text than the Target field of the CustomAction table, so longer scripts can be used in this case. However, for maintenance purposes, it is generally best to store relatively short scripts in the Property table, and to use the Binary table for longer scripts.

CustomAction Table Entry
Basic Custom Action Type 53 decimal (0×35 hex)
Source Column Key to the Property table identifying the property containing the script text.
Target Column The name of an optional script function.

Running a VBScript Function

As with JScript, custom actions can be implemented in VBScript as long as the install author can guarantee that the scripting engine is available on the target system. VBScript custom actions also have access to the installation session via the Session object, which can be used to query or modify the attributes of the installation session.

VBScript File Stored in a Binary Table Stream

VBScript files can be stored in the Binary table of the MSI package. This option is suitable for non-trivial scripts that are only utilized during installation or uninstallation. Such scripts will be available for use at virtually any point in the installation process, and storing them in the Binary table will help to hide the scripts from end-users.

CustomAction Table Entry
Basic Custom Action Type 6 decimal (0×06 hex)
Source Column Key to the Binary table identifying the binary data stream which represents the VBScript file.
Target Column The name of an optional script function.

VBScript File Installed With a Product

In cases where the installed product may use the same VBScript file, it may make sense to avoid duplication, and run the VBScript custom action using the installed file. This does restrict the points in the installation process where the custom action may be used. Mainly this includes any point after the InstallFiles standard action during a normal installation, or prior to the RemoveFiles standard action during an uninstallation.

CustomAction Table Entry
Basic Custom Action Type 22 decimal (0×16 hex)
Source Column Key to the File table identifying the VBScript file that is installed as part of the product.
Target Column The name of an optional script function.

VBScript Text Stored in This Sequence Table

For cases where the VBScript custom action consists of a relatively small amount of script text, it may be easier to store the script directly in the definition of the custom action. This basic custom action type facilitates this feature, storing the VBScript text in the Target field of the custom action. Due to field size restrictions, the VBScript text is limited to a maximum length of 255 characters.

CustomAction Table Entry
Basic Custom Action Type 38 decimal (0×26 hex)
Source Column null
Target Column Literal VBScript text

VBScript Text Specified by a Property Value

An alternative method for storing the VBScript text for a custom action is to place it in an entry in the Property table. That property can then be referenced by the custom action. Property values can accommodate longer text than the Target field of the CustomAction table, so longer scripts can be used in this case. However, for maintenance purposes, it is generally best to store relatively short scripts in the Property table, and to use the Binary table for longer scripts.

CustomAction Table Entry
Basic Custom Action Type 54 decimal (0×36 hex)
Source Column Key to the Property table identifying the property containing the script text.
Target Column The name of an optional script function.

Terminating an Installation

Under certain conditions, it may be necessary to abort an installation. Windows Installer provides a special custom action type for this purpose.

Display an Error Message

This basic custom action type allows the install author to present an error message to the user and terminate the installation. The error message displayed can be a string literal or retrieved from the Error table.

CustomAction Table Entry
Basic Custom Action Type 19 decimal (0×13 hex)
Source Column null
Target Column Formatted text string representing the error message to display. If the formatted text evaluates to an integer, that number is used as an index into the Error table to retrieve the message to display.

Setting Property Values

Properties are the variables for the Windows Installer, and there are many cases where it is necessary to define new properties based on certain installation attributes. This can be accomplished through custom actions that use the capabilities of the Formatted data type to set the values of properties and directories.

Directory Set With Formatted Text

Directories are really just a special kind of properties. A directory can be used virtually anywhere a property is expected, though the reverse is not necessarily true. In certain cases, it may be desired to change the value of a directory defined in the Directory table based on attributes of the current installation session. For example, a directory could be set to match the value read from an environment variable.

While any formatted text string can be entered, and will pass MSI validation, problems may be encountered at install-time if the formatted text does not resolve to a properly formatted directory path. Note that directory paths must always end with a directory separator (\).

CustomAction Table Entry
Basic Custom Action Type 35 decimal (0×23 hex)
Source Column Key to the Directory table identifying the directory that will be set using the formatted text.
Target Column A text string formatted according to the rules of the Formatted data type.

Property Set With Formatted Text

Unlike directories, properties have no formatting or length restrictions. As such, any formatted text can be used for setting the property value.

CustomAction Table Entry
Basic Custom Action Type 51 decimal (0×33 hex)
Source Column Key to the Property table identifying the property that will be set using the formatted text.
Target Column A text string formatted according to the rules of the Formatted data type.

Return Processing

Two bit flags in the custom action type are related to return processing. One flags controls whether the exit code returned from the custom action will be checked, while the other specifies whether the Windows Installer will wait for the custom action to complete before continuing with the installation process.

Ignore Exit Code

Bit Flag Value 64 decimal (0×40 hex)

If this flag is set, the Windows Installer will act as though the custom action returned an exit code indicating successful completion. This flag has no effect on basic custom action types that set directory/property values (types 35/51) or that terminate the installation (type 19). If this flag is not set, then DLL and EXE-based custom actions must return one of the following values:

Return Constant Name

Constant Value

Description
ERROR_FUNCTION_NOT_CALLED

1626

The custom action was not executed
ERROR_SUCCESS

0

The custom action completed successfully
ERROR_INSTALL_USEREXIT

1602

The user terminated the installation prematurely
ERROR_INSTALL_FAILURE

1603

An unrecoverable error occurred
ERROR_NO_MORE_ITEMS

259

Skips remaining actions, not an error

JScript and VBScript custom actions must return one of the following values if the Ignore Exit Code flag is not set:

Return Constant Name

Constant Value

Description
msiDoActionStatusNoAction

0

The custom action was not executed
msiDoActionStatusSuccess

IDOK=1

The custom action completed successfully
msiDoActionStatusUserExit

IDCANCEL=2

The user terminated the installation prematurely
msiDoActionStatusFailure

IDABORT=3

An unrecoverable error occurred
msiDoActionStatusSuspend

IDRETRY=4

Suspended sequence to be resumed later
msiDoActionStatusFinished

IDIGNORE=5

Skips remaining actions, not an error

Asynchronous Execution

Bit Flag Value 128 decimal (0×80 hex)

By default, the Windows Installer waits for a custom action to complete before proceeding with the installation. When the Asynchronous Execution flag is set, the Windows Installer will immediately continue with further installation actions after starting the custom action. This bit flag cannot be used on rollback custom actions or script custom actions (JScript/VBScript).

Additionally, this bit flag affects the behavior associated with the Ignore Exit Code bit flag. When Asynchronous Execution is enabled for a custom action, any checking of custom action exit codes will be delayed until the end of the installation sequence. If both Ignore Exit Code and Asynchronous Execution are set, then the custom action will be allowed to continue even after the Windows Installer terminates the installation session. Because of this, DLL custom actions cannot have both of these bit flags set. Only EXE-based custom actions are allowed to have both bit flags set.

Scheduling Options

When it comes to scheduling custom actions, there are two main options to be considered. Custom actions can either be set to run immediately, or they can be scheduled to run at a later point when the installation script is processed. In general, custom actions can be invoked from any of the following points in the installation process:

Immediate Custom Actions

Immediate custom actions are executed as soon as they are encountered in a sequence table, UI control event or explicit call to MsiDoAction. As a class, immediate custom actions can appear at any point in the installation process where custom actions are valid, though certain basic types of custom actions may have further restrictions on when they can be executed.

First Sequence

Bit Flag Value 256 decimal (0×100 hex)

By default, immediate custom actions will be executed each time they are encountered in a sequence table. By setting the First Sequence bit flag, the install author can direct the Windows Installer to only execute the custom action the first time it is encountered in a sequence table. Thus if a custom action appears in both the InstallUISequence and InstallExecuteSequence, it will be executed in the InstallUISequence when the install is run with full UI mode, or in the InstallExecuteSequence when the install is run with less than full UI mode.

Once Per Process

Bit Flag Value 512 decimal (0×200 hex)

The Once Per Process flag is similar to the First Sequence flag. In fact, on Windows 9x machines, both flags will result in the same behavior. The reason for this is that under Windows 9x, the InstallUISequence and InstallExecuteSequence tables are executed within the same process. With NT-based Windows (2000/XP/Vista/7), the InstallUISequence is executed in a client process while the InstallExecuteSequence is executed in a service process.

The primary purpose of this flag is to prevent actions that modify session state, such as property and database data, from running more than once. Thus if a custom action with this flag appears in both the InstallUISequence and InstallExecuteSequence, it will only be executed in the InstallUISequence on Windows 9x systems, but will be executed in both sequences on NT-based Windows systems.

Client Repeat

Bit Flag Value 768 decimal (0×300 hex)

This flag is actually the combination of the First Sequence and Once Per Process bit flags. Since it does not make sense to have both of those flags turned on at the same time, the Windows Installer creators decided to use that bit flag combination for a different meaning, rather that use a separate bit flag.

The Client Repeat bit flag setting will cause the custom action to execute only if it is running on the client after the UI sequence has been run. Thus, this is valid only for custom actions listed in the InstallExecuteSequence.

In-Script Custom Actions

Those custom actions scheduled in the InstallExecuteSequence between InstallInitialize and InstallFinalize may be flagged as In-Script custom actions (also known as deferred custom actions). These custom actions will not be processed immediately, but instead will be added to the installation script for later processing.

Deferred

Bit Flag Value 1024 decimal (0×400 hex)

This is the bit flag that identifies the custom action as In-Script or deferred, instead of immediate. Any custom actions with this bit set will be scheduled for later processing in the installation script. The exact point of that later scheduling may depend upon the settings of other bit flags.

Rollback

Bit Flag Value 256 decimal (0×100 hex)

The rollback bit flag must be used in combination with the deferred bit flag, and cannot be set in combination with the commit bit flag. It identifies the custom action as a rollback action. This causes the custom action to be scheduled for possible later processing in the rollback phase of the installation script.

Commit

Bit Flag Value 512 decimal (0×200 hex)

The commit bit flag must be used in combination with the deferred bit flag, and cannot be set in combination with the rollback bit flag. It identifies the custom action as a commit action. This causes the custom action to be scheduled for possible later processing in the commit phase of the installation script.

No Impersonate

Bit Flag Value 2048 decimal (0×800 hex)

The No Impersonate bit flag must be used in combination with the deferred bit flag. Normally, deferred custom actions are executed with user impersonation, such that they run with the privileges of the logged in user. In some cases, the user privileges are insufficient to perform certain system modifications or queries, so elevated privileges are needed. The No Impersonate bit flag can be used to cause the custom action to run with system privileges, thus providing a greater level of privileges.

TS Aware

Bit Flag Value 16384 decimal (0×4000 hex)

The TS Aware bit flag must be used in combination with the deferred bit flag. This bit flag has no effect if set in combination with the No Impersonate bit flag. Normally, deferred custom actions will execute with no user impersonation when running a per-machine installation on a terminal server. Setting the TS Aware bit flag will cause the custom action to run with user impersonation during a per-machine install on a server running the Terminal Server role service.

Custom Action Type Bit Map

The following table contains a summarization of the bit mapping used for Windows Installer custom action type values:

Bit

Usage

0-5

Basic Custom Action Type

6

Ignore Exit Code

7

Asynchronous Execution

8

First Sequence (immediate custom actions) / Rollback (deferred custom actions)

9

Once Per Process (immediate custom actions) / Commit (deferred custom actions)

10

Deferred

11

No Impersonate

12-13

unused

14

TS Aware

15-31

unused

Windows Installer Custom Action Type Encoder/Decoder

As an aid for encoding and decoding Windows Installer custom action types, I have created an Excel spreadsheet application for this purpose. This spreadsheet can be found here.

RSS Feed Add to Technorati Favorites Add to Del.icio.us Stumble It! Submit to Slashdot Submit to Buzz! Digg It!

April 29, 2009 • Posted in: Windows Installer • 1 Comment

Summary of Product Configuration Management Patterns

This is the final post in a series related to product configuration management (PCM) patterns. The earlier posts covered a variety of different PCM patterns including the following:

Each of the above patterns is named based on the point at which configuration options are set. This is an important factor since it determines both the inherent level of security of the option and the relative ease with which a configuration option can be changed. In general, the earlier such changes are made in the product’s life-cycle, the more secure the configuration option. However, this comes with a sacrifice of agility, since such changes typically require a larger amount of effort to implement and validate. Configuration changes made late in the product’s life-cycle have the opposite attributes. They are generally associated with insecure configuration options, but require little to no effort to implement and validate.

Note that these characteristics are not absolute. It is possible for early-phase PCM patterns like the Code-Time PCM pattern to be more agile. This could be accomplished by developing sophisticated automation to implement and validate configuration changes. Likewise, late-phase PCM patterns like the Run-Time PCM pattern can be made more secure. For instance, a client-server activation system can be used to check all configuration changes and enforce any required security protections. By and large, it takes some additional initial investment in technology in order to overcome the inherent deficiencies of each PCM pattern.

None of the PCM patterns should be considered as superior to the others. In fact, each fills a distinct need and can be the best choice for specific scenarios. The different PCM patterns are not mutually exclusive either. Nothing prevents a given product from using a combination of PCM patterns to achieve its configuration needs. In fact, this cocktail approach may produce much better results than using a single PCM pattern, since the best PCM pattern will be applied to each individual configuration need, rather than forcing all options to adapt to a single PCM pattern. Note that using multiple PCM patterns for a single product may significantly increase the complexity of managing and tracking configuration options, so this factor should be weighed in when deciding how many different PCM patterns to use.

Scale is one of the dominant factors that will be used to determine which PCM pattern to implement for a given use case. By scale, I mean the number of different product configurations that may need to be supported. If only one configuration is needed, then it is not a configuration; it’s simply standard functionality. If a few configurations are needed, then Code-Time or Build-Time PCM patterns are likely sufficient. If a dozen or so configurations are needed, then the Release-Time PCM pattern is probably the best choice. If very large numbers of configurations are needed, then Install-Time and Run-Time PCM patterns are likely the best alternatives. To determine the number of possible product configurations to be supported, count each unique combination of configuration option settings expected to be used. Also, be sure to include those configurations which are only used internally, such as test or debug configurations.

Keep in mind that the PCM pattern that is the best fit for today’s needs may buckle under the demands of the future. Make realistic projections for the scale of your product’s configuration needs going out at least a couple of years. While choosing a higher scale PCM pattern today will take some extra work and investment, it will be well worth it once the time comes where it is needed. The alternative, of waiting until the product’s configuration needs have grown in scale beyond the current PCM pattern’s capacity, will likely cost you far more in the end.

RSS Feed Add to Technorati Favorites Add to Del.icio.us Stumble It! Submit to Slashdot Submit to Buzz! Digg It!

Run-Time Product Configuration Management Pattern

This post is a continuation of a series related to product configuration management (PCM) patterns. Here, I discuss the implementation, features and drawbacks of the run-time PCM pattern. With this PCM pattern, a single installation of a product release can be configured as desired by the end-user.

Unlike the PCM patterns discussed in earlier posts, the run-time PCM pattern puts the end-user in full control of the configuration options. To facilitate this, the application UI must contain screens for presenting and configuring product options, and the application functionality must contain run-time checks of the configuration options to control its behavior. Some initial investment must be made in developing the configuration screens and run-time checks, but once that is complete, a single code base, build, release, installer and installation can be used to create any product configuration. This makes it the most scalable of the PCM patterns, especially suited for cases where there are large numbers of possible product configurations.

Run-Time Activation

In its simplest form, the run-time PCM pattern lacks any security, making it useful for only those configuration options which have low intrinsic value or associated third-party royalties. Typically, this type of PCM pattern is employed for handling user preferences, rather than major product features. However, with some additional investment, higher levels of security can be provided that make the run-time PCM pattern a viable mechanism for handling high value options.

One proven method for overcoming the inherent insecurity of the run-time PCM pattern is to couple it with a client-server feature activation system. Each time a user attempts to enable a high-value option, the configuration sub-system will contact a centralized server for instructions. The first time the user attempts to enable such an option, the server will direct the client to present an activation experience. This may be a simple as presenting a license agreement for acceptance, or it may involve a financial transaction to purchase the desired option. Whatever the experience, once it is completed from that point forward, the option is considered to be activated. The user can then enable/disable the option at will.

A run-time activation system is not a simple task to implement, as it requires a highly scalable server, consideration of privacy concerns, possible support for financial transaction processing, and a secure client module that cannot easily be hacked. For smaller businesses or niche products, it may make more sense to use a commercially available activation system rather than attempt to develop a proprietary one.

Application Footprint

In order for the run-time PCM pattern to function properly, the client installation must include all resources and functionality necessary to support the universe of possible configuration combinations. In some cases, this may dramatically increase the size of the installation on the client system. Also, for those applications that include service programs, system tray applications or other continuously running executables, the requirement of having all features persistently available for run-time options can result in excessive consumption of system memory or CPU cycles. Such impact on the client system can result in the application gaining a reputation as bloat-ware.

When evaluating the system performance impact of excessive consumption of storage, memory and CPU resources, it is often memory that proves to be the most limited resource. As such, applications using the run-time PCM pattern should design the configuration sub-system such that, when possible and appropriate, functionality associated with configurations options is unloaded from memory when the corresponding option is disabled.

Implementation

For run-time user preferences, a typical method for storing the options on Windows systems is to use the system registry (typically under HKEY_CURRENT_USER). This leverages existing standard functionality for storing and querying such configuration settings, and also can handle multiple users of an application. The application then needs only to implement the appropriate run-time checks of these registry entries to control functionality execution paths.

Similarly, per-machine configuration settings can be stored in the system registry under HKEY_LOCAL_MACHINE. The system registry is normally used for storing low value configuration options, since the system registry can be easily edited by end users. If a given option requires greater security, such as that afforded by a run-time activation system, then it will likely be stored in a much more secure format, such as a protected database or an encrypted file. It is also possible to use the system registry in such cases, so long as the data stored there is in an encrypted format.

Preparation Effort

All of the work involved with supporting the run-time PCM pattern is in the preparation effort. The primary work involves developing application UI for presenting configuration options to the user, and adding run-time checks to control program execution paths based on the configuration option settings.

As with the release-time and install-time PCM patterns, it is possible to substantially optimize the testing process for products that use the run-time PCM pattern. QA can rely on a single code base and set of binaries as the foundation for testing. Individual configuration options can easily be tested with simple application UI selection changes. This provides QA the ability to instantly generate any desired configuration for testing purposes.

Test/Fix Effort

Since the actual configuration changes have been pushed out beyond release to the customer, there is no need for specific configuration testing. Only the proper functioning of individual configuration options needs to be verified. This effectively eliminates the test/fix cycle for configuration changes.

Effort Summary

Following is a summary of the effort involved in handling multiple product configurations using the run-time PCM pattern:

Worker Time Machine Time Work Description
80 hours   Insert conditional run-time checks
80 hours   Develop UI configuration functionality
80 hours   Test preparation for configuration options
240 hours 0 hours Sub-total – preparation effort
240 hours 0 hours Total effort

 The run-time PCM pattern has a relatively large preparation phase, but requires little to no investment of effort beyond that. The one-time cost of the preparation phase is very quickly offset by the saving achieved through the elimination of downstream configuration work and testing. This makes the run-time PCM pattern the most scalable of all the PCM patterns, and well suited to cases where the number of possible configuration combinations is huge.

A potential downside to the run-time PCM pattern is its relative insecurity. However, as discussed, the use of a client-server activation system can be utilized to better protect certain high-value configuration options. This requires an increased investment in the preparation phase to either develop a proprietary activation system or integrate a third-party activation system. It also will incur continuing costs of operating and maintaining the activation server. However, the end result can be the holy-grail of product configuration management, with a secure, scalable, user-driven, configure-to-order mechanism.

RSS Feed Add to Technorati Favorites Add to Del.icio.us Stumble It! Submit to Slashdot Submit to Buzz! Digg It!

Install-Time Product Configuration Management Pattern

This post is a continuation of a series related to product configuration management (PCM) patterns. Here, I discuss the implementation, features and drawbacks of the install-time PCM pattern. With this PCM pattern, a single product release can be used to install multiple product configurations.

The install-time PCM pattern is traditionally implemented through the use of command line parameters specified when running the product installer, or through UI selections in the setup wizard. For the command line, available options can either be specified individually on the command line, or the name of a file containing the option settings can be specified. In order for these command line options to have their desired effect, the product installer must be crafted to look for and handle the options. Here are some examples of the types of changes that the product install might make for a specific option:

The install-time PCM pattern makes the control of configuration settings available to the one installing the product, which is often the end-user. As such, there is very little protection available to prevent the user from changing these settings at will. For cases where the software will be pre-installed on OEM systems, the configuration control will be with the OEM, not the end-user. While this improves configuration security somewhat, many OEM systems also ship with a CD containing the installers for the pre-installed software in case the user needs to re-install any of the software. The only other security protection available for command line installer options is lack of public documentation. If the options are undocumented, and not easily discoverable, it is less likely that an end-user will be able to take advantage of them. Overall, installer options are considered insecure, so they are generally suitable for controlling those product configuration options that have low intrinsic value.

Another implementation form of the install-time PCM pattern is frequently employed by products being deployed through system OEM vendors, though it can be used in any scenario where the software product has some form of hardware dependency. In this implementation scheme, the installer performs a hardware detection operation, and then configures its installation activities automatically based on the hardware that was found. For example, a software product to be used for OEM pre-installs may have its installer designed to detect that it is running on a specific OEM’s hardware before allowing the installation to proceed. This can be used to help prevent the product installer from being pirated for use on other computers.

Another case where this implementation form might be used is when certain product features are dependent upon the existence of certain hardware. In such a case, the installer might only install certain feature capabilities if a particular hardware device is present. The OEM may pay the ISV different amounts for installation on systems with and without the target hardware device. While two different product installers could be used to achieve the same result, it would then place the burden on the OEM to decide when and how to install which version of the product. Having the installer make the choice automatically simplifies the process and reduces the likelihood of mistakes. One caveat to this approach is that it potentially allows the end-user to receive the hardware-dependent feature without paying for it if they purchase the hardware device at a later point, and then re-install the software from the system recovery CD. If this poses a significant risk to revenue, then any of the following additional precautions can be taken:

The install-time PCM pattern differs from the code-time, build-time and release-time PCM patterns in that it passes the configuration work onto the customer. Once the ISV has developed the configuration capabilities, there is no further work aside from periodic maintenance updates to the product or installer code base. In turn, the customer receives both the responsibility and the power to control the available product configuration options. It’s a win-win situation in scenarios where customer-controlled configuration options are viable.

Most product installers already have some configuration options presented in the setup wizard, however not all provide equivalent command line functionality. It is very useful to be able to specify all configuration options on the command line, along with suppressing the setup wizard UI, in order to support fully automated installations. This is a key requirement for volume license partners (VLPs), since they need to perform mass deployments of applications to large numbers of computers within an enterprise. If the installation cannot be completely automated, they generally will not even consider the product for mass deployment.

Preparation Effort

As far as the ISV is concerned, all of the work involved with supporting the install-time PCM pattern is in the preparation effort. In this case, the preparation work is focused mainly on the installer, with functionality added to support various UI and command line based options. Each option will typically be handled as a unique case, and the complexity involved with handling each option may vary dramatically. Some of the options may be handled through native capabilities of the installer engines, such as through the use of optional product features with Windows Installer; others may require custom code development.

As with the release-time PCM pattern, it is possible to substantially optimize the testing process for products that use the install-time PCM pattern. QA can rely on a single code base and set of binaries as the foundation for testing. Individual configuration options can easily be tested with simple installer UI selection or command line options. This provides QA the ability to instantly generate any desired configuration for testing purposes.

Test/Fix Effort

Since the actual configuration changes have been pushed out beyond release to the customer, there is no need for configuration testing. Only the proper functioning of individual configuration options needs to be verified. This effectively eliminates the test/fix cycle for configuration changes.

Effort Summary

Following is a summary of the approximate effort involved in handling multiple product configurations using the install-time PCM pattern:

Worker Time Machine Time Work Description
80 hours   Insert conditional install-time checks
80 hours   Develop UI configuration functionality
80 hours   Develop command line configuration functionality
80 hours   Test preparation for configuration options
320 hours 0 hours Sub-total – preparation effort
320 hours 0 hours Total effort

All of the effort involved with managing configurations in the install-time PCM pattern is in the preparation phase. The preparation effort is a relatively large, but one-time, cost which is offset by an elimination of configuration effort. The install-time PCM pattern is an ideal approach when the universe of desired configuration combinations is extremely large or unpredictable in advance. By pushing the configuration responsibility to the customer, any conceivable configuration combination can be produced without any additional effort on the part of the ISV. Since the customer has full control over the configuration choices, the install-time PCM pattern is not well suited to controlling options that require any level of security protection.

RSS Feed Add to Technorati Favorites Add to Del.icio.us Stumble It! Submit to Slashdot Submit to Buzz! Digg It!