Apr 29, 2013

This blog is moving... Kind of


I've been wanting to move this blog to my own domain name for a while, in order to better define my "personal brand" (see Scott Hanselman & friends' advice in the subject).

Separately, Google recently announced it would be sun-setting Google Reader, a product I had come to use quite a bit and will leave a large hole to fill. This just reinforced my realization that my primary "voice" on the web (this blog) is strongly tied to a single vendor who's not directly making any money off the product - so could kill it off any day, rendering me voiceless.

So over the next few months, I'll be making some changes.  First, as you may have noticed if you're reading this in a web browser, I've migrated my blog within Blogger to a custom domain. So...

http://wrightthisblog.blogspot.com is now ==> http://blog.wrightfully.com


Currently, if you go to the old URL for any of my posts, you will get a redirect to the new hostname.  Similarly, the RSS feed has been pointed to the new hostname.

I'm also spinning up a WordPress instance that will be the new home of my online presence, including this blog, and I'll eventually move off Blogger altogether.  If I do this right, none of you will notice and your existing links should continue working as-is.  As part of that process, I'm also going to convert some of my posts into more of a page/wiki format since I continue to update them over time.  This will take some work to keep the old permalinks working, so don't expect this anytime soon.

And for those interested in why I went the way I did:
- I used DNSimple.com to register my domain and host my DNS records. In part because I want nothing to do with GoDaddy as I disagree with them on many political and social topics. I choose DNSimple specifically because they have a clean but full feature management UI and got a hattip from Scott Hanselman.  Note: if you use the above link and sign-up, we'll both get a free month of DNS service.

- I'm using a "self-hosted" WordPress instance for my new site.  There were several things that lead me down this route. First, WordPress has a massive ecosystem, being one of (if not the) largest blogging platform on the net.  There's plugins/themes/etc available for just about anything you want to do, and most for free, so no need to reinvent the wheel. Additionally, it's standalone -- not tied to a hosting service -- and easily migrateable to another hosting provider in the future, should I want to change vendors.

- I'm planning to use Azure Websites for hosting.  While it does have a really nice web dashboard for viewing stats, etc., the biggest selling point for Azure over other hosting providers is the integration with WebMatrix, which makes it extraordinarily easy to pull an instance of the current website, database and all, down to my local machine in order to make changes, etc, in an isolated dev environment and upload them back to the production system (or destroy them) easily.  Pricing is reasonable and likely only to go down over time.  They also made is super easy (three clicks) to spin up a new WordPress site.

Feb 4, 2013

Part 6 of Writing Your Own .Net-based Installer with WiX - A Note About UAC

This article is one in my series focusing on what I learned creating a Windows Installer using the WiX toolkit’s "Managed Bootstrapper Application" (Custom .NET UI) framework.  Each post builds upon the previous posts, so I would suggest you at least skim through the earlier articles in the series.

UAC prompt
UAC, if you're not familiar, is the feature in Windows where applications that need elevated permissions will "ask" for it by having Window pop up a "This app is trying to do something serious -- Do you want to allow it?" dialog, while completely blocking out the rest of your desktop.  Many installers require UAC, because they install "Machine Wide" (ie: not specific to just the current User).
In the world of installers, there are two basic camps: force the permission elevation up front or request it only when you need it.  The former is easier, the latter is what Microsoft wants you to do.  The big catch: you can only request elevated permissions when you start a process - so once a process is already loaded, you can't elevate it.  Instead, you must start up a new process and use inter-process communication to feed data back and forth. 
In other .Net apps, to force the elevation up front, you just create an assembly manifest file with the appropriate markers.  However, the manifest in this case is actually associated with the WiX engine and you can't just change it. If you try to extract the manifest using the typical .net tools, modify it and reattach, it changes the byte signature of the assembly, and it appears that WiX uses hard-coded byte offsets to determine where the embedded files are located. The result: changing the manifest causes the engine to fail to find your assemblies.  You could download the WiX source code, change the embedded manifest file, recompile, etc.  Be careful, though -- I'm not a lawyer, but I believe the WiX reciprocal-style open source license would require you to open source your installer code if you go this route.
For the most part, the MSIs are the only parts that will need elevated access, and WiX takes care of all of that for you.  The only time you really need to worry about it is if you need to do something in your bootstrapper itself that requires elevated permissions (such as certain Registry operations, IIS operations, etc).
Also note that the base class exposes an Elevate() method.  This will force the WiX engine to spin up the elevated process it uses for running the MSIs when you call it (assuming it hasn't already been created). It does not elevate the current process (ie: your code). Sorry.
There are a couple of other notes:
UAC shieldIf UAC is in play, it is suggested you show the little "shield" icon on the button that immediately precedes the action that will prompt for elevation. But if UAC is not enabled, you shouldn't show it.  So how do you know if you should show the shield?  That's pretty easy, actually. There are two rules:
1) The operating system supports UAC (is a version after WinXP).  Here's a little helper to make that determination:
        /// <summary>
        /// True if the current operating system supports UAC.
        /// Vista or higher only.
        /// </summary>
        internal static bool OperatingSystemSupportsUAC
        {
            get { return Environment.OSVersion.Version.Major >= 6; }
        }
2) The process is not already running in administrator mode. If the user choose "Run as Administrator", or if it was started by another administrator process (such as the Add/Remove programs control panel), then it will not need to ask for elevation permissions.  Here's another helper: (add "using System.Security.Principal;" to your file)
        /// <summary>
        /// True if the current user is in the Admin group, or the process
        /// is already running with elevated permissions.
        /// </summary>
        private static bool UserIsRunningAsAdmin
        {
            get
            {
                var principal = new WindowsPrincipal(WindowsIdentity .GetCurrent());
                return principal.IsInRole( WindowsBuiltInRole.Administrator);
            }
        }
 
So, add them together, and you get this:
               var ShieldDisplayRequired = OperatingSystemSupportsUAC && !UserIsRunningAsAdmin;          

Getting access to the actual shield and putting it on a button is another issue altogether.  I used a combination of the concepts raised in these two postings, along with some special sauce of my own, which I won't repost here. But you should be able to get a good start from these links:
Note, though, that if your installer is not also signed, then the UAC prompt will alert the user that the installer is untrusted.  To really do this right, you should sign the installer too, but there’s a couple extra steps you must take to do that. I’ll post about that separately.

Jan 28, 2013

Part 5 of Writing Your Own .Net-based Installer with WiX - Executing the Action

This article is one in my series focusing on what I learned creating a Windows Installer using the WiX toolkit’s "Managed Bootstrapper Application" (Custom .NET UI) framework.  Each post builds upon the previous posts, so I would suggest you at least skim through the earlier articles in the series.

Running the action

Once the Engine's planning phase is complete (see previous post), we can call Engine.Apply(IntPtr.Zero) to execute the action. Note: the parameter to Apply() is a window handle.  You could also pass handle to your UI window, but getting that value is beyond what I want to get into here.  I believe this is used by Windows when prompting for UAC, but this all works fine with IntPtr.Zero. The Apply action will provide status via events as well:
           BootstrapperApplication.ExecuteMsiMessage += EventProviderOnExecuteMsiMessage;
           BootstrapperApplication.Progress += EventProviderOnProgress;
           BootstrapperApplication.ExecuteComplete += EventProviderOnExecuteComplete;
           BootstrapperApplication.ExecuteFilesInUse += EventProviderOnExecuteFilesInUse;
           BootstrapperApplication.ExecutePackageBegin += EventProviderOnExecutePackageBegin;
           BootstrapperApplication.ExecutePackageComplete += EventProviderOnExecutePackageComplete;
           
           BootstrapperApplication.ApplyComplete += BootstrapperOnApplyComplete;

        this.Engine.Apply(IntPtr.Zero);


The "ExecuteMsiMessage" provides some non-user friendly message from the MSI engine, which I just log.  I use the "ExecuteComplete" to set my percentage variables to 100% (since the last progess event might only by 95% or so) and the "ExecutePackageBegin"/"ExecutePackageComplete" to set a UI label saying "Currently installing XXX package".

The ExecutePackageBegin includes the packageId for the package currently being installed. You'll need to use that to lookup the Name, etc, from the Package models you generated previously (see Part 2 of this series).

        private void EventProviderOnExecutePackageBegin(object sender, ExecutePackageBeginEventArgs executePackageBeginEventArgs)
        {           
            var inFlightPkgId = executePackageBeginEventArgs.PackageId;
            var inFlightPkg = BundlePackages.FirstOrDefault(pkg => pkg.Id == inFlightPkgId);

            if (inFlightPkg == null)
            {
                CurrentlyProcessingPackageName = string.Empty;
            } else
            {
                CurrentlyProcessingPackageName = inFlightPkg.Name;
            }

        }


While the action is being performed, progress will be provided via events, which will tell you which package is currently being installed, percentage completions, etc.  One note: if a rollback is initiated due to a failure or error in the install, the progress percentages will decrease as the rollback occurs.  Also note, this is the best place to handle user cancellations (see below section for that topic).
        private void EventProviderOnProgress( object sender, ProgressEventArgs progressEventArgs)
        {
            //update local properties (which are likely bound to a ProgressBar or something
            CurrentComponentProgressPercentage = progressEventArgs.ProgressPercentage;
            OverallProgressPercentage = progressEventArgs.OverallPercentage;

            //... handle user cancellations
        }

For the "ExecuteFileInUse", I haven't actually been successful in forcing this error, but here's an example of the code I have to handle it:


        private void EventProviderOnExecuteFilesInUse(object sender, ExecuteFilesInUseEventArgs executeFilesInUseEventArgs)
        {
            var message =
                new StringBuilder("The following files are in use. Please close the applications that are using them.\n");
            foreach (var file in executeFilesInUseEventArgs.Files)
            {
                message.AppendLine(" - " + file);
            }

            var userButton = MessageBox.Show(message.ToString(), "Files In Use", MessageBoxButton.OKCancel, MessageBoxImage.Warning);
            if (userButton != MessageBoxResult.OK)               
                executeFilesInUseEventArgs.Result = Result.Cancel;
        }
When the apply action is complete, it will fire the ApplyComplete handler. This is where you can set status, etc. Here is what my method looks like:
        private void BootstrapperOnApplyComplete( object sender, ApplyCompleteEventArgs applyCompleteEventArgs)
        {
            BootstrapperApplication.ApplyComplete -= BootstrapperOnApplyComplete;

            //using "ActionResult" property to store the result for use
            // when I call Engine.Quit()
            if (applyCompleteEventArgs.Status >= 0)
            {
                ActionResult = ActionResult.Success;
            } else {
                ActionResult = ActionResult.Failure;
            }
        }

Finishing it out

When you're ready to close down the app, even if you haven't actually done anything (user cancellationetc), you'll need to call Engine.Quit() with one of these ActionResult values: (hint: you'll need to cast the Enums an int)
·         ActionResult.Success
-          The action was run and was successful.
·         ActionResult.UserExit
-          Action was cancelled by user, therefore was unsuccessful.
·         ActionResult.Failure
-          Action had errors and was unsuccessful.
·         ActionResult.NotExecuted
-          No actions were performed.
Be careful that you return the correct values, as that affects the return code of the executable (which the caller may be monitoring in a scripted install) as well how the Add/Remove Programs list shows (or doesn't show) your app and if locally cached instances of your installer are deleted, etc. An incorrect return value may result in a  Add/Remove programs listing that never gets removed on uninstall, or never shows up in the first place, and other oddities.
Note too that you'll need to handle closing your UI windows, etc, on your own -- calling Engine.Quit(does not close your UI or terminate your threads, etc.
                Engine.Quit((
 intActionResult.Success);

Canceling while action is being performed

Most of the WiX events have an EventArgs parameter that includes a Result property.  This can be used to cancel asynchronous engine operations.  For instance, the progress event fires frequently, so is a good candidate.  If the user clicks your cancel button during the install, you can set Result=Result.Cancel on the next event to signal the engine to stop and initiate the rollback process. This assumes you provide the user a cancel button.  You'll also want to monitor if the user closes your UI window using the "X" button in the top right corner.

        
private void EventProviderOnProgress( object sender, ProgressEventArgs progressEventArgs)
        {
            //....
            if (_userHasCancelled)
                progressEventArgs.Result = Result.Cancel;
        }