Click or drag to resize
VoicepackUpdater Class
Provides the functionality needed to update the ATC voicepack of Microsoft Flight Simulator X and Lockheed Martin’s Prepar3D® simulation software.
Inheritance Hierarchy
SystemObject
  Bevelstone.EditVoicepack.InstallerApiVoicepackUpdater

Namespace: Bevelstone.EditVoicepack.InstallerApi
Assembly: Bevelstone.EditVoicepack.InstallerApi (in Bevelstone.EditVoicepack.InstallerApi.dll) Version: 5.0.77.0 (5.0.77.0)
Syntax
public class VoicepackUpdater : INotifyPropertyChanged, 
	IDisposable

The VoicepackUpdater type exposes the following members.

Constructors
  NameDescription
Public methodVoicepackUpdater
Initializes a new instance of the VoicepackUpdater class.
Top
Methods
  NameDescription
Public methodCancel
Asynchroniously cancels the current voicepack update.
Public methodDispose
Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
Public methodEquals
Determines whether the specified Object is equal to the current Object.
(Inherited from Object.)
Public methodExecute
Executes the voicepack update asynchroniously.
Public methodExecute(IntPtr)
Executes the voicepack update asynchroniously using the specified window as a parent window for the UAC dialog.
Protected methodFinalize
Allows an object to try to free resources and perform other cleanup operations before it is reclaimed by garbage collection.
(Inherited from Object.)
Public methodGetHashCode
Serves as a hash function for a particular type.
(Inherited from Object.)
Public methodGetType
Gets the type of the current instance.
(Inherited from Object.)
Protected methodMemberwiseClone
Creates a shallow copy of the current Object.
(Inherited from Object.)
Public methodToString
Returns a string that represents the current object.
(Inherited from Object.)
Top
Properties
  NameDescription
Public propertyIsCancelAllowed
Gets a value indicating if it's currently possible to cancel the voicepack update.
Public propertyIsCanceled
Gets a value indicating whether the voicepack update has been canceled.
Public propertyIsCompleted
Gets a value indicating whether the voicepack update has completed, either successfully or due to the update being canceled or failing.
Public propertyIsProcessElevationRequired
Gets a value indicating whether process elevation is required to update the Voicepack.
Public propertyProgressPercentage
Gets the current progress as a percentage.
Public propertyProgressText
Gets a short string identifying the current task the voicepack updater is performing.
Public propertyUpdateError
Gets the exception raised if the voicepack update failed.
Top
Events
  NameDescription
Public eventPropertyChanged
Occurs when a property value changes.
Top
Remarks
When integrating the VoicepackUpdater with an application or installer, the typical flow is as follows:
  1. Instantiate the VoicepackUpdater.
  2. If IsProcessElevationRequired returns true display the UAC shield on any user interface menu item or button used to start the update.
  3. Call Execute(IntPtr) to start the ATC voicepack update.
  4. Monitor the progress events through the PropertyChanged event and provide feedback to the user:
  5. Allow the user to cancel the update, as long as:
  6. Once IsCompleted is true, check if UpdateError is null. If this is not the case, display the error text to the user.

    Notice that in case the error is an UpdateVoicepackException, the real course of the error can be retreived through the ExceptionMessages and BaseExceptionMessage properties.

    The full stack trace is available for debugging purpose through the DebugInformation property.

  7. Dispose the VoicepackUpdater.
Examples
A WinForm based installer application. The full set of source files including Visual Studio 2010 project files are included with the API.
C#
using System;
using System.ComponentModel;
using System.Windows.Forms;
using Bevelstone.EditVoicepack.InstallerApi;
using Microsoft.Win32;

namespace Bevelstone.EditVoicepack.ExampleInstaller
{
    public partial class MainForm : Form
    {
        private VoicepackUpdater updater;

        public MainForm()
        {
            InitializeComponent();
        }

        /// <summary>
        ///     Called once the form is shown on the screen.
        /// </summary>
        /// <param name="sender">
        ///     The sender.
        /// </param>
        /// <param name="e">
        ///     The EventArgs instance containing the event data.
        /// </param>
        /// <remarks>
        ///     Waiting until the form is shown allows it to be used
        ///     as the parent window for the UAC dialog in case
        ///     it needs to be displayed.
        /// </remarks>
        private void FormShownHandler(object sender, EventArgs e)
        {
            string flightSimFolder = FindFlightSimDirectoryFromRegistry();
            if (flightSimFolder == null)
            {
                MessageBox.Show(this, "Unable to locate Flight Simulator X from the registry.",
                                "ATC Voicepack Installer", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Close();
                return;
            }

            // Instantiate and start the update process.
            updater = new VoicepackUpdater(flightSimFolder);
            updater.PropertyChanged += PropertyChangedHandler;
            try
            {
                updater.Execute(Handle);
            }
            catch (Win32Exception ex)
            {
                updater.Dispose();
                updater = null;
                // Check if it is a normal UAC cancel
                if (ex.NativeErrorCode == 1223) Close();
                else throw;
            }
        }

        /// <summary>
        ///     Called when the user click the cancel button.
        /// </summary>
        /// <param name="sender">
        ///     The sender.
        /// </param>
        /// <param name="e">
        ///     The EventArgs instance containing the event data.
        /// </param>
        /// <remarks>
        ///     If the update is already completed close the form.
        ///     If the update is not completed request the updater to cancel
        ///     but do not close the form until the cancelation is completed.
        /// </remarks>
        private void CancelButtonClickHandler(object sender, EventArgs e)
        {
            if (updater == null || updater.IsCompleted) Close();
            else updater.Cancel();
        }

        /// <summary>
        ///     Called by the VoicepackUpdater as it's properties are changed.
        /// </summary>
        /// <param name="sender">
        ///     The sender.
        /// </param>
        /// <param name="e">
        ///     The PropertyChangedEventArgs instance containing the event data.
        /// </param>
        void PropertyChangedHandler(object sender, PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "ProgressText":
                    progressTextLabel.Text = updater.ProgressText;
                    break;
                case "ProgressPercentage":
                    progressBar.Value = updater.ProgressPercentage;
                    break;
                case "IsCancelAllowed":
                    // Ensure the user can use the cancel button to close once the
                    // update is completed.
                    cancelButton.Enabled = updater.IsCancelAllowed || updater.IsCompleted;
                    break;
                case "IsCompleted":
                    if (updater.IsCompleted) UpdateCompleted();
                    break;
            }
        }

        /// <summary>
        ///     Executed once the voicepack update is completed.
        /// </summary>
        private void UpdateCompleted()
        {
            if (updater.IsCanceled)
            {
                // The user requested a cancel, so close the window.
                Close();
            }
            else if (updater.UpdateError == null)
            {
                // Normal termination
                cancelButton.Text = "Close";
                cancelButton.Enabled = true;
            }
            else
            {
                // Termination with error
                string errorMsg = "Updating the ATC voicepack failed with the following error:" + Environment.NewLine;
                if (updater.UpdateError is UpdateVoicepackException)
                {
                    errorMsg += ((UpdateVoicepackException)updater.UpdateError).BaseExceptionMessage;
                }
                else
                {
                    errorMsg += updater.UpdateError.GetBaseException().Message;
                }
                MessageBox.Show(this, errorMsg, "ATC Voicepack Installer", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Close();
            }
        }

        /// <summary>
        ///     Called when the Form is being closed.
        /// </summary>
        /// <param name="sender">
        ///     The sender.
        /// </param>
        /// <param name="e">
        ///     The FormClosingEventArgs instance containing the event data.
        /// </param>
        /// <remarks>
        ///     If the update is in progress cancel it but keep the window open.
        /// </remarks>
        private void FormClosingHandler(object sender, FormClosingEventArgs e)
        {
            if (updater != null && !updater.IsCompleted)
            {
                updater.Cancel();
                e.Cancel = true;
            }
        }

        /// <summary>
        ///     Called when the form has been closed
        /// </summary>
        /// <param name="sender">
        ///     The sender.
        /// </param>
        /// <param name="e">
        ///     The FormClosedEventArgs instance containing the event data.
        /// </param>
        /// <remarks>
        ///     Ensure Dispose is called on the VoicepackUpdater.
        /// </remarks>
        private void FormCloseHandler(object sender, FormClosedEventArgs e)
        {
            if (updater != null) updater.Dispose();
        }

        /// <summary>
        ///     Finds the root directory of Flight Simulator X based on the registry
        ///     key created by the installer.
        /// </summary>
        /// <returns>
        ///     The location of the root folder; or <c>null</c> if the registry key
        ///     indicating the root folder could not be found.
        /// </returns>
        /// <remarks>
        ///     Supports both 32 and 64 bit environments.
        /// </remarks>
        private static string FindFlightSimDirectoryFromRegistry()
        {
            string result;
            RegistryKey key = null;

            string keyPath = @"SOFTWARE\Microsoft\Microsoft Games\Flight Simulator\10.0";
            if (IntPtr.Size == 8) keyPath = @"SOFTWARE\Wow6432Node\Microsoft\Microsoft Games\Flight Simulator\10.0";

            try
            {
                key = Registry.LocalMachine.OpenSubKey(keyPath, false);
                if (key == null) return null;

                result = (string)key.GetValue("SetupPath");
            }
            finally
            {
                if (key != null) key.Close();
            }

            return result;
        }
    }
}
See Also