//****************************************************************************************************** // Program.cs - Gbtc // // Copyright © 2020, Grid Protection Alliance. All Rights Reserved. // // Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See // the NOTICE file distributed with this work for additional information regarding copyright ownership. // The GPA licenses this file to you under the MIT License (MIT), the "License"; you may not use this // file except in compliance with the License. You may obtain a copy of the License at: // // http://opensource.org/licenses/MIT // // Unless agreed to in writing, the subject software distributed under the License is distributed on an // "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the // License for the specific language governing permissions and limitations. // // Code Modification History: // ---------------------------------------------------------------------------------------------------- // 11/06/2020 - J. Ritchie Carroll // Generated original version of source code. // //****************************************************************************************************** using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Security.Principal; using System.Windows.Forms; using System.Xml.Linq; using GSF; using GSF.Configuration; using GSF.Console; using GSF.Data; using GSF.Diagnostics; using GSF.IO; using Microsoft.VisualBasic.ApplicationServices; namespace AdapterExplorer { public enum ExitCode { Success, DatabaseConnectFailure, SecurityValidationFailure } public enum Status { Disconnected, Connected } static class Program { // Static Properties public static LogPublisher Log; private static string s_hostConfigFileName; private static string s_connectionString; private static string s_dataProviderString; private static Guid s_nodeID; public static string HostConfigFileName => Path.GetFileName(s_hostConfigFileName ?? "undefined"); public static Guid HostNodeID => s_nodeID; private class AdapterExplorerApplication : WindowsFormsApplicationBase { protected override void OnCreateMainForm() { MainForm mainForm = new MainForm(); mainForm.ExceptionHandler = ex => { mainForm.BeginInvoke(new Action(() => { MessageBox.Show(SplashScreen, $"Failed to validate security for \"{mainForm.SecurityPrincipal?.Identity?.Provider?.UserData?.LoginID ?? "undefined user"}\" in database configured in \"{Program.HostConfigFileName}\": {ex.Message}", "Security Validation Error", MessageBoxButtons.OK); Environment.ExitCode = (int)ExitCode.SecurityValidationFailure; Application.Exit(); })); }; MainForm = mainForm; } protected override void OnCreateSplashScreen() { SplashScreen = new SplashScreen(); } } /// /// The main entry point for the application. /// [STAThread] private static int Main() { string localPath = FilePath.GetAbsolutePath(""); string logPath = string.Format("{0}{1}Logs{1}", localPath, Path.DirectorySeparatorChar); try { if (!Directory.Exists(logPath)) Directory.CreateDirectory(logPath); } catch { logPath = localPath; } Logger.FileWriter.SetPath(logPath); Logger.FileWriter.SetLoggingFileCount(10); Logger.SuppressFirstChanceExceptionLogMessages(); Log = Logger.CreatePublisher(typeof(Program), MessageClass.Application); Log.Publish(MessageLevel.Info, "ApplicationStart"); AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); try { using (AdoDataConnection database = Program.GetDatabaseConnection()) { if (database is null) throw new InvalidOperationException("No configured database connection string and data provider string found."); } } catch (Exception ex) { Log.Publish(MessageLevel.Error, "Database Connection", exception: ex); MessageBox.Show($"Failed to connect to database defined in \"{Program.HostConfigFileName}\":{Environment.NewLine}{ex.Message}", "Database Connection Error", MessageBoxButtons.OK); return (int)ExitCode.DatabaseConnectFailure; } AdapterExplorerApplication app = new AdapterExplorerApplication(); app.Run(Environment.GetCommandLineArgs()); return (int)ExitCode.Success; } public static ushort GetGEPPort() { XDocument serviceConfig = XDocument.Load(GetConfigurationFileName()); string configurationString = serviceConfig .Descendants("internaldatapublisher") .SelectMany(systemSettings => systemSettings.Elements("add")) .Where(element => "ConfigurationString".Equals((string)element.Attribute("name"), StringComparison.OrdinalIgnoreCase)) .Select(element => (string)element.Attribute("value")) .FirstOrDefault(); Dictionary settings = configurationString.ParseKeyValuePairs(); if (settings.TryGetValue("port", out string setting) && ushort.TryParse(setting, out ushort port)) return port; return 6165; } public static AdoDataConnection GetDatabaseConnection() { string connectionString = s_connectionString; string dataProviderString = s_dataProviderString; string nodeID = null; if (string.IsNullOrWhiteSpace(connectionString) || string.IsNullOrWhiteSpace(dataProviderString)) { XDocument serviceConfig = XDocument.Load(GetConfigurationFileName()); connectionString = serviceConfig .Descendants("systemSettings") .SelectMany(systemSettings => systemSettings.Elements("add")) .Where(element => "ConnectionString".Equals((string)element.Attribute("name"), StringComparison.OrdinalIgnoreCase)) .Select(element => (string)element.Attribute("value")) .FirstOrDefault(); dataProviderString = serviceConfig .Descendants("systemSettings") .SelectMany(systemSettings => systemSettings.Elements("add")) .Where(element => "DataProviderString".Equals((string)element.Attribute("name"), StringComparison.OrdinalIgnoreCase)) .Select(element => (string)element.Attribute("value")) .FirstOrDefault(); nodeID = serviceConfig .Descendants("systemSettings") .SelectMany(systemSettings => systemSettings.Elements("add")) .Where(element => "NodeID".Equals((string)element.Attribute("name"), StringComparison.OrdinalIgnoreCase)) .Select(element => (string)element.Attribute("value")) .FirstOrDefault(); } if (string.IsNullOrWhiteSpace(connectionString) || string.IsNullOrWhiteSpace(dataProviderString)) return null; // Copy target database settings into local user settings ConfigurationFile configFile = ConfigurationFile.Current; CategorizedSettingsElementCollection configSettings = configFile.Settings["systemSettings"]; if (nodeID is null) nodeID = Guid.NewGuid().ToString(); configSettings["ConnectionString"].Value = connectionString; configSettings["DataProviderString"].Value = dataProviderString; configSettings["NodeID"].Value = nodeID; s_connectionString = connectionString; s_dataProviderString = dataProviderString; s_nodeID = Guid.Parse(nodeID); return new AdoDataConnection(connectionString, dataProviderString); } private static string GetConfigurationFileName() { if (!string.IsNullOrWhiteSpace(s_hostConfigFileName) && File.Exists(s_hostConfigFileName)) return s_hostConfigFileName; string getConfigurationFileName() { Arguments arguments = new Arguments(Environment.CommandLine, true); if (arguments.Count > 0 && File.Exists(arguments["OrderedArg1"])) return arguments["OrderedArg1"]; // Will be faster to load known config file, try a few common ones first string[] knownConfigurationFileNames = { "openPDC.exe.config", "SIEGate.exe.config", "openHistorian.exe.config", "substationSBG.exe.config", "openMIC.exe.config", "PDQTracker.exe.config", "openECA.exe.config" }; // Search for the file name in the list of known configuration files foreach (string fileName in knownConfigurationFileNames) { string absolutePath = FilePath.GetAbsolutePath(fileName); if (File.Exists(absolutePath)) return absolutePath; } // Fall back on manual search foreach (string configFile in FilePath.GetFileList($"{FilePath.AddPathSuffix(FilePath.GetAbsolutePath(""))}*.exe.config")) { try { XDocument serviceConfig = XDocument.Load(configFile); string applicationName = serviceConfig .Descendants("securityProvider") .SelectMany(systemSettings => systemSettings.Elements("add")) .Where(element => "ApplicationName".Equals((string)element.Attribute("name"), StringComparison.OrdinalIgnoreCase)) .Select(element => (string)element.Attribute("value")) .FirstOrDefault(); if (string.IsNullOrWhiteSpace(applicationName)) continue; if (applicationName.Trim().Equals(FilePath.GetFileNameWithoutExtension(FilePath.GetFileNameWithoutExtension(configFile)), StringComparison.OrdinalIgnoreCase)) return configFile; } catch (Exception ex) { // Just move on to the next config file if XML parsing fails Program.Log.Publish(MessageLevel.Warning, "GetConfigurationFileName", $"Failed parse config file \"{configFile}\".", exception: ex); } } return ConfigurationFile.Current.Configuration.FilePath; } return s_hostConfigFileName = getConfigurationFileName(); } } }