SafeDispatch/Service Configurator/Form1.cs
2024-02-22 18:43:59 +02:00

574 lines
21 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ServiceProcess;
using Telerik.WinControls;
using Telerik.WinControls.UI;
using System.Diagnostics;
using Microsoft.Win32;
using System.Xml;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.Collections;
using System.IO;
using System.Security.AccessControl;
using System.Security.Principal;
namespace ServiceConfigurator
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private string SERVICE_NAME = null;
const string userRoot = "HKEY_LOCAL_MACHINE";
const string subkey = "SYSTEM\\CurrentControlSet\\services";
const string keyName = userRoot + "\\" + subkey;
//private data
private string _configFilename = "";
private bool _isDirty;
private bool IsDirty
{
get { return _isDirty; }
set { _isDirty = value; }
}
private Hashtable serviceHT = new Hashtable();
private string tcpServerServiceName = "TCPServerService";
private string tcpClientServiceName = "TCPClientService";
//static string logFile = System.AppDomain.CurrentDomain.BaseDirectory + "\\log.log";
//public properties
public virtual string ConfigFilename
{
get
{
return _configFilename;
}
set
{
_configFilename = value;
}
}
private void btnStart_Click(object sender, EventArgs e)
{
StartService(SERVICE_NAME,1000);
}
private void btnRestart_Click(object sender, EventArgs e)
{
RestartService(SERVICE_NAME, 1000);
}
private void btnStop_Click(object sender, EventArgs e)
{
StopService(SERVICE_NAME, 2000);
lblInfoStatus.Text = "";
}
private void btnCheckService_Click(object sender, EventArgs e)
{
UpdateStatus();
}
public static void StartService(string serviceName, int timeoutMilliseconds)
{
ServiceController service = new ServiceController(serviceName);
try
{
TimeSpan timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds);
service.Start();
service.WaitForStatus(ServiceControllerStatus.Running, timeout);
}
catch
{
// ...
}
}
public static void RestartService(string serviceName, int timeoutMilliseconds)
{
ServiceController service = new ServiceController(serviceName);
try
{
int millisec1 = Environment.TickCount;
TimeSpan timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds);
service.Stop();
service.WaitForStatus(ServiceControllerStatus.Stopped, timeout);
// count the rest of the timeout
int millisec2 = Environment.TickCount;
timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds - (millisec2 - millisec1));
service.Start();
service.WaitForStatus(ServiceControllerStatus.Running, timeout);
}
catch
{
// ...
}
}
public static void StopService(string serviceName, int timeoutMilliseconds)
{
ServiceController service = new ServiceController(serviceName);
try
{
TimeSpan timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds);
service.Stop();
service.WaitForStatus(ServiceControllerStatus.Stopped, timeout);
}
catch
{
// ...
}
}
string GetStatus(string serviceName)
{
ServiceController sc = new ServiceController(serviceName);
try
{
switch (sc.Status)
{
case ServiceControllerStatus.Running:
return "Running ";
case ServiceControllerStatus.Stopped:
return "Stopped ";
case ServiceControllerStatus.Paused:
return "Paused ";
case ServiceControllerStatus.StopPending:
return "Stopping ";
case ServiceControllerStatus.StartPending:
return "Starting ";
default:
return "Status Changing ";
}
}
catch
{
return "Invalid Service name!";
}
}
string GetPath(string serviceName)
{
string fullKeyName = keyName + "\\" + txtServiceName.Text;
string path = (string)Registry.GetValue(fullKeyName, "ImagePath", "Not available ...");
if (path != null)
{
if(path.Substring(0,1) == "\"")
path = path.Substring(1, path.Length - 2);
}
return path;
}
private void txtServiceName_TextChanged(object sender, EventArgs e)
{
Checkstate();
}
private void Checkstate()
{
foreach (Control ctrl in this.Controls)
{
if (ctrl is RadGroupBox)
{
foreach (Control tb in ctrl.Controls)
{
if (tb is RadButton)
{
((RadButton)tb).Enabled = (txtServiceName.Text.Length > 0);
}
}
}
}
btnRefesh.Enabled = true;
SERVICE_NAME = txtServiceName.Text.ToString();
}
private void Form1_Load(object sender, EventArgs e)
{
//#region Folder Rights
//try
//{
// GrantAccess(logFile);
//}
//catch
//{
// lblInfoStatus.Text = "Unable to give file permissions. Please run as admin!";
//}
//#endregion
//GetAllServices();
lblInfoStatus.Text = "";
Checkstate();
timerStatus.Start();
timerServiceState.Start();
LoadServices();
GetAllServices();
ToolTip toolTip1 = new System.Windows.Forms.ToolTip();
toolTip1.SetToolTip(btnStart, "START");
ToolTip toolTip2 = new System.Windows.Forms.ToolTip();
toolTip1.SetToolTip(btnRestart, "RESTART");
ToolTip toolTip3 = new System.Windows.Forms.ToolTip();
toolTip1.SetToolTip(btnStop, "STOP");
ToolTip toolTip4 = new System.Windows.Forms.ToolTip();
toolTip1.SetToolTip(btnSave, "SAVE");
ToolTip toolTip5 = new System.Windows.Forms.ToolTip();
toolTip1.SetToolTip(btnClose, "CLOSE");
ToolTip toolTip6 = new System.Windows.Forms.ToolTip();
toolTip1.SetToolTip(btnUninstall, "UNINSTALL");
ToolTip toolTip7 = new System.Windows.Forms.ToolTip();
toolTip1.SetToolTip(btnRefesh, "REFRESH LIST");
}
private void UpdateStatus()
{
//long times = DateTime.Now.Ticks;
//int pointNb = 0;
//if (times % 5 == 0) pointNb = 5;
//else if (times % 4 == 0) pointNb = 4;
//else if (times % 3 == 0) pointNb = 3;
//else if (times % 2 == 0) pointNb = 2;
//else if (times % 1 == 0) pointNb = 1;
//string points = new String('.', pointNb);
lblStatus.Text = GetStatus(SERVICE_NAME); // +points;
txtPath.Text = GetPath(SERVICE_NAME);
#region Notify icon
if (!Program.notify) return;
if (!serviceHT.Contains(SERVICE_NAME))
serviceHT.Add(SERVICE_NAME, lblStatus.Text);
else
{
if(serviceHT[SERVICE_NAME].ToString() != lblStatus.Text)
{
//add notify status changed for service
notifyIcon1.BalloonTipText = string.Format("{0} is {1}", SERVICE_NAME, lblStatus.Text);
notifyIcon1.Visible = true;
notifyIcon1.ShowBalloonTip(500);
serviceHT[SERVICE_NAME] = lblStatus.Text;
}
}
#endregion
}
private void NotifyUserIfChanged()
{
}
private void timerStatus_Tick(object sender, EventArgs e)
{
if(txtServiceName.Text !="") UpdateStatus();
NotifyUserIfChanged();
//pictureBox1.Visible = lblStatus.Text.Equals("Running ");
//if (txtServiceName.Text != "")
//{
// btnUninstall.Enabled = !(lblStatus.Text.Equals("Running "));
//}
//else
btnUninstall.Enabled = false;
lblProcNo.Text = CheckProcesses();
}
AutoCompleteStringCollection colValues = new AutoCompleteStringCollection();
private void GetAllServices()
{
// get list of Windows services
ServiceController[] services = ServiceController.GetServices();
List<string> ac = new List<string>();
// try to find service name
foreach (ServiceController service in services)
{
ac.Add(service.ServiceName.ToString());
}
colValues.AddRange(ac.ToArray());
if (colValues.Contains(tcpServerServiceName))
txtServiceName.Text = tcpServerServiceName;
else if (colValues.Contains(tcpClientServiceName))
txtServiceName.Text = tcpClientServiceName;
}
private void LoadPropertyGrid()
{
try
{
string[] splitConfig = txtPath.Text.Split(new string[] { ".exe" }, StringSplitOptions.None);
ConfigFilename = splitConfig[0] + ".exe.Config";
if (System.IO.File.Exists(ConfigFilename))
{
this.propertyGrid1.SelectedObject = LoadConfiguration(ConfigFilename);
}
else
this.propertyGrid1.SelectedObject = null;
//Process.Start("notepad.exe", fileConfig);
}
catch { }
}
private void btnClose_Click(object sender, EventArgs e)
{
if (this.IsDirty == true)
{
DialogResult result = RadMessageBox.Show("Save Application Configuration changes before closing?", "Application Configuration", MessageBoxButtons.YesNoCancel, RadMessageIcon.Question);
if (result == DialogResult.Yes)
{
try
{
SaveConfiguration(this.ConfigFilename, (CustomClass)this.propertyGrid1.SelectedObject);
RadMessageBox.Show("Application Configuration changes have been saved.", "Application Configuration", MessageBoxButtons.OK, RadMessageIcon.Info);
this.Close();
}
catch (Exception ex)
{
RadMessageBox.Show("Failed to btnSave configuration. Reason(" + ex.Message + ")", "Application Configuration", MessageBoxButtons.OK, RadMessageIcon.Exclamation);
}
}
else if (result == DialogResult.No)
{
this.Close();
}
}
else
{
this.Close();
}
}
public CustomClass LoadConfiguration(string configurationFile)
{
CustomClass customClass = new CustomClass();
try
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(configurationFile);
XmlNode configuration = xmlDoc.SelectSingleNode("configuration");
//Build the node list
XmlNodeList sectionList = configuration.ChildNodes;
for (int y = 0; y < sectionList.Count; y++)
{
XmlNodeList settingsList = xmlDoc.SelectNodes("configuration/" + sectionList[y].Name + "/add");
if (settingsList.Count != 0 && settingsList != null)
{
//Add a property to customClass for each node found.
for (int i = 0; i < settingsList.Count; i++)
{
XmlAttribute atrribKey = settingsList[i].Attributes["key"];
XmlAttribute attribValue = settingsList[i].Attributes["value"];
XmlAttribute attribDescription = settingsList[i].Attributes["description"];
if (atrribKey != null && attribValue != null)
{
//If there's no description for the key - assign the name to the description.
//The description attribute is displayed below the name in the property grid.
if (attribDescription == null)
{
attribDescription = atrribKey;
}
//We'll at least test to see if it's a boolean property and set the type here
//to force the property grid to display a dropdown list of True or False.
Type propType;
if (attribValue.Value.ToLower() == "true" || attribValue.Value.ToLower() == "false")
{
propType = typeof(System.Boolean);
}
else
{
propType = typeof(System.String);
}
//Now add the property
customClass.AddProperty(atrribKey.Value.ToString(), attribValue.Value.ToString(),
attribDescription.Value.ToString(), sectionList[y].Name, propType, false, false);
}
}
}
}
xmlDoc = null;
}
catch (Exception ex)
{
throw ex;
}
return customClass;
}
public void SaveConfiguration(string configurationFile, CustomClass customClass)
{
try
{
//Reload the configuration file
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(configurationFile);
//Save a backup version
xmlDoc.Save(configurationFile + "_bak");
//Populate our property collection.
PropertyDescriptorCollection props = customClass.GetProperties();
//Repolulate the three supported sections
RepopulateXmlSection("ApplicationConfiguration", xmlDoc, props);
RepopulateXmlSection("CommonConfiguration", xmlDoc, props);
RepopulateXmlSection("appSettings", xmlDoc, props);
xmlDoc.Save(configurationFile);
}
catch (Exception ex)
{
throw ex;
}
}
private void RepopulateXmlSection(string sectionName, XmlDocument xmlDoc, PropertyDescriptorCollection props)
{
XmlNodeList nodes = xmlDoc.SelectNodes("configuration/" + sectionName + "/add");
for (int i = 0; i < nodes.Count; i++)
{
//Find the property in the property collection with the same name as the current node in the Xml document
CustomClass.DynamicProperty property = (CustomClass.DynamicProperty)props[nodes[i].Attributes["key"].Value];
if (property != null)
{
//Set the node value to the property value (which will have been set in the Property grid.
nodes[i].Attributes["value"].Value = property.GetValue(null).ToString();
//Check to see if we have a value for our extended custom xml attribute - the description attribute.
//The default description is the property name when no descripyion attribute is present.
//If they're not the same - then a value was passed when the property was created.
if (property.Description != property.Name)
{
//double check here that there is in fact a description attribute
if (nodes[i].Attributes["description"] != null)
{
nodes[i].Attributes["description"].Value = property.Description;
}
}
}
}
}
private void propertyGrid1_PropertyValueChanged(object sender, PropertyGridItemValueChangedEventArgs e)
{
this.IsDirty = true;
}
private void txtPath_TextChanged(object sender, EventArgs e)
{
LoadPropertyGrid();
}
private void btnSave_Click(object sender, EventArgs e)
{
try
{
SaveConfiguration(ConfigFilename, (CustomClass)this.propertyGrid1.SelectedObject);
RadMessageBox.Show("Application Configuration changes have been saved.", "Application Configuration", MessageBoxButtons.OK, RadMessageIcon.Info);
this.IsDirty = false;
this.propertyGrid1.Focus();
//if(lblStatus.Text=="Running")
//{
StopService(SERVICE_NAME, 1000);
StartService(SERVICE_NAME, 1000);
//}
}
catch (Exception ex)
{
RadMessageBox.Show("Failed to btnSave configuration. Reason(" + ex.Message + ")", "Application Configuration", MessageBoxButtons.OK, RadMessageIcon.Exclamation);
}
}
private void btnUninstall_Click(object sender, EventArgs e)
{
if (UninstallMe())
{
RadMessageBox.Show("Successfully uninstalled the " + SERVICE_NAME, "Status",
MessageBoxButtons.OK, RadMessageIcon.Info);
colValues.Remove(txtServiceName.Text);
txtServiceName.Text = "";
LoadServices();
}
else
{
RadMessageBox.Show("Unsuccessfully uninstalled the " + SERVICE_NAME, "Status",
MessageBoxButtons.OK, RadMessageIcon.Error);
}
}
private bool UninstallMe()
{
try
{
ManagedInstallerClass.InstallHelper(
new string[] { "/u", txtPath.Text });
}
catch
{
return false;
}
return true;
}
private void LoadServices()
{
txtServiceName.AutoCompleteMode = AutoCompleteMode.Suggest;
txtServiceName.AutoCompleteSource = AutoCompleteSource.CustomSource;
txtServiceName.AutoCompleteCustomSource = colValues;
}
private void btnRefesh_Click(object sender, EventArgs e)
{
colValues.Clear();
GetAllServices();
LoadServices();
}
private string CheckProcesses()
{
int numberOfProcesses = 0;
Process[] processes = Process.GetProcesses();
foreach (Process process in processes)
{
numberOfProcesses++;
}
return numberOfProcesses.ToString();
}
private void ResizeForm(object sender, EventArgs e)
{
this.Height = radCollapsiblePanel1.Location.Y + radCollapsiblePanel1.Height +43;
}
//private void timerServiceState_Tick(object sender, EventArgs e)
//{
// if (File.Exists(logFile) && lblStatus.Text != ServiceControllerStatus.Stopped.ToString())
// {
// lblInfoStatus.Text = File.ReadAllText(logFile);
// }
//}
private bool GrantAccess(string fullPath)
{
if (!File.Exists(fullPath))
File.Create(fullPath);
DirectoryInfo dInfo = new DirectoryInfo(fullPath);
DirectorySecurity dSecurity = dInfo.GetAccessControl();
dSecurity.AddAccessRule(new FileSystemAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), FileSystemRights.FullControl, InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit, PropagationFlags.NoPropagateInherit, AccessControlType.Allow));
dInfo.SetAccessControl(dSecurity);
return true;
}
}
}