DCSIMG
April 2010 - Posts - Arik Poznanski's Blog

Arik Poznanski's Blog

It CAN be done with .NET

News

MVP

MCC

CodeProject MVP

MCPD

MCTS

Subscribe to my blog by email

Arik Poznanski LinkedIn Profile

Email: arik.com at gmail dot com
or, use this form

Locations of visitors to this page


Sela Group

Sela Canada

DZone MVB

Links

Official Blogs

WPF / SL Blogs

Developers Blogs

April 2010 - Posts

Application Recovery and Restart C# Quick Reference

Background

Application Recovery and Restart (ARR) is a feature that allows you to prepare for the impossible (?) case where your application crash or waits forever (“Not Responding”)

The feature lets you “register” for these cases in order to give you the opportunity to save the application data or do some clean up operations, before it ends its life.

This feature exists from Windows Vista, but it seems that not enough people knows it, so let’s see how can anyone use the Windows API Code Pack to easily integrate ARR in their applications.

More information on the feature can be found at Application Recovery and Restart on MSDN.

Step 1 – When to register?

The first step is quite obvious, but needs to be said nevertheless. You should register to ARR when the application loads and unregister when the application unloads.

public MainWindow()
{
    InitializeComponent();
    ...
    RegisterApplicationRecoveryAndRestart();
}

 

private void CloseButton_Click(object sender, RoutedEventArgs e)
{
    ...
    UnregisterApplicationRecoveryAndRestart();
    App.Current.Shutdown();
}

 

The functions RegisterApplicationRecoveryAndRestart and UnregisterApplicationRecoveryAndRestart are my functions which we will see on the next step.

Step 2 – How to Register?

Before using the ARR feature we check that we’re running on Windows Vista or up by using WindowsAPICodePack CoreHelper.RunningOnVista helper method.

private void RegisterApplicationRecoveryAndRestart()
{
    if (!CoreHelpers.RunningOnVista)
    {
        return;
    }

    // register for Application Restart
    RestartSettings restartSettings =
        new RestartSettings(string.Empty, RestartRestrictions.None);
    ApplicationRestartRecoveryManager.RegisterForApplicationRestart(restartSettings);

    // register for Application Recovery
    RecoverySettings recoverySettings =
        new RecoverySettings(new RecoveryData(PerformRecovery, null), KeepAliveInterval);
    ApplicationRestartRecoveryManager.RegisterForApplicationRecovery(recoverySettings);
}

Register for restart

Then we do two things. First we register for restart. The Windows Error Reporting component will present the user the restart dialog if the application had an unhandled exception or has been unresponsive for more than 60 seconds.

When registering for restart we supply an instance of RestartSettings. The first parameter it gets is the command line arguments that will be used for the restart, in case we want to define some special parameters (like “run in safe mode”).
The second parameters is an enum that allows us to restrict the restart in some cases, for example, we can set RestartRestriction.NotOnReboot if we don’t want our application to restart if the computer was restarted due to a system update.

Available restrictions are:

Restriction

Meaning

None No restart restrictions
NotOnCrash

Do not restart the process if it terminates due to an unhandled exception.

NotOnHang

Do not restart the process if it terminates due to the application not responding.

NotOnPatch

Do not restart the process if it terminates due to the installation of an update.

NotOnReboot

Do not restart the process if the computer is restarted as the result of an update.

Register for recovery

The second thing we do is register for recovery. This means that if the application will need a restart (from the same reasons as before), what function do we want to run to allow later recovery.

When registering for recovery we supply an instance of RecoverySettings. The first parameter it gets is the RecoveryData object, which wraps a delegate to be called and some state parameter that will be passed (in this example, null). The second parameter is the keep alive interval, which will be explained shortly.

Implementing the recovery function

The recovery function should obey some rules in order to avoid the application getting stuck (again) in the recovery function. You must call ApplicationRestartRecoveryManager.ApplicationRecoveryInProgress every few (mili)seconds (in the example, KeepAliveInterval = 5000). This tells the ARR mechanism, “I know it takes some time, but don’t worry, I’m still alive and working on the recovery stuff”.

Also, at the end of the recovery function you must call ApplicationRestartRecoveryManager.ApplicationRecoveryFinished with a parameter that indicates whether you succeeded in doing the recovery.

/// <summary>
/// Performs recovery by saving the state
/// </summary>
/// <param name="parameter">Unused.</param>
/// <returns>Unused.</returns>
private int PerformRecovery(object parameter)
{
    try
    {
        ApplicationRestartRecoveryManager.ApplicationRecoveryInProgress();
        
        // Save your work here for recovery
        ...

        ApplicationRestartRecoveryManager.ApplicationRecoveryFinished(true);
    }
    catch
    {
        ApplicationRestartRecoveryManager.ApplicationRecoveryFinished(false);
    }

    return 0;
}

Step 3 – How to unregister

private void UnregisterApplicationRecoveryAndRestart()
{
    if (!CoreHelpers.RunningOnVista)
    {
        return;
    }

    ApplicationRestartRecoveryManager.UnregisterApplicationRestart();
    ApplicationRestartRecoveryManager.UnregisterApplicationRecovery();
}

This is just some cleanup code to properly unregister from Application Recovery and Restart.

That’s it for now,
Arik Poznanski.

kick it on DotNetKicks.com Shout it

Windows Ribbon Framework - Visual Basic .NET Samples

Since so many people asked, I’ve created a Visual Basic .NET version of the Windows Ribbon for WinForms samples using Instant VB by Tangible Software Solutions.

Their demo version is limited to converting projects up to 1000 lines, but this was enough for me to convert the samples project.

The new VB.NET samples have been uploaded to the project site.

That’s it for now,
Arik Poznanski.

Crash while closing application that uses Windows Ribbon Framework

Since that’s the third time I’ve been asked about it, and in fact came across the problem myself, I thought I should blog my reply to help future users.

Problem Description

You use the Windows Ribbon Framework, either directly (in C++) or in managed code using my Windows Ribbon for WinForms library. You add a close button to the ribbon which closes the application. The application crash on close.

Don’t cut the branch you sit on

The problem is that you try to call ribbon.DestroyFramework, which ultimately calls IUIFramework.Destroy from a ribbon command handler. So while handling the ribbon event you try to kill the ribbon. It is only fair that the ribbon control fights back..

Solution

Either invoke the Close() method asynchronously:

void _exitButton_OnExecute(
    PropertyKeyRef key,
    PropVariantRef currentValue,
    IUISimplePropertySet commandExecutionProperties)
{
    // Close form asynchronously since we are in a ribbon event
    // handler, so the ribbon is still in use, and calling Close
    // will eventually call _ribbon.DestroyFramework(), which is
    // a big no-no, if you still use the ribbon.
    this.BeginInvoke(new MethodInvoker(this.Close));
}

or don’t call DestroyFramework when closing the application (and trust windows for releasing the resources).

[By the way, the C++ solution is simply to call PostMessage(WM_CLOSE) instead of SendMessage(WM_CLOSE)]

I’ve updated sample 04-TabGroupHelp on the project site so that it has a real exit button on the ribbon that closes the form.

That’s it for now,
Arik Poznanski.

kick it on DotNetKicks.com Shout it
Posted: Apr 14 2010, 12:28 AM by arik | with 4 comment(s) |
תגים:, , ,

WPF: Animate Visibility Property - Update

Back in this post I showed you how you can easily add a fade-in / fade-out effect to a UIElement that changes its Visibility property, using a simple attached property.

Some people encountered a problem using this property when they bind the UIElement to a model which initially hides the control. Since the default value of the Visibility property is Visible, using the attached property created an unwanted fade-out animation when the application started.

To fix this issue I added another attached property that allows the user to skip the first animation.

Also, I’ve fixed a minor issue with the double animation of the opacity.

For completion, I bring here the full updated source.
For more details on how the animation works, check the original post.

That’s it for now,
Arik Poznanski.

kick it on DotNetKicks.com Shout it

Appendix A – Updated Source Code for VisibilityAnimation class

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media.Animation;

namespace WPF.Common
{
    /// <summary>
    /// Supplies attached properties that provides visibility of animations
    /// </summary>
    public class VisibilityAnimation
    {
        public enum AnimationType
        {
            /// <summary>
            /// No animation
            /// </summary>
            None,
            /// <summary>
            /// Fade in / Fade out
            /// </summary>
            Fade
        }

        /// <summary>
        /// Animation duration
        /// </summary>
        private const int ANIMATION_DURATION = 200;

        /// <summary>
        /// List of hooked objects
        /// </summary>
        private static readonly Dictionary<FrameworkElement, bool> _hookedElements =
            new Dictionary<FrameworkElement, bool>();

        /// <summary>
        /// Get AnimationType attached property
        /// </summary>
        /// <param name="obj">Dependency object</param>
        /// <returns>AnimationType value</returns>
        public static AnimationType GetAnimationType(DependencyObject obj)
        {
            return (AnimationType)obj.GetValue(AnimationTypeProperty);
        }

        /// <summary>
        /// Set AnimationType attached property
        /// </summary>
        /// <param name="obj">Dependency object</param>
        /// <param name="value">New value for AnimationType</param>
        public static void SetAnimationType(DependencyObject obj, AnimationType value)
        {
            obj.SetValue(AnimationTypeProperty, value);
        }

        /// <summary>
        /// Using a DependencyProperty as the backing store for AnimationType.  
        /// This enables animation, styling, binding, etc...
        /// </summary>
        public static readonly DependencyProperty AnimationTypeProperty =
            DependencyProperty.RegisterAttached(
                "AnimationType",
                typeof(AnimationType),
                typeof(VisibilityAnimation),
                new FrameworkPropertyMetadata(AnimationType.None,
                    new PropertyChangedCallback(OnAnimationTypePropertyChanged)));

        /// <summary>
        /// Get IgnoreFirstTime attached property
        /// </summary>
        /// <param name="obj">Dependency object</param>
        /// <returns>IgnoreFirstTime value</returns>
        public static bool GetIgnoreFirstTime(DependencyObject obj)
        {
            return (bool)obj.GetValue(IgnoreFirstTimeProperty);
        }

        /// <summary>
        /// Set IgnoreFirstTime attached property
        /// </summary>
        /// <param name="obj">Dependency object</param>
        /// <param name="value">New value for IgnoreFirstTime</param>
        public static void SetIgnoreFirstTime(DependencyObject obj, bool value)
        {
            obj.SetValue(IgnoreFirstTimeProperty, value);
        }

        /// <summary>
        /// Using a DependencyProperty as the backing store for IgnoreFirstTime.  
        /// This enables animation, styling, binding, etc...
        /// </summary>
        public static readonly DependencyProperty IgnoreFirstTimeProperty =
            DependencyProperty.RegisterAttached(
                "IgnoreFirstTime",
                typeof(bool),
                typeof(VisibilityAnimation),
                new UIPropertyMetadata(false));


        /// <summary>
        /// AnimationType property changed
        /// </summary>
        /// <param name="dependencyObject">Dependency object</param>
        /// <param name="e">e</param>
        private static void OnAnimationTypePropertyChanged(
            DependencyObject dependencyObject,
            DependencyPropertyChangedEventArgs e)
        {
            var frameworkElement = dependencyObject as FrameworkElement;

            if (frameworkElement == null)
            {
                return;
            }

            // If AnimationType is set to True on this framework element,
            if (GetAnimationType(frameworkElement) != AnimationType.None)
            {
                // Add this framework element to hooked list
                HookVisibilityChanges(frameworkElement);
            }
            else
            {
                // Otherwise, remove it from the hooked list
                UnHookVisibilityChanges(frameworkElement);
            }
        }

        /// <summary>
        /// Add framework element to list of hooked objects
        /// </summary>
        /// <param name="frameworkElement">Framework element</param>
        private static void HookVisibilityChanges(FrameworkElement frameworkElement)
        {
            _hookedElements.Add(frameworkElement, false);
        }

        /// <summary>
        /// Remove framework element from list of hooked objects
        /// </summary>
        /// <param name="frameworkElement">Framework element</param>
        private static void UnHookVisibilityChanges(FrameworkElement frameworkElement)
        {
            if (_hookedElements.ContainsKey(frameworkElement))
            {
                _hookedElements.Remove(frameworkElement);
            }
        }

        /// <summary>
        /// VisibilityAnimation static ctor
        /// </summary>
        static VisibilityAnimation()
        {
            // Here we "register" on Visibility property "before change" event
            UIElement.VisibilityProperty.AddOwner(
                typeof(FrameworkElement),
                new FrameworkPropertyMetadata(
                    Visibility.Visible,
                    VisibilityChanged,
                    CoerceVisibility));
        }

        /// <summary>
        /// Visibility changed
        /// </summary>
        /// <param name="dependencyObject">Dependency object</param>
        /// <param name="e">e</param>
        private static void VisibilityChanged(
            DependencyObject dependencyObject,
            DependencyPropertyChangedEventArgs e)
        {
            // Ignore
        }

        /// <summary>
        /// Coerce visibility
        /// </summary>
        /// <param name="dependencyObject">Dependency object</param>
        /// <param name="baseValue">Base value</param>
        /// <returns>Coerced value</returns>
        private static object CoerceVisibility(
            DependencyObject dependencyObject,
            object baseValue)
        {
            // Make sure object is a framework element
            var frameworkElement = dependencyObject as FrameworkElement;
            if (frameworkElement == null)
            {
                return baseValue;
            }

            // Cast to type safe value
            var visibility = (Visibility)baseValue;

            // If Visibility value hasn't change, do nothing.
            // This can happen if the Visibility property is set using data
            // binding and the binding source has changed
            // but the new visibility value hasn't changed.
            if (visibility == frameworkElement.Visibility)
            {
                return baseValue;
            }

            // If element is not hooked by our attached property, stop here
            if (!IsHookedElement(frameworkElement))
            {
                return baseValue;
            }

            // if element has IgnoreFirstTime flag set, then ignore the first time
            // the property is coerced.
            if (GetIgnoreFirstTime(frameworkElement))
            {
                SetIgnoreFirstTime(frameworkElement, false);
                return baseValue;
            }

            // Update animation flag
            // If animation already started - don't restart it (otherwise, infinite loop)
            if (UpdateAnimationStartedFlag(frameworkElement))
            {
                return baseValue;
            }

            // If we get here, it means we have to start fade in or fade out animation.
            // In any case return value of this method will be Visibility.Visible,
            // to allow the animation.
            var doubleAnimation = new DoubleAnimation
            {
                Duration = new Duration(TimeSpan.FromMilliseconds(ANIMATION_DURATION))
            };

            // When animation completes, set the visibility value to the requested
            // value (baseValue)
            doubleAnimation.Completed += (sender, eventArgs) =>
            {
                if (visibility == Visibility.Visible)
                {
                    // In case we change into Visibility.Visible, the correct value
                    // is already set
                    // So just update the animation started flag
                    UpdateAnimationStartedFlag(frameworkElement);
                }
                else
                {
                    // This will trigger value coercion again
                    // but UpdateAnimationStartedFlag() function will reture true this time,
                    // thus animation will not be triggered.
                    if (BindingOperations.IsDataBound(frameworkElement,
                        UIElement.VisibilityProperty))
                    {
                        // Set visiblity using bounded value
                        Binding bindingValue = BindingOperations.GetBinding(frameworkElement,
                            UIElement.VisibilityProperty);
                        BindingOperations.SetBinding(frameworkElement,
                            UIElement.VisibilityProperty, bindingValue);
                    }
                    else
                    {
                        // No binding, just assign the value
                        frameworkElement.Visibility = visibility;
                    }
                }
            };

            if (visibility == Visibility.Collapsed || visibility == Visibility.Hidden)
            {
                // Fade out by animating opacity
                doubleAnimation.From = (double)frameworkElement.GetValue(
                    UIElement.OpacityProperty);
                doubleAnimation.To = 0.0;
            }
            else
            {
                // Fade in by animating opacity
                doubleAnimation.From = (double)frameworkElement.GetValue(
                    UIElement.OpacityProperty);
                doubleAnimation.To = 1.0;
            }

            // Start animation
            frameworkElement.BeginAnimation(UIElement.OpacityProperty, doubleAnimation);

            // Make sure the element remains visible during the animation
            // The original requested value will be set in the completed event of
            // the animation
            return Visibility.Visible;
        }

        /// <summary>
        /// Check if framework element is hooked with AnimationType property
        /// </summary>
        /// <param name="frameworkElement">Framework element to check</param>
        /// <returns>Is the framework element hooked?</returns>
        private static bool IsHookedElement(FrameworkElement frameworkElement)
        {
            return _hookedElements.ContainsKey(frameworkElement);
        }

        /// <summary>
        /// Update animation started flag or a given framework element
        /// </summary>
        /// <param name="frameworkElement">Given framework element</param>
        /// <returns>Old value of animation started flag</returns>
        private static bool UpdateAnimationStartedFlag(FrameworkElement frameworkElement)
        {
            var animationStarted = _hookedElements[frameworkElement];
            _hookedElements[frameworkElement] = !animationStarted;

            return animationStarted;
        }
    }
}
Posted: Apr 13 2010, 01:19 AM by arik | with 4 comment(s) |
תגים:, , , ,