using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Globalization;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.ServiceProcess;
using chc.servicemanagertray.Properties;
using System.Security.Principal;
namespace chc.servicemanagertray
{
public partial class ServiceManagerForm : Form
{
#region Fields
/// <summary>
/// The datasource for the grid that provides the services.
/// </summary>
private ServiceDataSource ds;
/// <summary>
/// The name of the service currently selected to re-select on refresh and re-bind.
/// </summary>
private string instance_selected_service_name = null;
#endregion
#region Constructor
/// <summary>
/// Initializes the designer components.
/// Initializes the form.
/// </summary>
public ServiceManagerForm(String[] args)
{
InitializeComponent();
InitializeForm();
this.servicegrid.CellMouseEnter += Servicegrid_CellMouseEnter;
if (args.Length == 3)
{
bool stopToFalseAndStartToTrue = Boolean.Parse(args[2]);
var service = (from sw in ds.GetServices() where sw.ServiceController.ServiceName == args[1] select sw).FirstOrDefault();
if (service != null)
{
if (!stopToFalseAndStartToTrue)
{
service.Stop();
} else
{
service.Start();
}
SetStatusUpdateNotificationTimer(service, !stopToFalseAndStartToTrue ? ServiceControllerStatus.Stopped : ServiceControllerStatus.Running, null);
}
}
searchFilter.TextChanged += SearchFilter_TextChanged;
searchServiceInfo.TextChanged += searchServiceInfo_TextChanged;
}
private void SearchFilter_TextChanged(object sender, EventArgs e)
{
this.ds.Search = searchFilter.Text;
searchServiceInfo.Text = searchFilter.Text;
BindServiceData(true);
}
private void searchServiceInfo_TextChanged(object sender, EventArgs e)
{
this.ds.Search = searchServiceInfo.Text;
searchFilter.Text = searchServiceInfo.Text;
BindServiceData(true);
}
#endregion
#region Methods
/// <summary>
/// Creates the datasource, the tray icon and binds the grid,
/// </summary>
private void InitializeForm()
{
#if DEBUG
WindowState = FormWindowState.Normal;
#endif
this.ds = new ServiceDataSource();
// grid binding
InitializeGrid();
BuildTrayMenu();
System.Reflection.Assembly ass = System.Reflection.Assembly.GetExecutingAssembly();
statusstrip_statuslabel.Text = string.Concat("v", ass.GetName().Version.ToString());
}
/// <summary>
/// Initializes the grid programmatically (set alternating row style and so on..)
/// </summary>
private void InitializeGrid()
{
servicegrid.AlternatingRowsDefaultCellStyle.BackColor = servicegrid.DefaultCellStyle.BackColor.ChangeBrightness(-25);
BindServiceData(true);
this.servicegrid.Rows[0].Selected = true;
this.servicegrid.Focus();
}
/// <summary>
/// Builds the tray menu, adds the selected favorite services.
/// </summary>
private void BuildTrayMenu()
{
var favorites = (from sw in ds.GetServices() where sw.IsFavorite orderby sw.DisplayName descending select sw).ToList<ServiceWrapper>();
while (this.trayicon_menu.Items.Count > 6)
{
this.trayicon_menu.Items.RemoveAt(2);
}
if (favorites.Count < 1)
{
return;
}
foreach (ServiceWrapper sw in favorites)
{
var item_service = new ToolStripMenuItem();
item_service.Text = GetServiceMenuItemText(sw);
item_service.Tag = sw;
item_service.Checked = sw.Status == ServiceControllerStatus.Running;
item_service.ToolTipText = Properties.Resources.NotifyIcon_Menu_FavoriteServicesLabel_Tooltip;
item_service.Click += delegate(object sender, EventArgs e)
{
var i = sender as ToolStripMenuItem;
var swi = i.Tag as ServiceWrapper;
if (item_service.Checked)
{
swi.Stop();
if (ServiceManagerForm.IsElevated)
{
SetStatusUpdateNotificationTimer(swi, ServiceControllerStatus.Stopped, item_service);
}
}
else
{
swi.Start();
if (ServiceManagerForm.IsElevated)
{
SetStatusUpdateNotificationTimer(swi, ServiceControllerStatus.Running, item_service);
}
}
};
this.trayicon_menu.Items.Insert(1, item_service);
}
this.trayicon_menu.Items.Insert(1, new ToolStripSeparator());
var favorite_label = new ToolStripLabel(Properties.Resources.NotifyIcon_Menu_FavoriteServicesLabel_Text);
favorite_label.Font = new Font(System.Drawing.SystemFonts.IconTitleFont, FontStyle.Bold);
favorite_label.ForeColor = System.Drawing.SystemColors.InfoText;
this.trayicon_menu.Items.Insert(2, favorite_label);
}
/// <summary>
/// The service menu item string like [service name] - [service state]
/// </summary>
/// <param name="sw"></param>
/// <returns></returns>
private static string GetServiceMenuItemText(ServiceWrapper sw)
{
var msg = string.Format(Properties.Resources.NotifyIcon_Menu_Service, sw.DisplayName, sw.Status.ToString());
return msg;
}
/// <summary>
/// Starts a timer for the specified service
/// and after the services reached the desired status it refreshes the grid.
/// </summary>
/// <param name="sw"></param>
/// <param name="statusToWaitFor"></param>
private void SetStatusUpdateNotificationTimer(ServiceWrapper sw, ServiceControllerStatus statusToWaitFor, ToolStripMenuItem item_service)
{
if (item_service != null)
{
item_service.Enabled = false;
}
var refresh = new Timer();
refresh.Interval = 200;
refresh.Tick += delegate(object sender2, EventArgs e2)
{
sw.ServiceController.Refresh();
if (sw.ServiceController.Status == statusToWaitFor)
{
if (item_service != null)
{
item_service.Checked = (sw.ServiceController.Status == ServiceControllerStatus.Running);
item_service.Text = GetServiceMenuItemText(sw);
item_service.Enabled = true;
}
ShowServiceState(sw);
BindServiceData(false);
BuildTrayMenu();
refresh.Stop();
}
};
refresh.Start();
}
/// <summary>
/// Displays the service state as a balloon.
/// </summary>
/// <param name="sw"></param>
private void ShowServiceState(ServiceWrapper sw)
{
var msg = string.Format(CultureInfo.InvariantCulture, Properties.Resources.NotifyIcon_Baloon_Service_State, sw.DisplayName, sw.Status.ToString().ToLowerInvariant());
trayicon.ShowBalloonTip(2000, Properties.Resources.NotifyIcon_Baloon_Header, msg, ToolTipIcon.Info);
}
/// <summary>
/// Refreshes the services info and binds the data to the grid.
/// </summary>
/// <param name="refresh_services">If TRUE the list of services is refreshed as well.</param>
private void BindServiceData(bool refresh_services)
{
string selected_service_name = this.instance_selected_service_name;
if (selected_service_name == null)
{
selected_service_name = GetSelectedServiceName();
}
var list = ds.GetServicesSearched(refresh_services);
DataGridViewColumn sorted_column = servicegrid.SortedColumn;
if (sorted_column != null)
{
Properties.Settings.Default.SortColumnName = sorted_column.DataPropertyName;
Properties.Settings.Default.SortOrder = servicegrid.SortOrder;
}
else
{
sorted_column = (from DataGridViewColumn c in servicegrid.Columns where c.DataPropertyName == Properties.Settings.Default.SortColumnName select c).Single<DataGridViewColumn>();
}
var sorting_list = new SortableBindingList<ServiceWrapper>(list);
this.servicegrid.DataSource = sorting_list;
if (sorted_column != null)
{
servicegrid.Sort(sorted_column, Properties.Settings.Default.SortOrder == SortOrder.Descending ? ListSortDirection.Descending : ListSortDirection.Ascending);
}
if (selected_service_name != null)
{
servicegrid.ClearSelection();
var row = (from DataGridViewRow r in servicegrid.Rows where (r.DataBoundItem as ServiceWrapper).DisplayName == selected_service_name select r).SingleOrDefault<DataGridViewRow>();
if (row != null)
{
row.Selected = true;
servicegrid.FirstDisplayedScrollingRowIndex = row.Index;
}
}
servicegrid.Update();
}
/// <summary>
/// Gets the name of the selected service.
/// </summary>
/// <returns></returns>
private string GetSelectedServiceName()
{
string selected_service_name = null;
if (servicegrid.SelectedRows.Count > 0)
{
selected_service_name = (servicegrid.SelectedRows[0].DataBoundItem as ServiceWrapper).DisplayName;
}
return selected_service_name;
}
/// <summary>
/// If the window is minimized it will hidden in the tray.
/// </summary>
private void SetTaskbarState()
{
if (FormWindowState.Minimized == this.WindowState)
{
this.ShowInTaskbar = false;
if (!Properties.Settings.Default.TrayBalloonShown)
{
this.trayicon.ShowBalloonTip(5000, Properties.Resources.NotifyIcon_Baloon_Header, Properties.Resources.NotifyIcon_Baloon_Hide, ToolTipIcon.Info);
Properties.Settings.Default.TrayBalloonShown = true;
}
}
else
{
this.ShowInTaskbar = true;
}
}
public static bool IsElevated
{
get
{
WindowsPrincipal pricipal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
bool hasAdministrativeRight = pricipal.IsInRole(WindowsBuiltInRole.Administrator);
return hasAdministrativeRight;
}
}
public static void RequestElevatation(String serviceName, bool falseIsToStopAndTrueIsToStart)
{
ProcessStartInfo processInfo = new ProcessStartInfo();
processInfo.Verb = "runas";
processInfo.FileName = Application.ExecutablePath;
processInfo.Arguments = serviceName + " " + falseIsToStopAndTrueIsToStart.ToString();
try
{
Process.Start(processInfo);
}
catch (Win32Exception)
{
return;
}
Application.Exit();
}
#endregion
#region Commands
/// <summary>
/// Displays the form.
/// </summary>
private void ShowForm()
{
this.WindowState = FormWindowState.Normal;
}
/// <summary>
/// Saves the settings and quits.
/// </summary>
public void QuitForm()
{
SaveSettings();
Application.Exit();
}
/// <summary>
/// Saves the grid sort settings into the program settings.
/// </summary>
private void SaveGridSortState()
{
if (servicegrid.SortedColumn != null)
{
Properties.Settings.Default.SortColumnName = servicegrid.SortedColumn.DataPropertyName;
Properties.Settings.Default.SortOrder = servicegrid.SortOrder;
}
}
/// <summary>
/// Saves settings.
/// Save grid sort state.
/// </summary>
private void SaveSettings()
{
SaveGridSortState();
Properties.Settings.Default.Save();
}
/// <summary>
/// Minimizes the form.
/// </summary>
private void MinimizeForm()
{
WindowState = FormWindowState.Minimized;
}
/// <summary>
/// Shows or hides the main form based on the visibility (toggle).
/// </summary>
private void ToggleFormDisplay()
{
if (WindowState != FormWindowState.Minimized)
{
MinimizeForm();
}
else
{
ShowForm();
}
}
private void RefreshGrid()
{
BindServiceData(true);
}
#endregion
#region Events
/// <summary>
/// When the form is resized, the taskbar state is set.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ServiceManagerForm_Resize(object sender, EventArgs e)
{
SetTaskbarState();
}
/// <summary>
/// When the form is closed, it is minimized instead so that it is hidden in the tray.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ServiceManagerForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason != CloseReason.ApplicationExitCall)
{
e.Cancel = true;
WindowState = FormWindowState.Minimized;
}
}
#endregion
#region Tray Icon Menu Events
/// <summary>
/// On left mouse click, show the service manager on the tray icon.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void trayicon_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
ToggleFormDisplay();
}
}
/// <summary>
/// Show the service manager on the tray menu item click.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void trayicon_menu_servicemanager_Click(object sender, EventArgs e)
{
ToggleFormDisplay();
}
/// <summary>
/// When exit is clicked the quit method is called.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void trayicon_menu_exit_Click(object sender, EventArgs e)
{
QuitForm();
}
#endregion
#region Main menu events
/// <summary>
/// About menu.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void mainmenu_help_about_Click(object sender, EventArgs e)
{
MessageBox.Show(global::chc.servicemanagertray.Properties.Resources.About_Text, global::chc.servicemanagertray.Properties.Resources.About_Title, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
/// <summary>
/// Options menu
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void mainmenu_tools_option_Click(object sender, EventArgs e)
{
MessageBox.Show("Not implemented at the moment.", global::chc.servicemanagertray.Properties.Resources.About_Title, MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
#endregion
#region Grid Events
private void Servicegrid_CellMouseEnter(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex < 0 || e.RowIndex < 0)
{
return;
}
var dataGridView = (sender as DataGridView);
//Check the condition as per the requirement casting the cell value to the appropriate type
servicegrid.Cursor = Cursors.Default;
switch (e.ColumnIndex)
{
case 2:
case 3:
case 4:
servicegrid.Cursor = Cursors.Hand;
break;
default:
servicegrid.Cursor = Cursors.Default;
break;
}
}
/// <summary>
/// Renders the info panel contents on the left.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void servicegrid_CurrentCellChanged(object sender, EventArgs e)
{
if (servicegrid.CurrentRow != null)
{
ServiceWrapper sw = servicegrid.CurrentRow.DataBoundItem as ServiceWrapper;
infopanel_name.Text = sw.ServiceController.DisplayName;
infopanel_description.Text = sw.Description;
}
}
/// <summary>
/// Selects the service row on right click also.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void servicegrid_MouseDown(object sender, MouseEventArgs e)
{
// Sets is so the right-mousedown will select a cell
DataGridView.HitTestInfo hti = servicegrid.HitTest(e.X, e.Y);
if (hti.RowIndex == -1)
{
return;
}
// Clear all the previously selected rows
servicegrid.ClearSelection();
// Set as selected
servicegrid.Rows[hti.RowIndex].Selected = true;
}
/// <summary>
/// Updates the ui to make a service favorita or start/stop on the gui.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void servicegrid_CellClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex < 0)
{
return;
}
var row = servicegrid.Rows[e.RowIndex];
var sw = row.DataBoundItem as ServiceWrapper;
switch (row.Cells[e.ColumnIndex].OwningColumn.DataPropertyName)
{
case "IsFavorite":
sw.IsFavorite = !sw.IsFavorite;
this.BuildTrayMenu();
SaveSettings();
break;
case "Status":
case "IsRunning":
ToolStripMenuItem menu_item = null;
bool new_state = !sw.IsRunning;
sw.IsRunning = new_state;
if (IsElevated)
{
SetStatusUpdateNotificationTimer(sw, new_state ? ServiceControllerStatus.Running : ServiceControllerStatus.Stopped, menu_item);
// find corresponding tray menu item
foreach (ToolStripItem item in trayicon_menu.Items)
{
menu_item = item as ToolStripMenuItem;
if (menu_item != null && menu_item.Tag == sw)
{
break;
}
menu_item = null;
}
break;
}
break;
}
}
#endregion
#region Generic Command Events
/// <summary>
/// Generic refresh command.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void generic_refreshbutton_Click(object sender, EventArgs e)
{
RefreshGrid();
}
/// <summary>
/// Generic exit command.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void generic_exit_Click(object sender, EventArgs e)
{
QuitForm();
}
#endregion
#region Tool Strip Events
/// <summary>
/// Starts the windows service manager.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void toolstrip_winservicemanager_Click(object sender, EventArgs e)
{
Process.Start("services.msc");
}
/// <summary>
/// Starts the windows task manager.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void toolstrip_taskmanager_Click(object sender, EventArgs e)
{
Process.Start("taskmgr.exe");
}
#endregion
}
}