Skip to content

Instantly share code, notes, and snippets.

@mrichman
Forked from anonymous/Console Output
Last active August 29, 2015 14:00
Show Gist options
  • Save mrichman/40ced4a50589c9f0f119 to your computer and use it in GitHub Desktop.
Save mrichman/40ced4a50589c9f0f119 to your computer and use it in GitHub Desktop.
ModuleBase.ReportProgress() [CLTDEPAPI10] [1]% [Installing Mobile Recruiter]
ModuleBase.ReportProgress() [CLTDEPFE1] [1]% [Installing Mobile Recruiter]
ModuleBase.ReportProgress() [CLTDEPAPI11] [1]% [Installing Mobile Recruiter]
ModuleBase.ReportProgress() [CLTDEPFE1] [5]% [Invoking installer agent at net.tcp://cltdepfe1:8890/]
ModuleBase.ReportProgress() [CLTDEPAPI11] [5]% [Invoking installer agent at net.tcp://cltdepapi11:8890/]
ModuleBase.ReportProgress() [CLTDEPAPI10] [5]% [Invoking installer agent at net.tcp://cltdepapi10:8890/]
#region
using System;
using System.ComponentModel;
using System.ServiceModel;
using NLog;
#endregion
namespace Cmc.Installer.Agent.Client
{
/// <summary>
/// This is the client library that wraps the InstallerAgentService.InstallerAgentServiceClient WCF service reference.
/// By default WCF will attempt to dispatch using an available SynchronizationContext.
/// The problem with this callback is the UI thread is already blocked in an outbound call.
/// For the call to dispatch we need to tell WCF not to use the SynchronizationContext.
/// </summary>
//[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
public sealed class InstallerAgentServiceClient : IInstallerAgentServiceClient, InstallerAgentService.IInstallerAgentServiceCallback, IDisposable
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private readonly InstallerAgentService.InstallerAgentServiceClient _client; // WCF client proxy
private readonly IInstallModule _installModule;
/// <summary>
/// Initializes a new instance of the <see cref="InstallerAgentServiceClient" /> class.
/// </summary>
/// <param name="module">The module.</param>
/// <param name="endpointAddress">The endpoint address.</param>
public InstallerAgentServiceClient(IInstallModule module, EndpointAddress endpointAddress)
{
try
{
// Each service client instance receives its own context
var instanceContext = new InstanceContext(this);
_client = new InstallerAgentService.InstallerAgentServiceClient(instanceContext, new NetTcpBinding(),
endpointAddress);
_installModule = module;
}
catch (Exception ex)
{
Logger.Error(ex.Message);
throw;
}
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
Dispose(true);
//GC.SuppressFinalize(this); //TODO Is this safe?
}
/// <summary>
/// Called when [update progress].
/// </summary>
/// <param name="progressPercentage">The progress.</param>
/// <exception cref="System.NotImplementedException"></exception>
public void OnUpdateProgress(int progressPercentage)
{
//Logger.Trace("OnUpdateProgress = " + progressPercentage);
var args = new ProgressChangedEventArgs(progressPercentage, null);
Progress = progressPercentage;
_installModule.OnProgressChanged(this, args);
}
/// <summary>
/// Called when [install complete].
/// </summary>
public void OnInstallComplete()
{
Logger.Trace("InstallerAgentServiceClient.OnInstallComplete()");
var handler = InstallCompleted;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
/// <summary>
/// Called when [uninstall complete].
/// </summary>
/// <exception cref="System.NotImplementedException"></exception>
public void OnUninstallComplete()
{
//_installModule.OnAfterUninstall();
}
/// <summary>
/// Gets the progress.
/// </summary>
/// <value>
/// The progress.
/// </value>
public int Progress { get; set; }
/// <summary>
/// Installs the specified installer path.
/// </summary>
/// <param name="installerPath">The installer path.</param>
/// <param name="commandLine">The command line.</param>
public void Install(string installerPath, string commandLine)
{
//TODO May need to introduce a delay to account for WCF service startup time
try
{
// Invoke Cmc.Installer.Agent.InstallerAgentService::Install() via Net.Tcp
_client.Install(installerPath, commandLine);
}
catch (EndpointNotFoundException enfe)
{
Logger.ErrorException("Endpoint not found: " + enfe.Message, enfe);
throw;
}
catch (ProtocolException pe)
{
// Are you sure you're connecting to a Net.Tcp port and not a mex (http) port?
Logger.ErrorException(pe.Message, pe);
throw;
}
}
/// <summary>
/// Uninstalls the specified installer path.
/// </summary>
/// <param name="installerPath">The installer path.</param>
/// <exception cref="System.NotImplementedException"></exception>
public void Uninstall(string installerPath)
{
// Invoke Cmc.Installer.Agent.InstallerAgentService::Uninstall() via Net.Tcp
_client.Uninstall(installerPath);
}
/// <summary>
/// Occurs when [progress changed].
/// </summary>
public event ProgressChangedEventHandler ProgressChanged;
/// <summary>
/// Occurs when [install completed].
/// </summary>
public event EventHandler InstallCompleted;
/// <summary>
/// Releases unmanaged and - optionally - managed resources.
/// </summary>
/// <param name="disposing">
/// <c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only
/// unmanaged resources.
/// </param>
private void Dispose(bool disposing)
{
if (disposing)
_client.Close();
}
}
}
#region
using System;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.ServiceModel;
using System.Threading.Tasks;
using Cmc.Installer.Agent.Client;
using Cmc.Installer.Infrastructure;
using Cmc.Installer.Modules.MobileRecruiter.Views;
using Microsoft.Practices.Prism.MefExtensions.Modularity;
using Microsoft.Practices.Prism.Regions;
#endregion
namespace Cmc.Installer.Modules.MobileRecruiter
{
/// <summary>
/// Mobile Recruiter Module
/// </summary>
[ModuleExport(typeof (MobileRecruiterModule))]
public sealed class MobileRecruiterModule : ModuleBase, IDisposable
{
[Import] public IRegionManager Region;
/// <summary>
/// The installer agent service client. Note: If this lived in ModuleBase
/// it would create a circular dependency with Cmc.Installer.Agent.Client
/// </summary>
private InstallerAgentServiceClient _installerAgentServiceClient;
/// <summary>
/// Gets the name of the module.
/// </summary>
/// <value>
/// The name of the module.
/// </value>
public override string ModuleName
{
get { return "Mobile Recruiter"; }
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
_installerAgentServiceClient.Dispose();
}
/// <summary>
/// Determines if module prerequisites are satisfied
/// </summary>
/// <param name="targetMachine"></param>
/// <returns></returns>
/// <exception cref="System.NotImplementedException"></exception>
public override bool PrerequisitesSatisfied(string targetMachine)
{
throw new NotImplementedException();
}
/// <summary>
/// Installs the specified target machine.
/// </summary>
/// <param name="targetMachine">The target machine.</param>
/// <param name="progress">The progress.</param>
/// <returns></returns>
public override async Task<int> Install(string targetMachine, IProgress<InstallProgress> progress)
{
Progress = progress;
ReportProgress(progress, targetMachine, 1, "Installing " + ModuleName);
LoadSettings();
var msi = Settings.MobileRecruiterModule.MSIs.MSI.Path.Value;
var msiArgs = Settings.MobileRecruiterModule.MSIs.MSI.CommandLine.Value;
//TODO make port configurable at runtime via app.config with fallback of 8890 or whatever
var uri = new Uri("net.tcp://" + targetMachine + ":8890");
var endpointAddress = new EndpointAddress(uri);
ReportProgress(Progress, targetMachine, 5, "Invoking installer agent at " + uri);
_installerAgentServiceClient = new InstallerAgentServiceClient(this, endpointAddress);
// Bubble progress events back up to WPF Shell
_installerAgentServiceClient.ProgressChanged += (sender, args) =>
{
Debug.WriteLine("InstallerAgentServiceClient.ProgressChanged: {0}", args.ProgressPercentage);
ReportProgress(Progress, targetMachine, args.ProgressPercentage, args.UserState.ToString());
};
var ret = await _installerAgentServiceClient.Install(msi, msiArgs);
return ret;
}
/// <summary>
/// Uninstalls the specified target machine.
/// </summary>
/// <param name="targetMachine">The target machine.</param>
/// <param name="progress">The progress.</param>
/// <returns></returns>
/// <exception cref="System.NotImplementedException"></exception>
public override Task<int> Uninstall(string targetMachine, IProgress<InstallProgress> progress)
{
throw new NotImplementedException();
}
/// <summary>
/// Notifies the module that it has be initialized.
/// </summary>
public override void Initialize()
{
Region.RegisterViewWithRegion(RegionNames.MainContentRegion, typeof (MobileRecruiterView));
}
}
}
#region
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.Practices.Prism.Modularity;
#endregion
namespace Cmc.Installer
{
public abstract class ModuleBase : IModule, IInstallModule
{
protected IProgress<InstallProgress> Progress;
protected dynamic Settings;
private string _targetMachine;
public event ProgressChangedEventHandler ProgressChanged;
public event InstallCompletedEventHandler InstallCompleted;
/// <summary>
/// Gets the name of the module.
/// </summary>
/// <value>
/// The name of the module.
/// </value>
public abstract string ModuleName { get; }
/// <summary>
/// Determines if module prerequisites are satisfied
/// </summary>
/// <param name="targetMachine"></param>
/// <returns></returns>
public abstract bool PrerequisitesSatisfied(string targetMachine);
/// <summary>
/// Called when [progress changed].
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="args">The <see cref="ProgressChangedEventArgs" /> instance containing the event data.</param>
public virtual void OnProgressChanged(object sender, ProgressChangedEventArgs args)
{
ReportProgress(Progress, _targetMachine, args.ProgressPercentage);
}
/// <summary>
/// Loads the settings.
/// </summary>
/// <exception cref="System.IO.FileNotFoundException"></exception>
/// <exception cref="Cmc.Installer.ModuleSettingsNotFoundException"></exception>
public virtual void LoadSettings()
{
var currentDirectory = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
if (!File.Exists(currentDirectory + @"\settings.xml"))
{
throw new FileNotFoundException(currentDirectory + @"\settings.xml");
}
Settings = SettingsReader.LoadSettings(currentDirectory + @"\settings.xml");
// Verify that settings.xml contains a <Modules><MobileRecruiterModule></MobileRecruiterModule></Modules> section
if (Settings.Modules == null || Settings.Modules.MobileRecruiterModule == null)
{
throw new ModuleSettingsNotFoundException();
}
}
/// <summary>
/// Installs the specified target machine.
/// </summary>
/// <param name="targetMachine">The target machine.</param>
/// <param name="progress">The progress.</param>
/// <returns></returns>
public abstract Task<int> Install(string targetMachine, IProgress<InstallProgress> progress);
/// <summary>
/// Uninstalls the specified target machine.
/// </summary>
/// <param name="targetMachine">The target machine.</param>
/// <param name="progress">The progress.</param>
/// <returns></returns>
public abstract Task<int> Uninstall(string targetMachine, IProgress<InstallProgress> progress);
/// <summary>
/// Notifies the module that it has be initialized.
/// </summary>
public abstract void Initialize();
/// <summary>
/// Installs the asynchronous.
/// </summary>
/// <param name="targetMachine">The target machine.</param>
/// <param name="progress">The progress.</param>
/// <returns></returns>
public virtual Task<InstallCompletedResult> InstallAsync(string targetMachine, IProgress<InstallProgress> progress = null)
{
var tcs = new TaskCompletionSource<InstallCompletedResult>();
InstallCompletedEventHandler handler = null;
handler = (s, e) =>
{
InstallCompleted -= handler;
if (e.Exception != null)
tcs.TrySetException(e.Exception);
else
tcs.TrySetResult(e.Result);
};
InstallCompleted += handler;
Install(targetMachine, progress);
return tcs.Task;
}
/// <summary>
/// Reports the progress.
/// </summary>
/// <param name="progress">The progress.</param>
/// <param name="machineName">Name of the machine.</param>
/// <param name="progressPercentage">The progress percentage.</param>
/// <param name="message">The message.</param>
protected void ReportProgress(IProgress<InstallProgress> progress, string machineName, int progressPercentage,
string message = "")
{
if (progress == null) return;
Debug.WriteLine("ModuleBase.ReportProgress() [{0}] [{1}%] [{2}]", machineName, progressPercentage,
message);
progress.Report(new InstallProgress
{
MachineName = machineName,
ProgressPercentage = progressPercentage,
Message = message
});
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment