コード例 #1
0
        void Initialize()
        {
            ffxiv_                = new FFXIVProcess(this);
            fight_tracker_        = new FightTracker(this);
            wipe_detector_        = new WipeDetector(this);
            dispatch_json_writer_ = new JsonTextWriter(new System.IO.StringWriter(dispatch_string_builder_));
            dispatch_serializer_  = JsonSerializer.CreateDefault();
            message_serializer_   = JsonSerializer.CreateDefault();


            // Our own timer with a higher frequency than OverlayPlugin since we want to see
            // the effect of log messages quickly.
            fast_update_timer_          = new System.Timers.Timer();
            fast_update_timer_.Elapsed += (o, args) => {
                // Hold this while we're in here to prevent the Renderer or Browser from disappearing from under us.
                fast_update_timer_semaphore_.Wait();
                int timer_interval = kSlowTimerMilli;
                try {
                    timer_interval = SendFastRateEvents();
                } catch (Exception e) {
                    // SendFastRateEvents holds this semaphore until it exits.
                    LogError("Exception in SendFastRateEvents: " + e.Message);
                    LogError("Stack: " + e.StackTrace);
                    LogError("Source: " + e.Source);
                }
                fast_update_timer_semaphore_.Release();
                fast_update_timer_.Interval = timer_interval;
                fast_update_timer_.Start();
            };
            fast_update_timer_.AutoReset = false;

            // Incoming events.
            Advanced_Combat_Tracker.ActGlobals.oFormActMain.OnLogLineRead += OnLogLineRead;

            // Outgoing JS events.
            OnGameExists        += (e) => DispatchToJS(e);
            OnGameActiveChanged += (e) => DispatchToJS(e);
            OnZoneChanged       += (e) => DispatchToJS(e);
            if (this.Config.LogUpdatesEnabled)
            {
                OnLogsChanged += (e) => DispatchToJS(e);
            }
            OnPlayerChanged   += (e) => DispatchToJS(e);
            OnTargetChanged   += (e) => DispatchToJS(e);
            OnTargetCasting   += (e) => DispatchToJS(e);
            OnFocusChanged    += (e) => DispatchToJS(e);
            OnFocusCasting    += (e) => DispatchToJS(e);
            OnInCombatChanged += (e) => DispatchToJS(e);
            OnPlayerDied      += (e) => DispatchToJS(e);
            OnPartyWipe       += (e) => DispatchToJS(e);
            OnDataFilesRead   += (e) => DispatchToJS(e);

            fast_update_timer_.Interval = kFastTimerMilli;
            fast_update_timer_.Start();

            if (is_first_overlay_initialized_)
            {
                is_first_overlay_initialized_ = false;

                var     versions = new VersionChecker(this);
                Version local    = versions.GetLocalVersion();
                Version remote   = versions.GetRemoteVersion();

                Version overlay = versions.GetOverlayPluginVersion();
                Version ffxiv   = versions.GetFFXIVPluginVersion();
                Version act     = versions.GetACTVersion();

                // Print out version strings and locations to help users debug.
                LogInfo("cactbot: {0} {1}", local.ToString(), versions.GetCactbotLocation());
                LogInfo("OverlayPlugin: {0} {1}", overlay.ToString(), versions.GetOverlayPluginLocation());
                LogInfo("FFXIV Plugin: {0} {1}", ffxiv.ToString(), versions.GetFFXIVPluginLocation());
                LogInfo("ACT: {0} {1}", act.ToString(), versions.GetACTLocation());

                if (remote.Major == 0 && remote.Minor == 0)
                {
                    var result = System.Windows.Forms.MessageBox.Show(Overlay,
                                                                      "Github error while checking Cactbot version. " +
                                                                      "Your current version is " + local + ".\n\n" +
                                                                      "Manually check for newer version now?",
                                                                      "Cactbot Manual Check",
                                                                      System.Windows.Forms.MessageBoxButtons.YesNo);
                    if (result == System.Windows.Forms.DialogResult.Yes)
                    {
                        System.Diagnostics.Process.Start(VersionChecker.kReleaseUrl);
                    }
                }
                else if (local < remote)
                {
                    Version remote_seen_before = new Version(Config.RemoteVersionSeen);
                    Config.RemoteVersionSeen = remote.ToString();

                    string update_message = "There is a new version of Cactbot is available at: \n" +
                                            VersionChecker.kReleaseUrl + " \n\n" +
                                            "New version " + remote + " \n" +
                                            "Current version " + local;
                    if (remote == remote_seen_before)
                    {
                        LogError(update_message);
                    }
                    else
                    {
                        var result = System.Windows.Forms.MessageBox.Show(Overlay,
                                                                          update_message + "\n\n" +
                                                                          "Get it now?",
                                                                          "Cactbot update available",
                                                                          System.Windows.Forms.MessageBoxButtons.YesNo);
                        if (result == System.Windows.Forms.DialogResult.Yes)
                        {
                            System.Diagnostics.Process.Start(VersionChecker.kReleaseUrl);
                        }
                    }
                    Config.RemoteVersionSeen = remote.ToString();
                }
            }

            string net_version_str = System.Diagnostics.FileVersionInfo.GetVersionInfo(typeof(int).Assembly.Location).ProductVersion;

            string[] net_version = net_version_str.Split('.');
            if (int.Parse(net_version[0]) < kRequiredNETVersionMajor || int.Parse(net_version[1]) < kRequiredNETVersionMinor)
            {
                LogError("Requires .NET 4.6 or above. Using " + net_version_str);
            }

            init_ = true;
            if (deferred_navigate_ != null)
            {
                this.Navigate(deferred_navigate_);
            }
        }
コード例 #2
0
        public override void Start()
        {
            // Our own timer with a higher frequency than OverlayPlugin since we want to see
            // the effect of log messages quickly.
            fast_update_timer_          = new System.Timers.Timer();
            fast_update_timer_.Elapsed += (o, args) => {
                int timer_interval = kSlowTimerMilli;
                try {
                    timer_interval = SendFastRateEvents();
                } catch (Exception e) {
                    // SendFastRateEvents holds this semaphore until it exits.
                    LogError("Exception in SendFastRateEvents: " + e.Message);
                    LogError("Stack: " + e.StackTrace);
                    LogError("Source: " + e.Source);
                }
                fast_update_timer_.Interval = timer_interval;
            };
            fast_update_timer_.AutoReset = false;

            FFXIVPlugin plugin_helper = new FFXIVPlugin(this);

            language_  = plugin_helper.GetLocaleString();
            pc_locale_ = System.Globalization.CultureInfo.CurrentUICulture.Name;

            var     versions = new VersionChecker(this);
            Version local    = versions.GetCactbotVersion();

            Version overlay = versions.GetOverlayPluginVersion();
            Version ffxiv   = versions.GetFFXIVPluginVersion();
            Version act     = versions.GetACTVersion();

            // Print out version strings and locations to help users debug.
            LogInfo("cactbot: {0} {1} (dir: {2})", local.ToString(), versions.GetCactbotPluginLocation(), versions.GetCactbotDirectory());
            LogInfo("OverlayPlugin: {0} {1}", overlay.ToString(), versions.GetOverlayPluginLocation());
            LogInfo("FFXIV Plugin: {0} {1}", ffxiv.ToString(), versions.GetFFXIVPluginLocation());
            LogInfo("ACT: {0} {1}", act.ToString(), versions.GetACTLocation());
            if (language_ == null)
            {
                LogInfo("Parsing Plugin Language: {0}", "(unknown)");
            }
            else
            {
                LogInfo("Parsing Plugin Language: {0}", language_);
            }
            if (pc_locale_ == null)
            {
                LogInfo("System Locale: {0}", "(unknown)");
            }
            else
            {
                LogInfo("System Locale: {0}", pc_locale_);
            }

            // This will be set explicitly, so if it's not set now, it will be set after reloading ACT.
            // Log this for now as there will likely be a lot of questions, re: user directories.
            if (Config.UserConfigFile != null)
            {
                LogInfo("cactbot user directory: {0}", Config.UserConfigFile);
            }

            // Temporarily target cn if plugin is old v2.0.4.0
            if (language_ == "cn" || ffxiv.ToString() == "2.0.4.0")
            {
                ffxiv_ = new FFXIVProcessCn(this);
                LogInfo("Version: cn");
            }
            else if (language_ == "ko")
            {
                ffxiv_ = new FFXIVProcessKo(this);
                LogInfo("Version: ko");
            }
            else
            {
                ffxiv_ = new FFXIVProcessIntl(this);
                LogInfo("Version: intl");
            }
            wipe_detector_ = new WipeDetector(this);
            fate_watcher_  = new FateWatcher(this, language_);

            // Incoming events.
            Advanced_Combat_Tracker.ActGlobals.oFormActMain.OnLogLineRead += OnLogLineRead;

            // Outgoing JS events.
            OnForceReload       += (e) => DispatchToJS(e);
            OnGameExists        += (e) => DispatchToJS(e);
            OnGameActiveChanged += (e) => DispatchToJS(e);
            OnZoneChanged       += (e) => DispatchToJS(e);
            OnLogsChanged       += (e) => DispatchToJS(e);
            OnImportLogsChanged += (e) => DispatchToJS(e);
            OnPlayerChanged     += (e) => DispatchToJS(e);
            OnInCombatChanged   += (e) => DispatchToJS(e);
            OnPlayerDied        += (e) => DispatchToJS(e);
            OnPartyWipe         += (e) => DispatchToJS(e);
            OnFateEvent         += (e) => DispatchToJS(e);
            OnCEEvent           += (e) => DispatchToJS(e);

            fast_update_timer_.Interval = kFastTimerMilli;
            fast_update_timer_.Start();
            fate_watcher_.Start();

            string net_version_str = System.Diagnostics.FileVersionInfo.GetVersionInfo(typeof(int).Assembly.Location).ProductVersion;

            string[] net_version = net_version_str.Split('.');
            if (int.Parse(net_version[0]) < kRequiredNETVersionMajor || int.Parse(net_version[1]) < kRequiredNETVersionMinor)
            {
                LogError("Requires .NET 4.6 or above. Using " + net_version_str);
            }

            versions.DoUpdateCheck(Config);

            // Start watching files after the update check.
            Config.WatchFileChangesChanged += (o, e) => {
                if (Config.WatchFileChanges)
                {
                    StartFileWatcher();
                }
                else
                {
                    StopFileWatcher();
                }
            };

            if (Config.WatchFileChanges)
            {
                StartFileWatcher();
            }
        }
コード例 #3
0
        public override void Start()
        {
            // Our own timer with a higher frequency than OverlayPlugin since we want to see
            // the effect of log messages quickly.
            fast_update_timer_          = new System.Timers.Timer();
            fast_update_timer_.Elapsed += (o, args) => {
                int timer_interval = kSlowTimerMilli;
                try {
                    timer_interval = SendFastRateEvents();
                } catch (Exception e) {
                    // SendFastRateEvents holds this semaphore until it exits.
                    LogError("Exception in SendFastRateEvents: " + e.Message);
                    LogError("Stack: " + e.StackTrace);
                    LogError("Source: " + e.Source);
                }
                fast_update_timer_.Interval = timer_interval;
            };
            fast_update_timer_.AutoReset = false;

            FFXIVPlugin plugin_helper = new FFXIVPlugin(this);

            language_ = plugin_helper.GetLocaleString();

            var     versions = new VersionChecker(this);
            Version local    = versions.GetLocalVersion();
            Version remote   = versions.GetRemoteVersion();

            Version overlay = versions.GetOverlayPluginVersion();
            Version ffxiv   = versions.GetFFXIVPluginVersion();
            Version act     = versions.GetACTVersion();

            // Print out version strings and locations to help users debug.
            LogInfo("cactbot: {0} {1} (dir: {2})", local.ToString(), versions.GetCactbotPluginLocation(), versions.GetCactbotDirectory());
            LogInfo("OverlayPlugin: {0} {1}", overlay.ToString(), versions.GetOverlayPluginLocation());
            LogInfo("FFXIV Plugin: {0} {1}", ffxiv.ToString(), versions.GetFFXIVPluginLocation());
            LogInfo("ACT: {0} {1}", act.ToString(), versions.GetACTLocation());
            if (language_ == null)
            {
                LogInfo("Language: {0}", "(unknown)");
            }
            else
            {
                LogInfo("Language: {0}", language_);
            }

            // Temporarily target cn if plugin is old v2.0.4.0
            if (language_ == "cn" || ffxiv.ToString() == "2.0.4.0")
            {
                ffxiv_ = new FFXIVProcessCn(this);
                LogInfo("Version: cn");
            }
            else if (language_ == "ko")
            {
                ffxiv_ = new FFXIVProcessKo(this);
                LogInfo("Version: ko");
            }
            else
            {
                ffxiv_ = new FFXIVProcessIntl(this);
                LogInfo("Version: intl");
            }
            wipe_detector_ = new WipeDetector(this);

            // Incoming events.
            Advanced_Combat_Tracker.ActGlobals.oFormActMain.OnLogLineRead += OnLogLineRead;

            // Outgoing JS events.
            OnForceReload       += (e) => DispatchToJS(e);
            OnGameExists        += (e) => DispatchToJS(e);
            OnGameActiveChanged += (e) => DispatchToJS(e);
            OnZoneChanged       += (e) => DispatchToJS(e);
            OnLogsChanged       += (e) => DispatchToJS(e);
            OnImportLogsChanged += (e) => DispatchToJS(e);
            OnPlayerChanged     += (e) => DispatchToJS(e);
            OnTargetChanged     += (e) => DispatchToJS(e);
            OnFocusChanged      += (e) => DispatchToJS(e);
            OnInCombatChanged   += (e) => DispatchToJS(e);
            OnPlayerDied        += (e) => DispatchToJS(e);
            OnPartyWipe         += (e) => DispatchToJS(e);

            fast_update_timer_.Interval = kFastTimerMilli;
            fast_update_timer_.Start();

            if (remote.Major == 0 && remote.Minor == 0)
            {
                var result = System.Windows.Forms.MessageBox.Show(
                    "Github error while checking Cactbot version. " +
                    "Your current version is " + local + ".\n\n" +
                    "Manually check for newer version now?",
                    "Cactbot Manual Check",
                    System.Windows.Forms.MessageBoxButtons.YesNo);
                if (result == System.Windows.Forms.DialogResult.Yes)
                {
                    System.Diagnostics.Process.Start(VersionChecker.kReleaseUrl);
                }
            }
            else if (local < remote)
            {
                Version remote_seen_before = new Version(Config.RemoteVersionSeen);
                Config.RemoteVersionSeen = remote.ToString();

                string update_message = "There is a new version of Cactbot is available at: \n" +
                                        VersionChecker.kReleaseUrl + " \n\n" +
                                        "New version " + remote + " \n" +
                                        "Current version " + local;
                if (remote == remote_seen_before)
                {
                    LogError(update_message);
                }
                else
                {
                    var result = System.Windows.Forms.MessageBox.Show(
                        update_message + "\n\n" +
                        "Get it now?",
                        "Cactbot update available",
                        System.Windows.Forms.MessageBoxButtons.YesNo);
                    if (result == System.Windows.Forms.DialogResult.Yes)
                    {
                        System.Diagnostics.Process.Start(VersionChecker.kReleaseUrl);
                    }
                }
                Config.RemoteVersionSeen = remote.ToString();
            }

            string net_version_str = System.Diagnostics.FileVersionInfo.GetVersionInfo(typeof(int).Assembly.Location).ProductVersion;

            string[] net_version = net_version_str.Split('.');
            if (int.Parse(net_version[0]) < kRequiredNETVersionMajor || int.Parse(net_version[1]) < kRequiredNETVersionMinor)
            {
                LogError("Requires .NET 4.6 or above. Using " + net_version_str);
            }
        }
コード例 #4
0
        public override void Start()
        {
            // Our own timer with a higher frequency than OverlayPlugin since we want to see
            // the effect of log messages quickly.
            fast_update_timer_          = new System.Timers.Timer();
            fast_update_timer_.Elapsed += (o, args) => {
                int timer_interval = kSlowTimerMilli;
                try {
                    timer_interval = SendFastRateEvents();
                } catch (Exception e) {
                    // SendFastRateEvents holds this semaphore until it exits.
                    LogError(Strings.SendFastRateEventsException, e.Message);
                    LogError(Strings.Stack, e.StackTrace);
                    LogError(Strings.Source, e.Source);
                }
                fast_update_timer_.Interval = timer_interval;
            };
            fast_update_timer_.AutoReset = false;

            FFXIVPlugin plugin_helper = new FFXIVPlugin(this);

            language_  = plugin_helper.GetLocaleString();
            pc_locale_ = System.Globalization.CultureInfo.CurrentUICulture.Name;

            var ui_lang = Config.DisplayLanguage;

            if (ui_lang == "default")
            {
                ui_lang = language_;
            }
            if (ui_lang == "cn")
            {
                ui_lang = "zh";
            }
            try {
                CultureInfo culture = new CultureInfo(ui_lang, false);
                CultureInfo.CurrentUICulture = culture;
            } catch {
                // CultureInfo's constructor throws on nulls.
                // TODO: remove this try/catch and verify a null check is sufficient?
            }

            var     versions = new VersionChecker(this);
            Version local    = versions.GetCactbotVersion();

            Version overlay = versions.GetOverlayPluginVersion();
            Version ffxiv   = versions.GetFFXIVPluginVersion();
            Version act     = versions.GetACTVersion();

            // Print out version strings and locations to help users debug.
            LogInfo(Strings.CactbotBaseInfo, local.ToString(), versions.GetCactbotPluginLocation(), versions.GetCactbotDirectory());
            LogInfo(Strings.OverlayPluginBaseInfo, overlay.ToString(), versions.GetOverlayPluginLocation());
            LogInfo(Strings.FFXIVPluginBaseInfo, ffxiv.ToString(), versions.GetFFXIVPluginLocation());
            LogInfo(Strings.ACTBaseInfo, act.ToString(), versions.GetACTLocation());
            if (language_ == null)
            {
                LogInfo(Strings.ParsingPluginLanguage, "(unknown)");
            }
            else
            {
                LogInfo(Strings.ParsingPluginLanguage, language_);
            }
            if (pc_locale_ == null)
            {
                LogInfo(Strings.SystemLocale, "(unknown)");
            }
            else
            {
                LogInfo(Strings.SystemLocale, pc_locale_);
            }

            // This will be set explicitly, so if it's not set now, it will be set after reloading ACT.
            // Log this for now as there will likely be a lot of questions, re: user directories.
            if (Config.UserConfigFile != null)
            {
                LogInfo(Strings.CactbotUserDirectory, Config.UserConfigFile);
            }

            // Temporarily target cn if plugin is old v2.0.4.0
            if (language_ == "cn" || ffxiv.ToString() == "2.0.4.0")
            {
                ffxiv_ = new FFXIVProcessCn(this);
                LogInfo(Strings.Version, "cn");
            }
            else if (language_ == "ko")
            {
                ffxiv_ = new FFXIVProcessKo(this);
                LogInfo(Strings.Version, "ko");
            }
            else
            {
                ffxiv_ = new FFXIVProcessIntl(this);
                LogInfo(Strings.Version, "intl");
            }

            // Avoid initialization races by always calling OnProcessChanged with the current process
            // in case the ffxiv plugin has already sent this event and it never changes again.
            plugin_helper.RegisterProcessChangedHandler(ffxiv_.OnProcessChanged);
            ffxiv_.OnProcessChanged(plugin_helper.GetCurrentProcess());

            wipe_detector_ = new WipeDetector(this);
            fate_watcher_  = new FateWatcher(this, language_);

            // Incoming events.
            Advanced_Combat_Tracker.ActGlobals.oFormActMain.OnLogLineRead += OnLogLineRead;

            // Outgoing JS events.
            OnForceReload       += (e) => DispatchToJS(e);
            OnGameExists        += (e) => DispatchToJS(e);
            OnGameActiveChanged += (e) => DispatchToJS(e);
            OnZoneChanged       += (e) => DispatchToJS(e);
            OnLogsChanged       += (e) => DispatchToJS(e);
            OnImportLogsChanged += (e) => DispatchToJS(e);
            OnPlayerChanged     += (e) => DispatchToJS(e);
            OnInCombatChanged   += (e) => DispatchToJS(e);
            OnPlayerDied        += (e) => DispatchToJS(e);
            OnPartyWipe         += (e) => DispatchToJS(e);
            OnFateEvent         += (e) => DispatchToJS(e);
            OnCEEvent           += (e) => DispatchToJS(e);

            fast_update_timer_.Interval = kFastTimerMilli;
            fast_update_timer_.Start();
            fate_watcher_.Start();

            string net_version_str = System.Diagnostics.FileVersionInfo.GetVersionInfo(typeof(int).Assembly.Location).ProductVersion;

            string[] net_version = net_version_str.Split('.');
            if (int.Parse(net_version[0]) < kRequiredNETVersionMajor || int.Parse(net_version[1]) < kRequiredNETVersionMinor)
            {
                LogError(Strings.RequireDotNetVersion, net_version_str);
            }

            versions.DoUpdateCheck(Config);
        }
コード例 #5
0
ファイル: CactbotOverlay.cs プロジェクト: Vuzrak/cactbot
    public CactbotOverlay(CactbotOverlayConfig config)
        : base(config, config.Name) {
      main_thread_sync_ = System.Windows.Forms.WindowsFormsSynchronizationContext.Current;
      ffxiv_ = new FFXIVProcess(this);
      fight_tracker_ = new FightTracker(this);
      wipe_detector_ = new WipeDetector(this);
      dispatch_json_writer_ = new JsonTextWriter(new System.IO.StringWriter(dispatch_string_builder_));
      dispatch_serializer_ = JsonSerializer.CreateDefault();
      message_serializer_ = JsonSerializer.CreateDefault();


      // Our own timer with a higher frequency than OverlayPlugin since we want to see
      // the effect of log messages quickly.
      fast_update_timer_ = new System.Timers.Timer();
      fast_update_timer_.Elapsed += (o, args) => {
        try {
          SendFastRateEvents();
        } catch (Exception e) {
          // SendFastRateEvents holds this semaphore until it exits.
          fast_update_timer_semaphore_.Release();
          LogError("Exception in SendFastRateEvents: " + e.Message);
          LogError("Stack: " + e.StackTrace);
          LogError("Source: " + e.Source);
          fast_update_timer_.Interval = kSlowTimerMilli;
          fast_update_timer_.Start();
        }
      };
      fast_update_timer_.AutoReset = false;

      // Incoming events.
      Advanced_Combat_Tracker.ActGlobals.oFormActMain.OnLogLineRead += OnLogLineRead;

      // Outgoing JS events.
      OnGameExists += (e) => DispatchToJS(e);
      OnGameActiveChanged += (e) => DispatchToJS(e);
      OnZoneChanged += (e) => DispatchToJS(e);
      if (config.LogUpdatesEnabled) {
        OnLogsChanged += (e) => DispatchToJS(e);
      }
      OnPlayerChanged += (e) => DispatchToJS(e);
      OnTargetChanged += (e) => DispatchToJS(e);
      OnTargetCasting += (e) => DispatchToJS(e);
      OnFocusChanged += (e) => DispatchToJS(e);
      OnFocusCasting += (e) => DispatchToJS(e);
      OnInCombatChanged += (e) => DispatchToJS(e);
      OnPlayerDied += (e) => DispatchToJS(e);
      OnPartyWipe += (e) => DispatchToJS(e);
      OnDataFilesRead += (e) => DispatchToJS(e);

      fast_update_timer_.Interval = kFastTimerMilli;
      fast_update_timer_.Start();

      if (check_version_) {
        check_version_ = false;
        var versions = new VersionChecker(this);
        Version local = versions.GetLocalVersion();
        Version remote = versions.GetRemoteVersion();
        if (local < remote) {
          Version remote_seen_before = new Version(Config.RemoteVersionSeen);
          Config.RemoteVersionSeen = remote.ToString();

          string update_message = "There is a new version of Cactbot is available at: \n" +
            VersionChecker.kReleaseUrl + " \n\n" +
            "New version " + remote + " \n" +
            "Current version " + local;
          if (remote == remote_seen_before) {
            LogError(update_message);
          } else {
            var result = System.Windows.Forms.MessageBox.Show(Overlay,
              update_message + "\n\n" +
              "Get it now?",
              "Cactbot update available",
              System.Windows.Forms.MessageBoxButtons.YesNo);
            if (result == System.Windows.Forms.DialogResult.Yes)
              System.Diagnostics.Process.Start(VersionChecker.kReleaseUrl);
          }
          Config.RemoteVersionSeen = remote.ToString();
        }
      }

      string net_version_str = System.Diagnostics.FileVersionInfo.GetVersionInfo(typeof(int).Assembly.Location).ProductVersion;
      string[] net_version = net_version_str.Split('.');
      if (int.Parse(net_version[0]) < kRequiredNETVersionMajor || int.Parse(net_version[1]) < kRequiredNETVersionMinor)
        LogError("Requires .NET 4.6 or above. Using " + net_version_str);

      init_ = true;
      if (deferred_navigate_ != null) {
        this.Navigate(deferred_navigate_);
      }
    }