Second Stanza

May 23, 2008

Timing Script using Powershell

Filed under: Powershell — Tags: — dfbaskin @ 12:32 pm

Here’s an example of a simple Powershell script that can be used to created a tab-separated file of timing events.

# Windows Powershell Timer.

$timingName = "Timing";
$timingPoints = @(
    "Step One",
    "Step Two",
    "Step Three",
    "Step Four"

$resultFile = $timingName + ' Timing ' + [DateTime]::Now.ToString( "yyyy-MM-dd hh-mm-ss" ) + ".csv";

$timeStamps = @();
$textItems = @();
[DateTime] $timeStamp = [DateTime]::Now;

# Add timing message
function AddMsg( [string] $msgTxt )
    $SCRIPT:timeStamp = [DateTime]::Now;
    $SCRIPT:timeStamps += $SCRIPT:timeStamp;
    $SCRIPT:textItems += $msgTxt;

$resultTxt = @();
$resultTxt += "StartTime`tEndTime`tDuration`tTotalDuration`tEvent";

[DateTime] $startTimeStamp = [DateTime]::Now;
[DateTime] $prevTimeStamp = $startTimeStamp;
foreach( $timingPoint in $timingPoints )
    Read-Host "Press Enter";
    AddMsg( $timingPoint );
    Write-Host( $prevTimeStamp.ToString('yyyy-MM-dd hh:mm:ss.ffffff') + " / " +
                $timeStamp.ToString('yyyy-MM-dd hh:mm:ss.ffffff') + " / " +
                $timeStamp.Subtract( $prevTimeStamp ).ToString() + " / " +
                $timeStamp.Subtract( $startTimeStamp ).ToString() );
    $resultTxt += $prevTimeStamp.ToString('yyyy-MM-dd hh:mm:ss.ffffff') + "`t" +
                  $timeStamp.ToString('yyyy-MM-dd hh:mm:ss.ffffff') + "`t" +
                  $timeStamp.Subtract( $prevTimeStamp ).ToString() + "`t" +
                  $timeStamp.Subtract( $startTimeStamp ).ToString() + "`t" +
    $prevTimeStamp = $timeStamp;

    Write-Host( $timingPoint );

Write-Host( "Created file:" );
Write-Host( $resultFile );
$resultTxt | Set-Content $resultFile;

May 16, 2008

Network Share Copy Problem in Vista

Filed under: Windows OS — Tags: — dfbaskin @ 3:13 pm

I ran into this bug: It showed up where a NAnt script was mysteriously not copying files.

My head hurts …

May 3, 2008

WiX and Managed Custom Actions

Filed under: WiX — Tags: , — dfbaskin @ 3:41 pm

I use WiX regularly and have occasionally had the need to write custom actions for certain scenarios. Of late, I’ve been working with custom actions written in managed code. .NET offers developers great benefits over programming real-mode C++ applications, so it makes sense that developers of Windows Installer applications should also be able to make use of it.

Rob Mensching discusses the critical issues in this post. In fact, a later post of his is even titled “Custom actions are (generally) an admission of failure”. Who’s failure? I think Rob says it best:

Now, having written something like 75% of the CustomActions in the WiX toolset let me assure you that I’m one of the first to point out that CustomActions are quite often a necessity today. However, I also know that the code in the Windows Installer has had far more scrutiny and testing than the WiX CustomActions to date. Thus, I can agree that it would be better if there were fewer CustomActions shipping in installation packages today and that the installation functionality was instead built into the Windows Installer or the operating system in general.

So there are plenty of things that Windows Installer does not do. In the current 2.0 version, WiX provides custom actions for a lot of the things Windows Installer doesn’t help you with:

  • Adding and deleting a per-user certificate.
  • Adding and deleting a per-machine certificate.
  • Installing and uninstalling certificates.
  • Creating and Dropping SQL Databases.
  • Executing SQL commands.
  • Registering and unregistering Performance Monitor counters.
  • Creating and deleting file shares.
  • Creating and removing Windows users.
  • Configuring IIS.
  • Printing the EULA.
  • Configuring Windows services.
  • Writing and removing XML data.
  • Creating .NET native images (NGen).

Therefore, I don’t think I’m going to feel too guilty about creating custom actions, or creating them to use the .NET runtime environment. If I understand correctly, it might only require a reboot before installing the application (if the correct .NET runtime can’t be loaded as described in Rob’s post).

Anyway, the source below demonstrates an installation for a simple .NET application. The application’s config file is marked as a permanent file (the file will not be uninstalled). For some cases, this makes sense if the application is uninstalled and then reinstalled or simply upgraded and the configuration options need to persist. A custom action could be used to update the configuration file or add additional content to the file. The custom action in this example, adds the date the application was installed to the config file. (Yes, the WiX XmlConfig element could be used to do the same thing, but this is just an example to show the technique.)

The custom action is implemented in managed C++. Its obviously not as simple as C# or VB.NET, but you gain access to the .NET runtime and you must provide the real-mode entry point for the Windows Installer. A couple of wrapper classes are created for MSI functions so the custom action can do things like add messages to the installer log.

I had to specify the original manifest for the C++ runtime, even though I was using Visual Studio 2005 with SP1 (more details here).

So far, I’ve not had any trouble using this technique while installing on Windows 2000, XP, 2003, or Vista. You can examine the log messages created by the installation by using these commands:

To Install:

msiexec /l*v install.log /i DemoApplication.msi

To uninstall:

msiexec /l*v uninstall.log /x DemoApplication.msi

For your own custom actions, make sure you watch out for issues related to deffered custom actions (see here).

Download / View Source Code
(View requires Microsoft Silverlight 1.0 and Internet Explorer)

Blog at