//******************************************************************************************************// MainForm.ManageHostConfig.cs - Gbtc//// Copyright © 2021, 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:// ----------------------------------------------------------------------------------------------------// 12/31/2020 - J. Ritchie Carroll// Generated original version of source code.////****************************************************************************************************** using System;using System.Diagnostics;using System.IO;using System.Linq;using System.Xml.Linq;using GSF;using GSF.Diagnostics;using GSF.IO; namespace SELPDCImporter{ partial class MainForm { private Process m_consoleProcess; // Attempt to auto-load initial host configuration file (useful when running from host service folder) private string LookupHostConfig() { // Search through list of known source applications (faster than manual search) foreach (string hostApp in new[] { "openPDC", "openHistorian", "SIEGate" }) { string absolutePath = FilePath.GetAbsolutePath($"{hostApp}.exe.config"); if (File.Exists(absolutePath)) { HostApp = hostApp; return absolutePath; } } // Fall back on manual search foreach (string configFile in FilePath.GetFileList($"{FilePath.AddPathSuffix(FilePath.GetAbsolutePath(""))}*.exe.config")) { if (IsHostConfig(configFile)) return configFile; } return ""; } private bool IsHostConfig(string configFile) { 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)) return false; if (applicationName.Trim().Equals(FilePath.GetFileNameWithoutExtension(FilePath.GetFileNameWithoutExtension(configFile)), StringComparison.OrdinalIgnoreCase)) { HostApp = applicationName; return true; } } catch (Exception ex) { m_log.Publish(MessageLevel.Warning, "IsHostConfig", $"Failed parse config file \"{configFile}\".", exception: ex); } return false; } private void LoadHostConfigFile(string configFile, ImportParameters importParams) { XDocument serviceConfig = XDocument.Load(configFile); string 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(); string 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(); Guid nodeID = Guid.Parse(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() ?? Guid.Empty.ToString()); importParams.InitializeConnection(connectionString, dataProviderString, nodeID); StartConsoleProcess(configFile); } private void StartConsoleProcess(string configFile) { // Stop any existing running process StopConsoleProcess(); m_consoleProcess = new Process { StartInfo = new ProcessStartInfo { UseShellExecute = false, RedirectStandardInput = true, RedirectStandardOutput = true, RedirectStandardError = true, WindowStyle = ProcessWindowStyle.Hidden, CreateNoWindow = true, FileName = $"{FilePath.AddPathSuffix(Path.GetDirectoryName(configFile))}{HostApp}Console.exe" }, EnableRaisingEvents = true }; // Example to send command to console: // m_consoleProcess.StandardInput.WriteLine("ReloadConfig"); m_consoleProcess.OutputDataReceived += m_consoleProcess_DataReceived; m_consoleProcess.ErrorDataReceived += m_consoleProcess_DataReceived; m_consoleProcess.Exited += m_consoleProcess_Exited; m_consoleProcess.Start(); m_consoleProcess.BeginOutputReadLine(); } private void StopConsoleProcess() { if (m_consoleProcess is null) return; m_consoleProcess.OutputDataReceived -= m_consoleProcess_DataReceived; m_consoleProcess.ErrorDataReceived -= m_consoleProcess_DataReceived; m_consoleProcess.Exited -= m_consoleProcess_Exited; m_consoleProcess.Close(); m_consoleProcess.Dispose(); m_consoleProcess = null; } private void m_consoleProcess_Exited(object sender, EventArgs e) { if (m_formClosing) return; AppendConsoleText($"Console process exited. Attempting restart...{Environment.NewLine}"); try { StartConsoleProcess(textBoxHostConfig.Text); } catch (Exception ex) { AppendConsoleText($"Exception attempting to start console process: {ex.Message}{Environment.NewLine}"); } } private void m_consoleProcess_DataReceived(object sender, DataReceivedEventArgs e) => AppendConsoleText(e.Data); private void AppendConsoleText(string text) { if (m_formClosing) return; BeginInvoke(new Action(() => { if (m_formClosing) return; int maxOutput = textBoxConsoleOutput.MaxLength; string output = $"{textBoxConsoleOutput.Text}{text}{Environment.NewLine}"; if (output.Length > maxOutput) output = output.TruncateLeft(maxOutput); textBoxConsoleOutput.Text = output; textBoxConsoleOutput.SelectionStart = output.Length; textBoxConsoleOutput.ScrollToCaret(); tabPageHostConnection.ToolTipText = $"{textBoxConsoleOutput.Lines.Length / 2:N0} messages..."; })); } }}
//******************************************************************************************************
// MainForm.ManageHostConfig.cs - Gbtc
//
// Copyright © 2021, 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:
// ----------------------------------------------------------------------------------------------------
// 12/31/2020 - J. Ritchie Carroll
// Generated original version of source code.
//
//******************************************************************************************************
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using GSF;
using GSF.Diagnostics;
using GSF.IO;
namespace SELPDCImporter
{
partial class MainForm
{
private Process m_consoleProcess;
// Attempt to auto-load initial host configuration file (useful when running from host service folder)
private string LookupHostConfig()
{
// Search through list of known source applications (faster than manual search)
foreach (string hostApp in new[] { "openPDC", "openHistorian", "SIEGate" })
{
string absolutePath = FilePath.GetAbsolutePath($"{hostApp}.exe.config");
if (File.Exists(absolutePath))
{
HostApp = hostApp;
return absolutePath;
}
}
// Fall back on manual search
foreach (string configFile in FilePath.GetFileList($"{FilePath.AddPathSuffix(FilePath.GetAbsolutePath(""))}*.exe.config"))
{
if (IsHostConfig(configFile))
return configFile;
}
return "";
}
private bool IsHostConfig(string configFile)
{
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))
return false;
if (applicationName.Trim().Equals(FilePath.GetFileNameWithoutExtension(FilePath.GetFileNameWithoutExtension(configFile)), StringComparison.OrdinalIgnoreCase))
{
HostApp = applicationName;
return true;
}
}
catch (Exception ex)
{
m_log.Publish(MessageLevel.Warning, "IsHostConfig", $"Failed parse config file \"{configFile}\".", exception: ex);
}
return false;
}
private void LoadHostConfigFile(string configFile, ImportParameters importParams)
{
XDocument serviceConfig = XDocument.Load(configFile);
string 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();
string 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();
Guid nodeID = Guid.Parse(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() ?? Guid.Empty.ToString());
importParams.InitializeConnection(connectionString, dataProviderString, nodeID);
StartConsoleProcess(configFile);
}
private void StartConsoleProcess(string configFile)
{
// Stop any existing running process
StopConsoleProcess();
m_consoleProcess = new Process
{
StartInfo = new ProcessStartInfo
{
UseShellExecute = false,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
WindowStyle = ProcessWindowStyle.Hidden,
CreateNoWindow = true,
FileName = $"{FilePath.AddPathSuffix(Path.GetDirectoryName(configFile))}{HostApp}Console.exe"
},
EnableRaisingEvents = true
};
// Example to send command to console:
// m_consoleProcess.StandardInput.WriteLine("ReloadConfig");
m_consoleProcess.OutputDataReceived += m_consoleProcess_DataReceived;
m_consoleProcess.ErrorDataReceived += m_consoleProcess_DataReceived;
m_consoleProcess.Exited += m_consoleProcess_Exited;
m_consoleProcess.Start();
m_consoleProcess.BeginOutputReadLine();
}
private void StopConsoleProcess()
{
if (m_consoleProcess is null)
return;
m_consoleProcess.OutputDataReceived -= m_consoleProcess_DataReceived;
m_consoleProcess.ErrorDataReceived -= m_consoleProcess_DataReceived;
m_consoleProcess.Exited -= m_consoleProcess_Exited;
m_consoleProcess.Close();
m_consoleProcess.Dispose();
m_consoleProcess = null;
}
private void m_consoleProcess_Exited(object sender, EventArgs e)
{
if (m_formClosing)
return;
AppendConsoleText($"Console process exited. Attempting restart...{Environment.NewLine}");
try
{
StartConsoleProcess(textBoxHostConfig.Text);
}
catch (Exception ex)
{
AppendConsoleText($"Exception attempting to start console process: {ex.Message}{Environment.NewLine}");
}
}
private void m_consoleProcess_DataReceived(object sender, DataReceivedEventArgs e) =>
AppendConsoleText(e.Data);
private void AppendConsoleText(string text)
{
if (m_formClosing)
return;
BeginInvoke(new Action(() =>
{
if (m_formClosing)
return;
int maxOutput = textBoxConsoleOutput.MaxLength;
string output = $"{textBoxConsoleOutput.Text}{text}{Environment.NewLine}";
if (output.Length > maxOutput)
output = output.TruncateLeft(maxOutput);
textBoxConsoleOutput.Text = output;
textBoxConsoleOutput.SelectionStart = output.Length;
textBoxConsoleOutput.ScrollToCaret();
tabPageHostConnection.ToolTipText = $"{textBoxConsoleOutput.Lines.Length / 2:N0} messages...";
}));
}
}
}