aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Tango.Logging/ApplicationCrashedEventArgs.cs
blob: 259089578d90ae9070d6c6b547a4389f1b202796 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Tango.Logging
{
    /// <summary>
    /// Represents an application crash event arguments
    /// </summary>
    /// <seealso cref="System.EventArgs" />
    public class ApplicationCrashedEventArgs : EventArgs
    {
        /// <summary>
        /// Gets or sets the error.
        /// </summary>
        public Exception Exception { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether to attempt recovering from this crash and ignoring the exception.
        /// </summary>
        public bool TryRecover { get; set; }

        /// <summary>
        /// Initializes a new instance of the <see cref="ApplicationCrashedEventArgs"/> class.
        /// </summary>
        /// <param name="exception">The error.</param>
        public ApplicationCrashedEventArgs(Exception exception)
        {
            Exception = exception;
        }
    }
}
light .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
using Ionic.Zip;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Tango.BL;
using Tango.Core;
using Tango.Core.DB;
using Tango.Core.DI;
using Tango.MachineStudio.Common.Web;
using Tango.SQLExaminer;
using Tango.Transport.Web;
using Tango.Core.ExtensionMethods;
using Tango.PPC.Common.Publish;
using Tango.Settings;
using Tango.Core.Components;
using System.Text.RegularExpressions;

namespace Tango.MachineStudio.Common.Tup
{
    public class TupFileBuilder : ExtendedObject
    {
        public event EventHandler<TupFileBuilderProgressEventArgs> Progress;

        public Task Build(String serialNumber, String filePath)
        {
            return Task.Factory.StartNew(() =>
            {
                String tempDbName = "Tango_TUP";
                var tempPackageFolder = TemporaryManager.CreateFolder();
                String tempBackupFolder = "C:\\MachineStudioTUP";
                String tempBackupFile = Path.Combine(tempBackupFolder, tempDbName + ".bak");
                var tempZipFile = TemporaryManager.CreateImaginaryFile();
                DbManager dbManager = null;

                LogManager.Log("Generating tup file...");
                LogManager.Log($"Tup file: '{filePath}.'");
                LogManager.Log($"Temporary db name: '{tempDbName}'.");
                LogManager.Log($"Temporary package folder: '{tempPackageFolder}'.");
                LogManager.Log($"Temporary db backup folder: '{tempBackupFolder}'.");
                LogManager.Log($"Temporary db backup file: '{tempBackupFile}'.");
                LogManager.Log($"Temporary zip file: '{tempZipFile}'.");

                try
                {
                    LogManager.Log("Initializing...");

                    OnProgress("Initializing...");

                    Core.DataSource localDataSource = new Core.DataSource()
                    {
                        Address = "localhost\\SQLEXPRESS",
                        IntegratedSecurity = true,
                        Type = DataSourceType.SQLServer,
                        Catalog = null,
                    };

                    try
                    {
                        LogManager.Log($"Trying to connect via SQLEXPRESS:\n{localDataSource.ToJsonString()}");
                        dbManager = DbManager.FromDataSource(localDataSource);
                    }
                    catch (Exception ex)
                    {
                        try
                        {
                            LogManager.Log(ex, "Could not connect using SQLEXPRESS. Trying local DB...");

                            CmdCommand command = new CmdCommand("sqllocaldb", "start \"MSSQLLocalDB\"");
                            var result = command.Run().Result;

                            command = new CmdCommand("sqllocaldb", "info \"MSSQLLocalDB\"");
                            result = command.Run().Result;

                            String pattern = "np:.+";
                            Regex reg = new Regex(pattern);
                            var match = reg.Match(result.StandardOutput);
                            String address = match.ToString();
                            if (address.Contains("np:"))
                            {
                                localDataSource.Address = address;
                                address = address.Trim().Replace("\r", "");
                            }
                            else
                            {
                                throw new ArgumentException("Could not parse LocalDB address string.");
                            }

                            LogManager.Log($"Trying to connect via LocalDB:\n{localDataSource.ToJsonString()}");
                            dbManager = DbManager.FromDataSource(localDataSource);
                        }
                        catch (Exception x)
                        {
                            LogManager.Log(x, "Could not find any database service for this operation.");
                            throw x;
                        }
                    }



                    OnProgress("Downloading latest PPC version...");

                    LogManager.Log("Connecting to machine service...");
                    MachineStudioWebClient client = TangoIOC.Default.GetInstance<MachineStudioWebClient>();

                    LogManager.Log("Requesting latest PPC version from machine service...");
                    var response = client.DownloadLatestPPCVersion(new DownloadLatestPPCVersionRequest() { SerialNumber = serialNumber }).Result;

                    LogManager.Log($"Machine service response:\n{response.ToJsonString()}");

                    var remoteDataSource = response.DataSource;

                    using (AutoFileDownloader downloader = new AutoFileDownloader(response.BlobAddress, response.CdnAddress, tempZipFile))
                    {
                        downloader.Progress += (x, e) =>
                        {
                            OnProgress($"Downloading latest PPC version '{response.Version}'...", false, e.Current, e.Total);
                        };

                        downloader.ResolveMode().GetAwaiter().GetResult();

                        LogManager.Log($"Downloading latest PPC version from: '{downloader.Address}'");

                        downloader.Download().Wait();
                    }

                    LogManager.Log("Extracting PPC version package...");

                    OnProgress("Extracting PPC package...");

                    using (ZipFile zip = new ZipFile(tempZipFile))
                    {
                        int currentEntry = 0;

                        zip.ExtractProgress += (x, args) =>
                        {
                            if (args.EventType == ZipProgressEventType.Extracting_AfterExtractEntry)
                            {
                                OnProgress("Extracting PPC package...", false, currentEntry++, zip.Entries.Count);
                            }
                        };

                        zip.ExtractAll(tempPackageFolder);
                    }

                    OnProgress("Extracting version information...");
                    LogManager.Log("Extracting publish information...");
                    PublishInfo publishInfo = PublishInfo.FromJson(File.ReadAllText(Path.Combine(tempPackageFolder, "version.json")));
                    LogManager.Log($"Publish Information:\n{publishInfo}");

                    LogManager.Log("Modifying publish information to custom tup file...");
                    publishInfo.IsMachineTupPackage = true;
                    publishInfo.MachineSerialNumber = serialNumber;
                    publishInfo.MachineDeploymentSlot = SettingsManager.Default.GetOrCreate<MachineStudioSettings>().DeploymentSlot;

                    OnProgress("Creating temporary database...");

                    LogManager.Log($"Creating temporary db backup directory '{tempBackupFolder}'");

                    Directory.CreateDirectory(tempBackupFolder);

                    LogManager.Log($"Creating new database: '{tempDbName}'");

                    //Create temp db
                    dbManager.Create(tempDbName, Path.Combine(tempBackupFolder, tempDbName + ".mdf"));

                    OnProgress("Generating database snapshot...");

                    LogManager.Log("Starting database synchronization...");

                    Thread.Sleep(2000);

                    localDataSource.Catalog = tempDbName;

                    ExaminerSequenceConfigurationRunner runner = new ExaminerSequenceConfigurationRunner(
                        Path.Combine(tempPackageFolder, "Provision Scripts", "config.xml"),
                        Path.Combine(tempPackageFolder, "Provision Scripts"),
                            remoteDataSource,
                            localDataSource,
                            serialNumber);

                    runner.ScriptExecuting += (x, item) =>
                    {
                        LogManager.Log($"Executing script '{item.FileName}'...");
                        OnProgress($"{item.Name}...");
                    };

                    runner.Log += (x, log) =>
                    {
                        LogManager.Log(log);
                    };

                    runner.Run().GetAwaiter().GetResult();

                    OnProgress("Generating database snapshot...");

                    if (File.Exists(tempBackupFile))
                    {
                        LogManager.Log($"Deleting file '{tempBackupFile}'");
                        File.Delete(tempBackupFile);
                    }

                    LogManager.Log($"Generating backup for '{tempDbName}' to '{tempBackupFile}'...");

                    dbManager.Backup(tempDbName, tempBackupFile);

                    OnProgress("Injecting database snapshot to PPC package...");

                    using (ZipFile zip = new ZipFile(tempZipFile))
                    {
                        LogManager.Log($"Injecting file '{tempBackupFile}' to original package at '{tempZipFile}'...");
                        zip.AddFile(tempBackupFile, "/");

                        LogManager.Log($"Injecting modified publish information...");
                        zip.UpdateEntry("version.json", publishInfo.ToJson());

                        zip.Save();
                    }

                    LogManager.Log($"Copying '{tempZipFile}' to '{filePath}'...");

                    File.Copy(tempZipFile, filePath, true);

                    OnProgress("Completed", false, 100, 100);

                    LogManager.Log("TUP file generation completed successfully.");
                }
                catch (Exception ex)
                {
                    LogManager.Log(ex, "TUP file generation failed.");
                    OnProgress("Failed", false, 0, 100);
                    throw ex;
                }
                finally
                {
                    LogManager.Log($"Removing '{tempZipFile}'.");
                    tempZipFile.Delete();
                    LogManager.Log($"Removing '{tempPackageFolder}'.");
                    tempPackageFolder.Delete();

                    try
                    {
                        LogManager.Log($"Removing database '{tempDbName}'.");
                        dbManager.SetOffline(tempDbName);
                        dbManager.SetOnline(tempDbName);
                        dbManager.Delete(tempDbName);
                        dbManager.Dispose();
                    }
                    catch (Exception ex)
                    {
                        LogManager.Log(ex, $"Error removing temp database '{tempDbName}'.");
                    }

                    try
                    {
                        LogManager.Log($"Removing '{tempBackupFolder}'.");
                        Directory.Delete(tempBackupFolder, true);
                    }
                    catch (Exception ex)
                    {
                        LogManager.Log(ex, $"Error removing folder '{tempBackupFolder}'.");
                    }
                }
            });
        }

        public async Task<String> GetLatestPPCVersion(String serialNumber)
        {
            MachineStudioWebClient client = TangoIOC.Default.GetInstance<MachineStudioWebClient>();
            var response = await client.DownloadLatestPPCVersion(new DownloadLatestPPCVersionRequest() { SerialNumber = serialNumber });
            return response.Version;
        }

        private void OnProgress(String message, bool isIntermediate = true, double progress = 0, double total = 100)
        {
            Progress?.Invoke(this, new TupFileBuilderProgressEventArgs()
            {
                Message = message,
                IsIntermediate = isIntermediate,
                Progress = progress,
                Total = total,
            });
        }
    }
}