I have the following code in a WPF application that shows a splash screen while a long running process happens. On all of our developer machines and testing machines this works perfectly. However on some customer machines this code is leaving the main process running.
I've tried various methods of calling a shutdown including Environment.Exit(0);
and we are still seeing this process left running after it has completed.
Is there something that I have missed about how my task and the application are interacting?
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.IO.Pipes;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace GKUpdate
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
MainWindow oWindow;
string sPipeName;
string sGKPath;
//Call base startup
base.OnStartup(e);
//Find the GK path
sPipeName = FindArgument(e.Args, "n");
sGKPath = FindArgument(e.Args, "p");
//Check if we have a path
if (!string.IsNullOrEmpty(sGKPath))
{
//Start listening
Task.Factory.StartNew(() => ListenForSuccess(sPipeName, sGKPath));
//Show the splash window
oWindow = new MainWindow();
oWindow.Show();
}
else
{
//Exit
this.Shutdown();
}
}
private string FindArgument(string[] oArgs, string sArgumentName)
{
string sFilter;
string sArgument;
//Get the argument
sFilter = string.Format("/{0}=", sArgumentName).ToLower();
sArgument = oArgs.FirstOrDefault(x => x.ToLower().StartsWith(sFilter));
//Check if we found the argument
if (!string.IsNullOrEmpty(sArgument) && sArgument.Length > sFilter.Length)
{
//Set the argument
sArgument = sArgument.Substring(sFilter.Length).Trim('"');
}
else
{
//Set null
sArgument = null;
}
//Return the argument
return sArgument;
}
private void ListenForSuccess(string sPipeName, string sGKPath)
{
int iStatus;
try
{
//Set default status
iStatus = -1;
//Loop until the service is online
do
{
//Create the named pipe
using (NamedPipeClientStream oNamedPipe = new NamedPipeClientStream(".", sPipeName, PipeDirection.InOut))
{
//Connect the pipe allowing 5 mins
oNamedPipe.Connect(300000);
//Send the byte asking for a status report
oNamedPipe.WriteByte(0);
oNamedPipe.WaitForPipeDrain();
//Read the return
iStatus = oNamedPipe.ReadByte();
//Disconnect
oNamedPipe.Close();
}
} while (iStatus != 1);
//Check if we can do the success actions
if (iStatus == 1)
{
//Start GateKeeper using the remaining command arguments
Process.Start(sGKPath, string.Join(" ", Environment.GetCommandLineArgs().Skip(3)));
}
}
catch (Exception)
{
//Do nothing
}
finally
{
//Exit the application
Application.Current.Dispatcher.InvokeShutdown();
}
}
}
}