Globals.cs
author Thomas
Wed, 31 May 2017 13:06:53 +0200
changeset 1683 ecffc9945641
parent 1679 c2db58a77e08
child 1690 4ade58875b61
permissions -rw-r--r--
Back out changeset: c2db58a77e08
Thomas@1239
     1
using Microsoft.Win32;
Thomas@1239
     2
using pEp.UI;
Dean@1076
     3
using System;
Dean@1081
     4
using System.Collections.Generic;
Dean@911
     5
using System.IO;
Dean@660
     6
using System.Reflection;
Dean@660
     7
using System.Runtime.InteropServices;
Dean@660
     8
using System.Text;
Dean@660
     9
using System.Threading;
Dean@1074
    10
using System.Windows;
Dean@660
    11
using System.Windows.Forms;
Dean@660
    12
using Office = Microsoft.Office.Core;
Dean@606
    13
Dean@606
    14
namespace pEp
Dean@606
    15
{
Dean@606
    16
    /// <summary>
Dean@660
    17
    /// Class to store all global/shared data and methods.
Dean@860
    18
    /// This class is a shared partial class with the internally generated code.
Dean@606
    19
    /// </summary>
Dean@860
    20
    internal sealed partial class Globals
Dean@606
    21
    {
Thomas@1110
    22
        public const string CUSTOM_SENT_FOLDER_NAME    = "Sent";
Dean@1437
    23
        public const string PEP_INTERNAL_CATEGORY_NAME = "pEp Internal";
Thomas@1573
    24
        public const string PEP_COPYRIGHT              = "Copyright © 2014-2017 p≡p Security SA, Luxembourg";
Dean@1114
    25
        public const string PEP_DATA_FILE_NAME         = "pEp";                           // The file name of the pEp data store. This does NOT include extension (.pst)
Dean@1132
    26
        public const string PEP_DISPLAY_NAME           = "p≡p for Outlook";               // Display name to the user
Dean@1161
    27
        public const string PEP_DISPLAY_NAME_READER    = "p≡p Reader for Outlook";        // Display name to the user
Thomas@1543
    28
        public const string PEP_DRAFTS_FOLDER_NAME     = "pEp Drafts";                    // Folder name for secure drafts
Dean@1023
    29
#if DEBUG
Dean@1023
    30
        public const string PEP_NAME_ADDIN_DESC        = "pEp";                           // Description of the add-in within Outlook itself (shared with reader)
Dean@1023
    31
#else
Dean@1023
    32
        public const string PEP_NAME_ADDIN_DESC        = "pEp for Outlook";               // Description of the add-in within Outlook itself (shared with reader)
Dean@1023
    33
#endif
Dean@1023
    34
        public const string PEP_NAME_INSTALL           = "pEp for Outlook";               // Name for Windows installer, must sync with installation code (shared with reader)
Dean@1278
    35
        public const string PEP_WEBSITE_LINK           = "https://prettyeasyprivacy.com";
Dean@1278
    36
        public const string PEP_WEBSITE_UPGRADE_LINK   = "https://pep.digitalcourage.de/shop/p8801p-for-outlook.html";
Dean@859
    37
Dean@859
    38
#if READER_RELEASE_MODE
Dean@859
    39
        public const ReleaseMode RELEASE_MODE = ReleaseMode.Reader;
Dean@859
    40
#else
Dean@859
    41
        public const ReleaseMode RELEASE_MODE = ReleaseMode.Standard;
Dean@859
    42
#endif
Dean@859
    43
Dean@882
    44
        // Engine translations
Dean@882
    45
        public const int PHRASE_ID_TRUSTWORDS_LANGUAGE = 1000;
Dean@882
    46
Dean@607
    47
        /// <summary>
Dean@859
    48
        /// Enumeration to define the supported release modes.
Dean@859
    49
        /// </summary>
Dean@859
    50
        public enum ReleaseMode
Dean@859
    51
        {
Dean@859
    52
            Standard,
Dean@859
    53
            Reader
Dean@859
    54
        }
Dean@859
    55
Dean@859
    56
        /// <summary>
Dean@910
    57
        /// Enumeration to define the return status of methods.
Dean@910
    58
        /// </summary>
Dean@910
    59
        public enum ReturnStatus
Dean@910
    60
        {
Dean@910
    61
            /// <summary>
Dean@910
    62
            /// An unspecified failure occured.
Dean@910
    63
            /// </summary>
Dean@910
    64
            Failure,
Dean@910
    65
Dean@910
    66
            /// <summary>
Dean@910
    67
            /// A failure occured because there is no internet or Exchange connection.
Dean@910
    68
            /// </summary>
Dean@910
    69
            FailureNoConnection,
Dean@910
    70
Dean@910
    71
            /// <summary>
Dean@910
    72
            /// Successfully completed with no unexpected failures.
Dean@910
    73
            /// </summary>
Thomas@1683
    74
            Success
Dean@910
    75
        }
Dean@910
    76
Thomas@1669
    77
        /// <summary>
Thomas@1669
    78
        /// Enumeration to define the Outlook version pEp runs on.
Thomas@1669
    79
        /// For information on version numbers, see: https://en.wikipedia.org/wiki/Microsoft_Outlook#Versions
Thomas@1669
    80
        /// </summary>            
Thomas@1669
    81
        public enum Version
Thomas@1669
    82
        {
Thomas@1669
    83
            Undefined = 0,
Thomas@1669
    84
            Outlook2010 = 14,
Thomas@1669
    85
            Outlook2013 = 15,
Thomas@1669
    86
            Outlook2016 = 16
Thomas@1669
    87
        }
Thomas@1669
    88
Dean@1074
    89
        private static bool               eventsAreConnected = false;
Dean@1075
    90
        private static ResourceDictionary _ResourceDict      = null;
Dean@1074
    91
Dean@1074
    92
        /**************************************************************
Dean@1074
    93
         * 
Dean@1074
    94
         * Property Accessors
Dean@1074
    95
         * 
Dean@1074
    96
         *************************************************************/
Dean@1074
    97
Dean@1074
    98
        /// <summary>
Dean@1074
    99
        /// Gets the shared XAML resource dictionary.
Dean@1074
   100
        /// </summary>
Dean@1074
   101
        public static ResourceDictionary ResourceDict
Dean@1074
   102
        {
Dean@1074
   103
            get
Dean@1074
   104
            {
Dean@1075
   105
                if (_ResourceDict == null)
Dean@1074
   106
                {
Dean@1074
   107
                    // Load resource dictionary
Dean@1075
   108
                    _ResourceDict = new ResourceDictionary();
Dean@1075
   109
                    _ResourceDict.Source = new Uri("pack://application:,,,/pEp;component/Resources/Dictionary.xaml", UriKind.RelativeOrAbsolute);
Dean@1074
   110
Dean@1075
   111
                    return (_ResourceDict);
Dean@1074
   112
                }
Dean@1074
   113
                else
Dean@1074
   114
                {
Dean@1075
   115
                    return (_ResourceDict);
Dean@1074
   116
                }
Dean@1074
   117
            }
Dean@1074
   118
        }
Dean@660
   119
Dean@660
   120
        /**************************************************************
Dean@660
   121
         * 
Dean@660
   122
         * Methods
Dean@660
   123
         * 
Dean@660
   124
         *************************************************************/
Dean@660
   125
Dean@660
   126
        /// <summary>
Dean@660
   127
        /// Builds a crash report and displays it to the user before sending. 
Dean@660
   128
        /// </summary>
Dean@660
   129
        /// <param name="exception">The exception to build the report with.</param>
Dean@660
   130
        /// <param name="summaryMessage">The message summarizing where the error occured or what it is.</param>
Dean@660
   131
        /// <param name="allowRestart">True to allow the add-in to attempt to restart itself.</param>
Dean@660
   132
        /// <param name="isEngineCrash">True if the engine generated the error. This will not attempt to get
Dean@660
   133
        /// an engine log as the engine itself is not working (avoids infinite loop).</param>
Dean@660
   134
        public static void StopAndSendCrashReport(Exception exception = null,
Dean@660
   135
                                                  string summaryMessage = null,
Dean@660
   136
                                                  bool allowRestart = true,
Dean@660
   137
                                                  bool isEngineCrash = false)
Dean@660
   138
        {
Dean@660
   139
            bool continueSend = true;
Dean@660
   140
            string engineLog = "";
Dean@960
   141
            string log = "";
Dean@660
   142
            FormCrashReport form;
Dean@1076
   143
            FormControlCrashReport.State stateIn = null;
Dean@660
   144
            DialogResult result;
Dean@660
   145
            Office.COMAddIns comAddIns = null;
Dean@660
   146
            Office.COMAddIn addIn = null;
Dean@660
   147
            PEPMessage newMessage;
Dean@660
   148
            PEPAttachment attachment = null;
Dean@660
   149
Dean@660
   150
            // Show the report before sending
Dean@660
   151
            if (continueSend)
Dean@660
   152
            {
Dean@1076
   153
                stateIn = new FormControlCrashReport.State();
Thomas@1634
   154
                stateIn.AddressTo = Globals.ThisAddIn.Settings?.CrashReportSendAddress ?? PEPSettings.CRASH_REPORT_SEND_ADDRESS_DEFAULT;
Dean@660
   155
                stateIn.AddressFrom = null; // A message can be sent without a "from" address
Dean@660
   156
Dean@960
   157
                // Get log
Dean@960
   158
                try
Dean@960
   159
                {
Dean@1249
   160
                    log = string.Join(Environment.NewLine, Log.Read());
Dean@960
   161
                }
Dean@960
   162
                catch
Dean@960
   163
                {
Dean@960
   164
                    log = "";
Dean@960
   165
                }
Dean@960
   166
Dean@660
   167
                // Get engine log
Dean@660
   168
                if (isEngineCrash == false)
Dean@660
   169
                {
Dean@660
   170
                    try
Dean@660
   171
                    {
markus@1337
   172
                        engineLog = ThisAddIn.PEPEngine.GetCrashdumpLog();
Dean@660
   173
                    }
Dean@660
   174
                    catch (COMException ex)
Dean@660
   175
                    {
Dean@660
   176
                        engineLog = ex.ToString();
Dean@660
   177
                    }
Dean@660
   178
                    catch (Exception ex)
Dean@660
   179
                    {
Dean@660
   180
                        engineLog = ex.ToString();
Dean@660
   181
                    }
Dean@660
   182
                }
Dean@660
   183
Dean@960
   184
                // Double check for null log files
Dean@960
   185
                if (log == null) { log = ""; }
Dean@960
   186
                if (engineLog == null) { engineLog = ""; }
Dean@960
   187
Dean@660
   188
                // Build report header
Dean@660
   189
                stateIn.ReportText = string.Join(Environment.NewLine, new string[]
Dean@660
   190
                    {
Dean@660
   191
                        "Summary---------------------------------------------------",
Dean@660
   192
                        "",
Dean@660
   193
                        "Date: " + System.DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss K"),
Dean@860
   194
                        Globals.GetSystemInfo(),
Dean@660
   195
                        "",
Dean@660
   196
                        (string.IsNullOrWhiteSpace(summaryMessage) ? "no message" : summaryMessage),
Dean@660
   197
                        "",
Dean@660
   198
                        "Exception Details-----------------------------------------",
Dean@660
   199
                        "",
Dean@660
   200
                        (exception == null ? "no exception" : exception.ToString()),
Dean@660
   201
                        "",
Dean@660
   202
                        "p≡p for Outlook Log---------------------------------------",
Dean@660
   203
                        "",
Dean@960
   204
                        log,
Dean@660
   205
                        "",
Dean@660
   206
                        "p≡p Engine Log--------------------------------------------",
Dean@660
   207
                        "",
Dean@660
   208
                        engineLog,
Dean@660
   209
                        "",
Dean@660
   210
                        "END OF REPORT"
Dean@660
   211
                    });
Dean@660
   212
Thomas@1634
   213
                if (Globals.ThisAddIn.Settings?.IsCrashReportVisible ?? true)
Dean@660
   214
                {
Dean@660
   215
                    form = new FormCrashReport();
Dean@1082
   216
                    form.StartPosition = FormStartPosition.CenterParent;
Dean@1377
   217
                    form.DisplayState = stateIn;
Dean@1076
   218
                    result = form.ShowDialog();
Dean@660
   219
Dean@660
   220
                    if (result != DialogResult.OK)
Dean@660
   221
                    {
Dean@660
   222
                        continueSend = false;
Dean@660
   223
                    }
Dean@660
   224
                }
Dean@660
   225
            }
Dean@660
   226
Dean@660
   227
            // Build and send message
Dean@660
   228
            if (continueSend)
Dean@660
   229
            {
Dean@660
   230
                newMessage = new PEPMessage();
Dean@660
   231
                newMessage.ShortMsg = "Crash Report";
Dean@660
   232
                newMessage.To.Add(new PEPIdentity(stateIn.AddressTo));
Dean@660
   233
                newMessage.LongMsg = stateIn.ReportText;
markus@1337
   234
                newMessage.Direction = pEpCOMServerAdapterLib.pEpMsgDirection.pEpDirOutgoing;
Dean@660
   235
Dean@960
   236
                // Add logs as attachments
Dean@960
   237
                if (string.IsNullOrEmpty(log) == false)
Dean@660
   238
                {
Dean@960
   239
                    attachment = new PEPAttachment();
Dean@960
   240
                    attachment.Data = Encoding.UTF8.GetBytes(log);
Dean@960
   241
                    attachment.FileName = "pEp Log.txt";
Dean@960
   242
                    newMessage.Attachments.Add(attachment);
Dean@960
   243
                }
Dean@960
   244
Dean@960
   245
                if (string.IsNullOrEmpty(engineLog) == false)
Dean@960
   246
                {
Dean@960
   247
                    attachment = new PEPAttachment();
Dean@960
   248
                    attachment.Data = Encoding.UTF8.GetBytes(engineLog);
Dean@960
   249
                    attachment.FileName = "pEp Engine Log.txt";
Dean@660
   250
                    newMessage.Attachments.Add(attachment);
Dean@660
   251
                }
Dean@660
   252
Dean@1235
   253
                // Try to send the message but ignore any errors
Dean@1235
   254
                try
Dean@1235
   255
                {
Dean@1455
   256
                    Globals.ThisAddIn.SendWithoutProcessing(newMessage, true, false);
Dean@1235
   257
                }
Dean@1235
   258
                catch { }
Dean@660
   259
            }
Dean@660
   260
Dean@1053
   261
            // Stop logging
Dean@1249
   262
            Log.Close();
Dean@1053
   263
Dean@660
   264
            // Locate the Outlook add-in
Dean@660
   265
            comAddIns = Globals.ThisAddIn.Application.COMAddIns;
Dean@660
   266
            foreach (Office.COMAddIn addin in comAddIns)
Dean@660
   267
            {
Dean@1023
   268
                if (string.Equals(addin.Description, Globals.PEP_NAME_ADDIN_DESC, StringComparison.OrdinalIgnoreCase))
Dean@660
   269
                {
Dean@660
   270
                    addIn = addin;
Dean@660
   271
                    break;
Dean@660
   272
                }
Dean@660
   273
            }
Dean@660
   274
Dean@660
   275
            // Shutdown add-in
Dean@660
   276
            if (addIn != null)
Dean@660
   277
            {
Dean@660
   278
                addIn.Connect = false;
Dean@660
   279
            }
Dean@660
   280
Dean@660
   281
            return;
Dean@660
   282
        }
Dean@660
   283
Dean@660
   284
        /// <summary>
Dean@660
   285
        /// Connects or disconnects all global error handling events.
Dean@660
   286
        /// </summary>
Dean@660
   287
        /// <param name="connect">True to connect events, false to disconnect.</param>
Dean@660
   288
        public static void ConnectEvents(bool connect)
Dean@660
   289
        {
Dean@660
   290
            // Connect events only if not already connected
Dean@660
   291
            if ((connect == true) &&
Dean@660
   292
                (eventsAreConnected == false))
Dean@660
   293
            {
Dean@1074
   294
                System.Windows.Forms.Application.ThreadException += Application_UnhandledException;
Dean@660
   295
                AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
Dean@660
   296
Dean@660
   297
                eventsAreConnected = true;
Dean@660
   298
            }
Dean@660
   299
            // Always attempt to disconnect
Dean@660
   300
            else if (connect == false)
Dean@660
   301
            {
Dean@1074
   302
                System.Windows.Forms.Application.ThreadException -= Application_UnhandledException;
Dean@660
   303
                AppDomain.CurrentDomain.UnhandledException -= CurrentDomain_UnhandledException;
Dean@660
   304
Dean@660
   305
                eventsAreConnected = false;
Dean@660
   306
            }
Dean@660
   307
Dean@660
   308
            return;
Dean@660
   309
        }
Dean@660
   310
Dean@660
   311
        /// <summary>
Thomas@1669
   312
        /// Gets the Outlook version pEp runs on.       
Thomas@1669
   313
        /// </summary>
Thomas@1669
   314
        /// <returns>The Outlook version or 'Undefined' if an error occured.</returns>
Thomas@1669
   315
        public static Version GetOutlookVersion()
Thomas@1669
   316
        {
Thomas@1669
   317
            var version = Version.Undefined;
Thomas@1669
   318
            int versionNo = 0;
Thomas@1669
   319
            string versionNumber = string.Empty;
Thomas@1669
   320
Thomas@1669
   321
            try
Thomas@1669
   322
            {
Thomas@1669
   323
                versionNumber = Globals.ThisAddIn.Application.Version.Substring(0, 2);
Thomas@1669
   324
            }
Thomas@1669
   325
            catch (Exception e)
Thomas@1669
   326
            {
Thomas@1669
   327
                versionNumber = string.Empty;
Thomas@1669
   328
                Log.Error("GetOutlookVersion: Error getting version. " + e.Message);
Thomas@1669
   329
            }
Thomas@1669
   330
Thomas@1669
   331
            if (int.TryParse(versionNumber, out versionNo))
Thomas@1669
   332
            {
Thomas@1669
   333
                try
Thomas@1669
   334
                {
Thomas@1669
   335
                    version = (Globals.Version)versionNo;
Thomas@1669
   336
                }
Thomas@1669
   337
                catch (Exception e)
Thomas@1669
   338
                {
Thomas@1669
   339
                    version = Version.Undefined;
Thomas@1669
   340
                    Log.Error("GetOutlookVersion: Error parsing version. " + e.Message);
Thomas@1669
   341
                }
Thomas@1669
   342
            }
Thomas@1669
   343
Thomas@1669
   344
            return version;
Thomas@1669
   345
        }
Thomas@1669
   346
Thomas@1669
   347
        /// <summary>
Dean@1366
   348
        /// Gets the pEp for Outlook version.
Dean@1366
   349
        /// This will never be null.
Dean@1366
   350
        /// </summary>
Dean@1366
   351
        /// <returns>The version string.</returns>
Dean@1366
   352
        public static string GetPEPVersion()
Dean@1366
   353
        {
Dean@1366
   354
            string version;
Dean@1366
   355
            string updateLevel;
Dean@1366
   356
Dean@1366
   357
            // Build the version string
Dean@1366
   358
            updateLevel = Properties.Settings.Default.UpdateLevel;
Dean@1366
   359
            version = string.Empty;
Dean@1366
   360
            version += Assembly.GetExecutingAssembly().GetName().Version.Major.ToString();
Dean@1366
   361
            version += "." + Assembly.GetExecutingAssembly().GetName().Version.Minor.ToString();
Dean@1366
   362
Dean@1366
   363
            if (string.IsNullOrWhiteSpace(updateLevel) == false)
Dean@1366
   364
            {
Dean@1366
   365
                version += " Update " + updateLevel;
Dean@1366
   366
            }
Dean@1366
   367
Dean@1366
   368
            return (version);
Dean@1366
   369
        }
Dean@1366
   370
Dean@1366
   371
        /// <summary>
Dean@660
   372
        /// Gets the current system information string.
Dean@660
   373
        /// </summary>
Dean@660
   374
        /// <returns>The system information as a string.</returns>
Dean@660
   375
        public static string GetSystemInfo()
Dean@660
   376
        {
Dean@1081
   377
            string result = "";
Dean@1081
   378
            List<KVPair<string, string>> systemInfo;
Dean@1081
   379
            List<string> list = new List<string>();
Dean@660
   380
Dean@660
   381
            try
Dean@660
   382
            {
Dean@1081
   383
                systemInfo = Globals.GetSystemInfoList();
Dean@1081
   384
Dean@1081
   385
                for (int i = 0; i < systemInfo.Count; i++)
Dean@660
   386
                {
Dean@1081
   387
                    list.Add(systemInfo[i].Key + " " + systemInfo[i].Value);
Dean@1081
   388
                }
Dean@1081
   389
Dean@1081
   390
                result = string.Join(Environment.NewLine, list);
Dean@660
   391
            }
Dean@660
   392
            catch { }
Dean@660
   393
Dean@1081
   394
            return (result);
Dean@1081
   395
        }
Dean@1081
   396
Dean@1081
   397
        /// <summary>
Dean@1081
   398
        /// Gets the current system information as a list of Key-Value pairs.
Dean@1081
   399
        /// </summary>
Dean@1081
   400
        /// <returns>The system information as a list.</returns>
Dean@1081
   401
        public static List<KVPair<string, string>> GetSystemInfoList()
Dean@1081
   402
        {
Dean@1081
   403
            string serial;
Dean@1366
   404
            string version = Globals.GetPEPVersion();
Dean@1207
   405
            string engineVersion;
Dean@1081
   406
            List<KVPair<string, string>> systemInfo = new List<KVPair<string, string>>();
Dean@1081
   407
            Office.LanguageSettings lang = null;
Dean@1081
   408
Dean@1081
   409
            try
Dean@1081
   410
            {
Dean@1081
   411
                lang = Globals.ThisAddIn.Application.LanguageSettings;
Dean@1081
   412
Dean@1207
   413
                // Get the engine version
Dean@1207
   414
                try
Dean@1207
   415
                {
markus@1337
   416
                    engineVersion = ThisAddIn.PEPEngine.GetEngineVersion();
Dean@1207
   417
                }
Dean@1207
   418
                catch
Dean@1207
   419
                {
Dean@1207
   420
                    engineVersion = null;
Dean@1207
   421
                }
Dean@1207
   422
Dean@1081
   423
                // Use only the first 10-digits which is the serial itself
Dean@1081
   424
                serial = Properties.Settings.Default.Serial;
Dean@1208
   425
                serial = (serial != null ? serial : "");
Dean@1081
   426
                serial = (serial.Length > 10) ? serial.Substring(0, 10) : serial;
Dean@1081
   427
Thomas@1214
   428
                systemInfo.Add(new KVPair<string, string>(Properties.Resources.SystemInfo_Serial, (Globals.RELEASE_MODE == Globals.ReleaseMode.Reader ? Properties.Resources.SystemInfo_Reader : serial)));
Dean@1363
   429
                systemInfo.Add(new KVPair<string, string>(Properties.Resources.SystemInfo_PEPForOutlookVersion, (version != null ? version : "-")));
Dean@1363
   430
                systemInfo.Add(new KVPair<string, string>(Properties.Resources.SystemInfo_PEPEngineVersion, (engineVersion != null ? engineVersion : "-")));
Thomas@1214
   431
                systemInfo.Add(new KVPair<string, string>(Properties.Resources.SystemInfo_OutlookVersion, Globals.ThisAddIn.Application.Version));
Thomas@1214
   432
                systemInfo.Add(new KVPair<string, string>(Properties.Resources.SystemInfo_OSVersion, Environment.OSVersion.VersionString));
Thomas@1214
   433
                systemInfo.Add(new KVPair<string, string>(Properties.Resources.SystemInfo_64BitOS, Environment.Is64BitOperatingSystem.ToString()));
Thomas@1214
   434
                systemInfo.Add(new KVPair<string, string>(Properties.Resources.SystemInfo_64BitProcess, Environment.Is64BitProcess.ToString()));
Thomas@1214
   435
                systemInfo.Add(new KVPair<string, string>(Properties.Resources.SystemInfo_InstallLanguage, ((Office.MsoLanguageID)lang.LanguageID[Office.MsoAppLanguageID.msoLanguageIDInstall]).ToString()));
Thomas@1214
   436
                systemInfo.Add(new KVPair<string, string>(Properties.Resources.SystemInfo_UILanguage, ((Office.MsoLanguageID)lang.LanguageID[Office.MsoAppLanguageID.msoLanguageIDUI]).ToString()));
Dean@1081
   437
            }
Dean@1081
   438
            catch (Exception ex)
Dean@1081
   439
            {
Thomas@1214
   440
                systemInfo.Add(new KVPair<string, string>(Properties.Resources.SystemInfo_Exception, ex.ToString()));
Dean@1081
   441
            }
Dean@1081
   442
            finally
Dean@1081
   443
            {
Dean@1081
   444
                if (lang != null)
Dean@1081
   445
                {
vb@1507
   446
                    // Marshal.ReleaseComObject(lang);
Dean@1081
   447
                    lang = null;
Dean@1081
   448
                }
Dean@1081
   449
            }
Dean@1081
   450
Dean@660
   451
            return (systemInfo);
Dean@660
   452
        }
Dean@660
   453
Dean@660
   454
        /// <summary>
Thomas@1239
   455
        /// Gets the path of the GPA .exe using the install directory from the registry.
Thomas@1239
   456
        /// WARNING: this method can return a null path.
Thomas@1239
   457
        /// </summary>
Thomas@1239
   458
        /// <returns>The path of the GPA .exe, otherwise null.</returns>
Thomas@1239
   459
        public static string GetGPAPath()
Thomas@1239
   460
        {
Thomas@1239
   461
            // We put a general catch block around here, just to be safe - disabling
Thomas@1239
   462
            // the GPA button is the better alternative to crashing if something goes
Thomas@1239
   463
            // wrong here. 
Thomas@1239
   464
            try
Thomas@1239
   465
            {
Thomas@1239
   466
                foreach (var gpgPath in TryToGuessGpgPathes())
Thomas@1239
   467
                {
Thomas@1239
   468
                    var gpaPath = System.IO.Path.Combine(gpgPath, "gpa.exe");
Thomas@1239
   469
                    if (File.Exists(gpaPath))
Thomas@1239
   470
                        return gpaPath;
Thomas@1239
   471
                }
Thomas@1239
   472
            }
Thomas@1239
   473
            catch (Exception ex)
Thomas@1239
   474
            {
Thomas@1239
   475
                // As I do not expext any exceptions to actually appear at this level,
Thomas@1239
   476
                // we log them (even in non-verbose level).
Dean@1249
   477
                Log.Error("GetGpaPath: " + ex.Message);
Thomas@1239
   478
            }
Thomas@1239
   479
Thomas@1239
   480
            return null;
Thomas@1239
   481
        }
Thomas@1239
   482
Thomas@1239
   483
        /// <summary>
Thomas@1239
   484
        /// Helper method which tries to find possible GnuPG installation pathes, with
Thomas@1239
   485
        /// decreasing confidence level.
Thomas@1239
   486
        /// </summary>
Thomas@1239
   487
        /// <returns></returns>
Thomas@1239
   488
        private static IEnumerable<string> TryToGuessGpgPathes()
Thomas@1239
   489
        {
Thomas@1239
   490
            // We just try all possible registry views to find GPA. As we just start it as an externa process,
Thomas@1239
   491
            // we don´t care whether its 32 bit or 64 bit.
Thomas@1239
   492
Thomas@1239
   493
            // We try the 32 bit view first, as that's what we currently deploy.
Thomas@1239
   494
            var gpgPath = TryToReadGpgPathFromRegistry(RegistryView.Registry32);
Thomas@1239
   495
Thomas@1239
   496
            if (!string.IsNullOrEmpty(gpgPath))
Thomas@1239
   497
                yield return gpgPath;
Thomas@1239
   498
Thomas@1239
   499
            gpgPath = TryToReadGpgPathFromRegistry(RegistryView.Registry64);
Thomas@1239
   500
Thomas@1239
   501
            if (!string.IsNullOrEmpty(gpgPath))
Thomas@1239
   502
                yield return gpgPath;
Thomas@1239
   503
Thomas@1239
   504
            // Use backup hardcoded directory locations as fallbacks. However, we log this issue
Thomas@1239
   505
            // as it is not expected (broken installation?)
Dean@1249
   506
            Log.Warning("TryToGuessGpgPathes: Not found in registry, trying backup hard-coded directory pathes.");
Thomas@1239
   507
Dean@1249
   508
            yield return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86),
Thomas@1239
   509
                "GNU", "GnuPG");
Thomas@1239
   510
Dean@1249
   511
            yield return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles),
Thomas@1239
   512
                "GNU", "GnuPG");
Thomas@1239
   513
        }
Thomas@1239
   514
Thomas@1239
   515
        private static string TryToReadGpgPathFromRegistry(RegistryView view)
Thomas@1239
   516
        {
Thomas@1239
   517
            try
Thomas@1239
   518
            {
Thomas@1239
   519
                using (var rootKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, view))
Thomas@1239
   520
                using (RegistryKey rk = rootKey.OpenSubKey("SOFTWARE\\GNU\\GnuPG"))
Thomas@1239
   521
                {
Thomas@1239
   522
                    var gpgPath = (string)rk.GetValue("Install Directory");
Thomas@1239
   523
                    return gpgPath;
Thomas@1239
   524
                }
Thomas@1239
   525
            }
Thomas@1239
   526
            catch (Exception ex)
Thomas@1239
   527
            {
Thomas@1239
   528
                // Exceptions here are expected (the key does not exist in the view we currently 
Thomas@1239
   529
                // tried), thus we only long them in verbose mode.
Dean@1249
   530
                Log.Verbose("TryToReadGpgPathFromRegistry: " + ex.Message);
Thomas@1239
   531
                return null;
Thomas@1239
   532
            }
Thomas@1239
   533
        }
Thomas@1239
   534
Dean@660
   535
        /**************************************************************
Dean@660
   536
         * 
Dean@660
   537
         * Event Handling
Dean@660
   538
         * 
Dean@660
   539
         *************************************************************/
Dean@660
   540
Dean@660
   541
        /// <summary>
Dean@660
   542
        /// Event handler for when an unhandled error occurs within the current application.
Dean@660
   543
        /// </summary>
Dean@660
   544
        private static void Application_UnhandledException(object sender, ThreadExceptionEventArgs e)
Dean@660
   545
        {
Dean@860
   546
            Globals.StopAndSendCrashReport(e.Exception);
Dean@660
   547
            return;
Dean@660
   548
        }
Dean@660
   549
Dean@660
   550
        /// <summary>
Dean@660
   551
        /// Event handler for when an unhandled error occurs within the current domain.
Dean@660
   552
        /// </summary>
Dean@660
   553
        private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
Dean@660
   554
        {
Dean@860
   555
            Globals.StopAndSendCrashReport();
Dean@660
   556
            return;
Dean@660
   557
        }
Dean@660
   558
Dean@606
   559
    }
Dean@606
   560
}