From 7af1bdb84b1178585cf5da47d732bff20dd6a40e Mon Sep 17 00:00:00 2001 From: Brian Saville Date: Tue, 8 Jun 2021 17:29:03 +1000 Subject: [PATCH 1/5] Move to WMI Events instead of polling --- .../Extensions/ServiceControllerExtensions.cs | 42 --- src/ServiceBouncer/MainForm.Designer.cs | 10 +- src/ServiceBouncer/MainForm.cs | 148 +++++---- src/ServiceBouncer/MainForm.resx | 3 - src/ServiceBouncer/ServiceViewModel.cs | 295 +++++++++--------- 5 files changed, 244 insertions(+), 254 deletions(-) diff --git a/src/ServiceBouncer/Extensions/ServiceControllerExtensions.cs b/src/ServiceBouncer/Extensions/ServiceControllerExtensions.cs index 2032692..e6080a0 100644 --- a/src/ServiceBouncer/Extensions/ServiceControllerExtensions.cs +++ b/src/ServiceBouncer/Extensions/ServiceControllerExtensions.cs @@ -78,47 +78,5 @@ public static void SetStartupType(this ServiceController controller, ServiceStar wmiManagementObject.InvokeMethod("ChangeStartMode", parameters); } } - - public static string GetDescription(this ServiceController controller) - { - using (var wmiManagementObject = controller.GetNewWmiManagementObject()) - { - return wmiManagementObject["Description"]?.ToString(); - } - } - - public static string GetLogOnAs(this ServiceController controller) - { - using (var wmiManagementObject = controller.GetNewWmiManagementObject()) - { - const string localSystemAccountName = "LocalSystem"; - - var logOnAs = wmiManagementObject["StartName"]?.ToString(); - if (string.IsNullOrWhiteSpace(logOnAs) || logOnAs.Equals(localSystemAccountName, StringComparison.OrdinalIgnoreCase)) - { - logOnAs = localSystemAccountName; - } - - return logOnAs; - } - } - -#if NET45 - //NET45 PolyFil as controller doesn't have StartType - public static string GetStartupType(this ServiceController controller) - { - using (var wmiManagementObject = controller.GetNewWmiManagementObject()) - { - return wmiManagementObject["StartMode"].ToString(); - } - } -#elif NET461 || NET471 || NET48 - - public static string GetStartupType(this ServiceController controller) - { - return controller.StartType.ToString(); - } - -#endif } } diff --git a/src/ServiceBouncer/MainForm.Designer.cs b/src/ServiceBouncer/MainForm.Designer.cs index e96551b..125ce16 100644 --- a/src/ServiceBouncer/MainForm.Designer.cs +++ b/src/ServiceBouncer/MainForm.Designer.cs @@ -1,4 +1,4 @@ -namespace ServiceBouncer +namespace ServiceBouncer { partial class MainForm { @@ -79,7 +79,6 @@ private void InitializeComponent() this.toolStripRefreshButton = new System.Windows.Forms.ToolStripButton(); this.toolStripFilterIcon = new System.Windows.Forms.ToolStripLabel(); this.toolStripFilterBox = new System.Windows.Forms.ToolStripTextBox(); - this.refreshTimer = new System.Windows.Forms.Timer(this.components); this.appTerminationTimer = new System.Windows.Forms.Timer(this.components); this.toolStripContainer.BottomToolStripPanel.SuspendLayout(); this.toolStripContainer.ContentPanel.SuspendLayout(); @@ -570,12 +569,6 @@ private void InitializeComponent() this.toolStripFilterBox.ToolTipText = "Type a name here to filter"; this.toolStripFilterBox.TextChanged += new System.EventHandler(this.FilterBoxTextChanged); // - // refreshTimer - // - this.refreshTimer.Enabled = true; - this.refreshTimer.Interval = 1000; - this.refreshTimer.Tick += new System.EventHandler(this.RefreshTimerTicked); - // // appTerminationTimer // this.appTerminationTimer.Enabled = true; @@ -620,7 +613,6 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripContainer toolStripContainer; private System.Windows.Forms.ToolStripButton toolStripStartButton; private System.Windows.Forms.ToolStripButton toolStripStopButton; - private System.Windows.Forms.Timer refreshTimer; private System.Windows.Forms.DataGridView dataGridView; private System.Windows.Forms.BindingSource serviceViewModelBindingSource; private System.Windows.Forms.ToolStripButton toolStripRestartButton; diff --git a/src/ServiceBouncer/MainForm.cs b/src/ServiceBouncer/MainForm.cs index d1e5c11..dbc32d8 100644 --- a/src/ServiceBouncer/MainForm.cs +++ b/src/ServiceBouncer/MainForm.cs @@ -10,6 +10,7 @@ using System.Threading.Tasks; using System.Windows.Forms; using DialogResult = System.Windows.Forms.DialogResult; +using System.Management; namespace ServiceBouncer { @@ -22,6 +23,11 @@ public partial class MainForm : Form private DateTime? appDeactivatedTime; private bool IsActive => machineLockedTime == null || appDeactivatedTime == null; + // WMI Events + private ManagementEventWatcher modificationEventWatcher; + private ManagementEventWatcher creationEventWatcher; + private ManagementEventWatcher deletionEventWatcher; + public MainForm(string machine) { InitializeComponent(); @@ -29,14 +35,7 @@ public MainForm(string machine) machineHostname = machine; toolStripConnectToTextBox.Text = machineHostname; services = new List(); - Microsoft.Win32.SystemEvents.SessionSwitch += SessionSwitch; - -#if NET45 - //In NET45 startup type requires WMI, so it doesn't auto refresh - dataGridStatupType.HeaderText = $@"{dataGridStatupType.HeaderText}*"; -#endif - dataGridDescription.HeaderText = $@"{dataGridDescription.HeaderText}*"; - dataGridLogOnAs.HeaderText = $@"{dataGridLogOnAs.HeaderText}*"; + Microsoft.Win32.SystemEvents.SessionSwitch += SessionSwitch; // not sure what to do with this after converting to WMI events. probably good to do something. perhaps stop listening and reload services on unlock? } private void AppTerminationTimerTick(object sender, EventArgs e) @@ -52,21 +51,6 @@ private void AppTerminationTimerTick(object sender, EventArgs e) } } - private async void RefreshTimerTicked(object sender, EventArgs e) - { - if (IsActive) - { -#if NET45 - //Only refresh things which do not use WMI (i.e. Startup Type, Description, and Log On As are not refreshed) - await PerformBackgroundOperation(x => x.Refresh(ServiceViewModel.RefreshData.DisplayName, ServiceViewModel.RefreshData.ServiceName, ServiceViewModel.RefreshData.Status)); -#elif NET461 || NET471 || NET48 - //Only refresh things which do not use WMI (i.e. Description and Log On As are not refreshed) - await PerformBackgroundOperation(x => x.Refresh(ServiceViewModel.RefreshData.DisplayName, ServiceViewModel.RefreshData.ServiceName, ServiceViewModel.RefreshData.Status, ServiceViewModel.RefreshData.Startup)); -#endif - SetTitle(); - } - } - // PC Locked private void SessionSwitch(object sender, Microsoft.Win32.SessionSwitchEventArgs e) { @@ -152,8 +136,6 @@ await PerformOperationWithCheck(s => async x => { await x.Delete(); - Thread.Sleep(500); - await Reload(); }); } @@ -206,13 +188,9 @@ await PerformOperationWithCheck(s => }); } - private async void InstallClicked(object sender, EventArgs e) + private void InstallClicked(object sender, EventArgs e) { - await PerformAction(async () => - { - new InstallationForm().ShowDialog(); - await Reload(); - }); + new InstallationForm().ShowDialog(); } private async void ConnectButtonClick(object sender, EventArgs e) @@ -244,22 +222,56 @@ private async Task Reload() { try { - var systemServices = await Task.Run(() => ServiceController.GetServices(machineHostname)); + ManagementObjectCollection win32_Services = null; + + await Task.Run(() => + { + ManagementObjectSearcher searcher; + + if (!string.IsNullOrEmpty(machineHostname) && machineHostname != Environment.MachineName) + { + ConnectionOptions options = new ConnectionOptions(); + options.Impersonation = System.Management.ImpersonationLevel.Impersonate; + + ManagementScope scope = new ManagementScope("\\\\" + machineHostname + "\\root\\cimv2", options); + scope.Connect(); + + ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_Service"); + searcher = new ManagementObjectSearcher(scope, query); + } + else + { + searcher = new ManagementObjectSearcher("SELECT * FROM Win32_Service"); + } + + win32_Services = searcher.Get(); + + modificationEventWatcher?.Dispose(); + modificationEventWatcher = new ManagementEventWatcher(searcher.Scope, + new EventQuery("SELECT * FROM __InstanceModificationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_Service'")); + modificationEventWatcher.EventArrived += ModificationEventWatcher_EventArrived; + modificationEventWatcher.Start(); + + creationEventWatcher?.Dispose(); + creationEventWatcher = new ManagementEventWatcher(searcher.Scope, + new EventQuery("SELECT * FROM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_Service'")); + creationEventWatcher.EventArrived += CreationEventWatcher_EventArrived; + creationEventWatcher.Start(); + + deletionEventWatcher?.Dispose(); + deletionEventWatcher = new ManagementEventWatcher(searcher.Scope, + new EventQuery("SELECT * FROM __InstanceDeletionEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_Service'")); + deletionEventWatcher.EventArrived += DeletionEventWatcher_EventArrived; ; + deletionEventWatcher.Start(); + }); + services.Clear(); - foreach (var model in systemServices.Select(service => new ServiceViewModel(service))) + foreach (var model in win32_Services) { - services.Add(model); + services.Add(new ServiceViewModel(machineHostname, model)); } - await PerformBackgroundOperation(x => x.Refresh( - ServiceViewModel.RefreshData.DisplayName, - ServiceViewModel.RefreshData.ServiceName, - ServiceViewModel.RefreshData.Description, - ServiceViewModel.RefreshData.Status, - ServiceViewModel.RefreshData.Startup, - ServiceViewModel.RefreshData.LogOnAs)); - PopulateFilteredDataview(); SetTitle(); return true; @@ -290,6 +302,44 @@ await PerformBackgroundOperation(x => x.Refresh( } } + private void DeletionEventWatcher_EventArrived(object sender, EventArrivedEventArgs e) + { + var targetInstance = (ManagementBaseObject)e.NewEvent["TargetInstance"]; + var serviceName = targetInstance["Name"].ToString(); + services.RemoveAll(x => x.ServiceName == serviceName); + + this.Invoke(new MethodInvoker(delegate { + PopulateFilteredDataview(); + SetTitle(); + })); + } + + private void CreationEventWatcher_EventArrived(object sender, EventArrivedEventArgs e) + { + var targetInstance = (ManagementBaseObject)e.NewEvent["TargetInstance"]; + + services.Add(new ServiceViewModel(machineHostname, targetInstance)); + + this.Invoke(new MethodInvoker(delegate { + PopulateFilteredDataview(); + SetTitle(); + })); + } + + private void ModificationEventWatcher_EventArrived(object sender, EventArrivedEventArgs e) + { + var previousInstance = (ManagementBaseObject)e.NewEvent["PreviousInstance"]; + var targetInstance = (ManagementBaseObject)e.NewEvent["TargetInstance"]; + + var serviceName = targetInstance["Name"].ToString(); + + var modifiedService = services.Find(x => x.ServiceName == serviceName); + if (modifiedService == null) + return; + + modifiedService.UpdateFromWmi(targetInstance); + } + private void StartNewProcess(BaseCredentialsPrompt promptResult) { string username, domain; @@ -368,9 +418,6 @@ private async Task Connect() backgroundRefreshSeconds = EnvHelper.IsLocalMachine(machineHostname) ? 1 : 30; - refreshTimer.Enabled = true; - refreshTimer.Interval = backgroundRefreshSeconds * 1000; - SetConnectedStatusBar(); foreach (ToolStripItem toolStripItem in toolStrip.Items) @@ -399,7 +446,6 @@ private void Disconnect() toolStripConnectToTextBox.Visible = true; toolStripConnectButton.Visible = true; - refreshTimer.Enabled = false; } private void SetTitle() @@ -417,15 +463,7 @@ private void SetTitle() private void SetConnectedStatusBar() { - if (IsActive) - { - var backgroundRefreshTimeText = backgroundRefreshSeconds == 1 ? "1 second" : $"{backgroundRefreshSeconds} seconds"; - toolStripStatusLabel.Text = $@"Connected to {machineHostname}. - Background refresh every {backgroundRefreshTimeText}. - Columns marked '*' will not refresh."; - } - else - { - toolStripStatusLabel.Text = $@"Connected to {machineHostname}. - Background refresh disabled"; - } + toolStripStatusLabel.Text = $@"Connected to {machineHostname}."; } private async Task PerformOperationWithCheck(Func, bool> check, Func actionToPerform) diff --git a/src/ServiceBouncer/MainForm.resx b/src/ServiceBouncer/MainForm.resx index e79b0c5..399127f 100644 --- a/src/ServiceBouncer/MainForm.resx +++ b/src/ServiceBouncer/MainForm.resx @@ -132,9 +132,6 @@ 17, 17 - - 122, 17 - 918, 17 diff --git a/src/ServiceBouncer/ServiceViewModel.cs b/src/ServiceBouncer/ServiceViewModel.cs index f25d685..e22cc1c 100644 --- a/src/ServiceBouncer/ServiceViewModel.cs +++ b/src/ServiceBouncer/ServiceViewModel.cs @@ -4,7 +4,7 @@ using System.ComponentModel; using System.Diagnostics; using System.Drawing; -using System.Linq; +using System.Management; using System.Reflection; using System.ServiceProcess; using System.Text; @@ -14,7 +14,6 @@ namespace ServiceBouncer { public sealed class ServiceViewModel : INotifyPropertyChanged { - private readonly ServiceController controller; public event PropertyChangedEventHandler PropertyChanged; public string Name { get; private set; } public string ServiceName { get; private set; } @@ -23,119 +22,153 @@ public sealed class ServiceViewModel : INotifyPropertyChanged public string StartupType { get; private set; } public string LogOnAs { get; private set; } public Image StatusIcon { get; private set; } + public string MachineName { get; private set; } - public ServiceViewModel(ServiceController controller) + private const string LOCAL_SYSTEM_ACCOUNT_NAME = "LocalSystem"; + + public ServiceViewModel(string machineName, ManagementBaseObject wmiObject) { - this.controller = controller; + MachineName = machineName; + FillFromWmiObject(wmiObject); } - public async Task Start() + private void FillFromWmiObject(ManagementBaseObject wmiObject) { - if (controller.Status == ServiceControllerStatus.Stopped) + Name = wmiObject["DisplayName"]?.ToString(); + ServiceName = wmiObject["Name"]?.ToString(); + Description = wmiObject["Description"]?.ToString(); + Status = wmiObject["State"].ToString(); + StatusIcon = GetIcon(Status); + StartupType = wmiObject["StartMode"].ToString(); + + LogOnAs = wmiObject["StartName"]?.ToString(); + if (string.IsNullOrWhiteSpace(LogOnAs) || LogOnAs.Equals(LOCAL_SYSTEM_ACCOUNT_NAME, StringComparison.OrdinalIgnoreCase)) { - await Task.Run(() => controller.Start()); - await Refresh(RefreshData.Status); + LogOnAs = LOCAL_SYSTEM_ACCOUNT_NAME; } - else if (controller.Status == ServiceControllerStatus.Paused) + } + + public async Task Start() + { + using (var controller = new ServiceController(Name, MachineName)) { - await Task.Run(() => controller.Continue()); - await Refresh(RefreshData.Status); + if (controller.Status == ServiceControllerStatus.Stopped) + await Task.Run(() => controller.Start()); + else if (controller.Status == ServiceControllerStatus.Paused) + await Task.Run(() => controller.Continue()); } } public async Task Restart() { - if (controller.Status == ServiceControllerStatus.Running || controller.Status == ServiceControllerStatus.Paused) + using (var controller = new ServiceController(Name, MachineName)) { - await Task.Run(() => + if (controller.Status == ServiceControllerStatus.Running || controller.Status == ServiceControllerStatus.Paused) { - controller.Stop(); - controller.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(60)); - - if (controller.Status != ServiceControllerStatus.Stopped) + await Task.Run(() => { - throw new Exception("The service did not stop within 60 seconds, you will need to start manually"); - } + controller.Stop(); + controller.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(60)); - controller.Start(); - }); + if (controller.Status != ServiceControllerStatus.Stopped) + { + throw new Exception("The service did not stop within 60 seconds, you will need to start manually"); + } - await Refresh(RefreshData.Status); + controller.Start(); + }); + } } } public async Task Stop() { - if (controller.Status == ServiceControllerStatus.Running || controller.Status == ServiceControllerStatus.Paused) + using (var controller = new ServiceController(Name, MachineName)) { - await Task.Run(() => controller.Stop()); - await Refresh(RefreshData.Status); + if (controller.Status == ServiceControllerStatus.Running || controller.Status == ServiceControllerStatus.Paused) + { + await Task.Run(() => controller.Stop()); + } } } public async Task Pause() { - if (controller.Status == ServiceControllerStatus.Running) + using (var controller = new ServiceController(Name, MachineName)) { - if (controller.CanPauseAndContinue) - { - await Task.Run(() => controller.Pause()); - await Refresh(RefreshData.Status); - } - else + if (controller.Status == ServiceControllerStatus.Running) { - throw new Exception("Cannot pause this service"); + if (controller.CanPauseAndContinue) + { + await Task.Run(() => controller.Pause()); + } + else + { + throw new Exception("Cannot pause this service"); + } } } } public async Task Delete() { - if (controller.Status == ServiceControllerStatus.Running) + using (var controller = new ServiceController(Name, MachineName)) { - await Task.Run(() => controller.Stop()); + // TODO: log bug. This needs to be disabled for remote machines since the process is only executed locally. + if (controller.Status == ServiceControllerStatus.Running) + { + await Task.Run(() => controller.Stop()); + } + await Task.Run(() => Process.Start("sc.exe", "delete \"" + ServiceName + "\"")); } - await Task.Run(() => Process.Start("sc.exe", "delete \"" + ServiceName + "\"")); } public async Task SetStartupType(ServiceStartMode newType) { - await Task.Run(() => controller.SetStartupType(newType)); - await Refresh(RefreshData.Startup); + using (var controller = new ServiceController(Name, MachineName)) + { + await Task.Run(() => controller.SetStartupType(newType)); + } } public async Task OpenServiceInExplorer() { - await Task.Run(() => + using (var controller = new ServiceController(Name, MachineName)) { - var path = controller.GetExecutablePath(); - Process.Start("explorer.exe", $"/select, \"{path.FullName}\""); - }); + await Task.Run(() => + { + var path = controller.GetExecutablePath(); + Process.Start("explorer.exe", $"/select, \"{path.FullName}\""); + }); + } } public async Task GetAssemblyInfo() { - return await Task.Run(() => + using (var controller = new ServiceController(Name, MachineName)) { - var path = controller.GetExecutablePath(); - try - { - var assembly = Assembly.LoadFrom(path.FullName); - return BuildAssemblyInfoText(assembly); - } - catch (Exception) + return await Task.Run(() => { + var path = controller.GetExecutablePath(); try { - var versionInfo = FileVersionInfo.GetVersionInfo(path.FullName); - return BuildAssemblyInfoText(versionInfo); + var assembly = Assembly.LoadFrom(path.FullName); + return BuildAssemblyInfoText(assembly); } catch (Exception) { - throw new Exception("Unable to find property values"); + try + { + var versionInfo = FileVersionInfo.GetVersionInfo(path.FullName); + return BuildAssemblyInfoText(versionInfo); + } + catch (Exception) + { + throw new Exception("Unable to find property values"); + } } - } - }); + }); + } } private string BuildAssemblyInfoText(Assembly assembly) @@ -181,115 +214,87 @@ public enum RefreshData Startup, LogOnAs, } + private Image GetIcon(string status) + { + switch (status.ToLower()) + { + case "running": + return Properties.Resources.Running_State_Running; + case "stopped": + return Properties.Resources.Running_State_Stopped; + case "startpending": + return Properties.Resources.Running_State_StartPending; + case "stoppending": + return Properties.Resources.Running_State_StopPending; + case "paused": + return Properties.Resources.Running_State_Paused; + default: + return Properties.Resources.Running_State_Unknown; + } + } - public async Task Refresh(params RefreshData[] refreshData) + internal void UpdateFromWmi(ManagementBaseObject targetInstance) { + var changedEvents = new List(); + try { - var changed = await Task.Run(() => + var name = targetInstance["DisplayName"]?.ToString(); + if (Name != name) { - var changedEvents = new List(); - - try - { - controller.Refresh(); - - if (refreshData.Contains(RefreshData.DisplayName)) - { - if (Name != controller.DisplayName) - { - Name = controller.DisplayName; - changedEvents.Add("Name"); - } - } - - if (refreshData.Contains(RefreshData.ServiceName)) - { - if (ServiceName != controller.ServiceName) - { - ServiceName = controller.ServiceName; - changedEvents.Add("ServiceName"); - } - } - - if (refreshData.Contains(RefreshData.Description)) - { - var description = controller.GetDescription(); - if (Description != description) - { - Description = description; - changedEvents.Add("Description"); - } - } - - if (refreshData.Contains(RefreshData.Status)) - { - var statusText = controller.Status.ToString(); - if (Status != statusText) - { - Status = controller.Status.ToString(); - StatusIcon = GetIcon(Status); - changedEvents.Add("Status"); - changedEvents.Add("StatusIcon"); - } - } + Name = name; + changedEvents.Add("Name"); + } - if (refreshData.Contains(RefreshData.Startup)) - { - var startup = controller.GetStartupType(); - if (StartupType != startup) - { - StartupType = startup; - changedEvents.Add("StartupType"); - } - } + var serviceName = targetInstance["Name"]?.ToString(); + if (ServiceName != serviceName) + { + ServiceName = serviceName; + changedEvents.Add("ServiceName"); + } - if (refreshData.Contains(RefreshData.LogOnAs)) - { - var logOnAs = controller.GetLogOnAs(); - if (LogOnAs != logOnAs) - { - LogOnAs = logOnAs; - changedEvents.Add("LogOnAs"); - } - } - } - catch (Exception) - { + var description = targetInstance["Description"]?.ToString(); + if (Description != description) + { + Description = description; + changedEvents.Add("Description"); + } - //Ignored - } + var status = targetInstance["State"].ToString(); + if (Status != status) + { + Status = status; + StatusIcon = GetIcon(Status); + changedEvents.Add("Status"); + changedEvents.Add("StatusIcon"); + } - return changedEvents; - }); + var startupType = targetInstance["StartMode"].ToString(); + if (StartupType != startupType) + { + StartupType = startupType; + changedEvents.Add("StartupType"); + } - foreach (var item in changed) + var logOnAs = targetInstance["StartName"]?.ToString(); + if (string.IsNullOrWhiteSpace(logOnAs) || logOnAs.Equals(LOCAL_SYSTEM_ACCOUNT_NAME, StringComparison.OrdinalIgnoreCase)) + { + logOnAs = LOCAL_SYSTEM_ACCOUNT_NAME; + } + if (LogOnAs != logOnAs) { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(item)); + LogOnAs = logOnAs; + changedEvents.Add("LogOnAs"); } } catch (Exception) { //Ignored } - } - private Image GetIcon(string status) - { - switch (status.ToLower()) + foreach (var item in changedEvents) { - case "running": - return Properties.Resources.Running_State_Running; - case "stopped": - return Properties.Resources.Running_State_Stopped; - case "startpending": - return Properties.Resources.Running_State_StartPending; - case "stoppending": - return Properties.Resources.Running_State_StopPending; - case "paused": - return Properties.Resources.Running_State_Paused; - default: - return Properties.Resources.Running_State_Unknown; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(item)); } } } From 349b9bc451d9a8e402b23d3c60ea82dfe089d788 Mon Sep 17 00:00:00 2001 From: Chris Blyth Date: Tue, 8 Jun 2021 09:00:48 +0100 Subject: [PATCH 2/5] Bumping version --- src/Deploy/ServiceBouncer.nuspec | 2 +- src/ServiceBouncer/Properties/AssemblyInfo.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Deploy/ServiceBouncer.nuspec b/src/Deploy/ServiceBouncer.nuspec index 2ff253c..36b9d11 100644 --- a/src/Deploy/ServiceBouncer.nuspec +++ b/src/Deploy/ServiceBouncer.nuspec @@ -2,7 +2,7 @@ ServiceBouncer - 1.2.10 + 1.3.0 ServiceBouncer ServiceBouncer false diff --git a/src/ServiceBouncer/Properties/AssemblyInfo.cs b/src/ServiceBouncer/Properties/AssemblyInfo.cs index 6f12510..48dd34c 100644 --- a/src/ServiceBouncer/Properties/AssemblyInfo.cs +++ b/src/ServiceBouncer/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.2.10.0")] -[assembly: AssemblyFileVersion("1.2.10.0")] +[assembly: AssemblyVersion("1.3.0.0")] +[assembly: AssemblyFileVersion("1.3.0.0")] From c4f4b9c38157e873b963d76b89918d3e025f8ca7 Mon Sep 17 00:00:00 2001 From: Chris Blyth Date: Tue, 8 Jun 2021 09:50:13 +0100 Subject: [PATCH 3/5] Updates to the pull request --- ...indingList`1.cs => SortableBindingList.cs} | 35 +-- .../Extensions/AssemblyExtensions.cs | 20 -- .../Extensions/ServiceControllerExtensions.cs | 1 - src/ServiceBouncer/FrameworkChecker.cs | 2 +- src/ServiceBouncer/InstallationForm.cs | 24 +- .../InstallationForm.designer.cs | 31 +- src/ServiceBouncer/MainForm.Designer.cs | 101 +++---- src/ServiceBouncer/MainForm.cs | 118 ++++---- src/ServiceBouncer/Program.cs | 4 +- .../Properties/Resources.Designer.cs | 267 +++++++++++------- .../Properties/Settings.Designer.cs | 12 +- src/ServiceBouncer/RunAs.cs | 166 +++++++---- src/ServiceBouncer/ServiceBouncer.csproj | 3 +- src/ServiceBouncer/ServiceViewModel.cs | 23 +- 14 files changed, 437 insertions(+), 370 deletions(-) rename src/ServiceBouncer/ComponentModel/{SortableBindingList`1.cs => SortableBindingList.cs} (74%) delete mode 100644 src/ServiceBouncer/Extensions/AssemblyExtensions.cs diff --git a/src/ServiceBouncer/ComponentModel/SortableBindingList`1.cs b/src/ServiceBouncer/ComponentModel/SortableBindingList.cs similarity index 74% rename from src/ServiceBouncer/ComponentModel/SortableBindingList`1.cs rename to src/ServiceBouncer/ComponentModel/SortableBindingList.cs index 579975b..814eabc 100644 --- a/src/ServiceBouncer/ComponentModel/SortableBindingList`1.cs +++ b/src/ServiceBouncer/ComponentModel/SortableBindingList.cs @@ -9,35 +9,16 @@ public class SortableBindingList : BindingList where T : class private bool isSorted; private ListSortDirection sortDirection = ListSortDirection.Ascending; private PropertyDescriptor sortProperty; - - public SortableBindingList() - { - } - + public SortableBindingList(IList list) : base(list) { } - protected override bool SupportsSortingCore - { - get { return true; } - } - - protected override bool IsSortedCore - { - get { return isSorted; } - } - - protected override ListSortDirection SortDirectionCore - { - get { return sortDirection; } - } - - protected override PropertyDescriptor SortPropertyCore - { - get { return sortProperty; } - } + protected override bool SupportsSortingCore => true; + protected override bool IsSortedCore => isSorted; + protected override ListSortDirection SortDirectionCore => sortDirection; + protected override PropertyDescriptor SortPropertyCore => sortProperty; protected override void RemoveSortCore() { @@ -51,8 +32,7 @@ protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection sortProperty = prop; sortDirection = direction; - var list = Items as List; - if (list == null) + if (!(Items is List list)) { return; } @@ -90,8 +70,7 @@ private int OnComparison(T x, T y) return 1; } - var value = xValue as IComparable; - if (value != null) + if (xValue is IComparable value) { return value.CompareTo(yValue); } diff --git a/src/ServiceBouncer/Extensions/AssemblyExtensions.cs b/src/ServiceBouncer/Extensions/AssemblyExtensions.cs deleted file mode 100644 index 40bf31c..0000000 --- a/src/ServiceBouncer/Extensions/AssemblyExtensions.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Reflection; - -namespace ServiceBouncer.Extensions -{ - public static class AssemblyExtensions - { - public static T GetCustomAttributeOrNull(this Assembly assembly) where T : Attribute - { - try - { - return assembly.GetCustomAttribute(); - } - catch (Exception) - { - return null; - } - } - } -} \ No newline at end of file diff --git a/src/ServiceBouncer/Extensions/ServiceControllerExtensions.cs b/src/ServiceBouncer/Extensions/ServiceControllerExtensions.cs index e6080a0..87b5f87 100644 --- a/src/ServiceBouncer/Extensions/ServiceControllerExtensions.cs +++ b/src/ServiceBouncer/Extensions/ServiceControllerExtensions.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Management; using System.ServiceProcess; diff --git a/src/ServiceBouncer/FrameworkChecker.cs b/src/ServiceBouncer/FrameworkChecker.cs index 0145dec..be56ff8 100644 --- a/src/ServiceBouncer/FrameworkChecker.cs +++ b/src/ServiceBouncer/FrameworkChecker.cs @@ -32,7 +32,7 @@ public static void CheckFrameworkValid() else { var releaseKey = Convert.ToInt32(ndpKey.GetValue("Release")); - if (releaseKey < FrameworkChecker.MinReleaseKey) + if (releaseKey < MinReleaseKey) { validFramework = false; } diff --git a/src/ServiceBouncer/InstallationForm.cs b/src/ServiceBouncer/InstallationForm.cs index d52b8e3..8e8a4a9 100644 --- a/src/ServiceBouncer/InstallationForm.cs +++ b/src/ServiceBouncer/InstallationForm.cs @@ -8,7 +8,7 @@ namespace ServiceBouncer { public partial class InstallationForm : Form { - private bool m_installationInProgress; + private bool mInstallationInProgress; public InstallationForm() { @@ -48,13 +48,13 @@ private void btnSelectService_Click(object sender, EventArgs e) private async void btnInstall_Click(object sender, EventArgs e) { - if (m_installationInProgress) + if (mInstallationInProgress) { MessageBox.Show("One installation is in progress. Please wait until completion.", "One installation is in progress"); return; } - m_installationInProgress = true; + mInstallationInProgress = true; Enabled = false; Refresh(); @@ -73,9 +73,11 @@ private async void btnInstall_Click(object sender, EventArgs e) case "Automatic": startMode = "auto"; break; + case "Manual": startMode = "demand"; break; + default: startMode = "disabled"; break; @@ -96,11 +98,13 @@ await Task.Run(() => { using (var installationProcess = Process.Start(startInfo)) { - installationProcess.OutputDataReceived += InstallationProcess_OutputDataReceived; - installationProcess.BeginOutputReadLine(); - installationProcess.WaitForExit(); + if (installationProcess != null) + { + installationProcess.OutputDataReceived += InstallationProcess_OutputDataReceived; + installationProcess.BeginOutputReadLine(); + installationProcess.WaitForExit(); + } } - }); } catch (Exception ex) @@ -113,7 +117,7 @@ await Task.Run(() => MessageBox.Show(ex.Message, "An error occurred during installation", MessageBoxButtons.OK, MessageBoxIcon.Error); } - m_installationInProgress = false; + mInstallationInProgress = false; Enabled = true; Refresh(); btnInstall.Text = "Install"; @@ -124,7 +128,9 @@ private void InstallationProcess_OutputDataReceived(object sender, DataReceivedE lblProcessResult.Invoke(new MethodInvoker(() => { if (string.IsNullOrEmpty(e.Data)) + { return; + } lblProcessResult.Text += e.Data; lblProcessResult.ForeColor = lblProcessResult.Text.IndexOf("failed", StringComparison.OrdinalIgnoreCase) > -1 ? Color.Red : Color.Green; @@ -134,7 +140,7 @@ private void InstallationProcess_OutputDataReceived(object sender, DataReceivedE private void InstallationForm_FormClosing(object sender, FormClosingEventArgs e) { - if (m_installationInProgress) + if (mInstallationInProgress) { MessageBox.Show("One installation is in progress. Please wait until completion.", "One installation is in progress"); e.Cancel = true; diff --git a/src/ServiceBouncer/InstallationForm.designer.cs b/src/ServiceBouncer/InstallationForm.designer.cs index 54cb9cd..cbf5b58 100644 --- a/src/ServiceBouncer/InstallationForm.designer.cs +++ b/src/ServiceBouncer/InstallationForm.designer.cs @@ -1,11 +1,14 @@ -namespace ServiceBouncer +using System.ComponentModel; +using System.Windows.Forms; + +namespace ServiceBouncer { partial class InstallationForm { /// /// Required designer variable. /// - private System.ComponentModel.IContainer components = null; + private IContainer components = null; /// /// Clean up any resources being used. @@ -181,17 +184,17 @@ private void InitializeComponent() #endregion - private System.Windows.Forms.OpenFileDialog installSvcFileSelectionDialog; - private System.Windows.Forms.TextBox txtBxServiceExePath; - private System.Windows.Forms.Button btnSelectService; - private System.Windows.Forms.Label label1; - private System.Windows.Forms.Label label2; - private System.Windows.Forms.TextBox txtBxServiceName; - private System.Windows.Forms.ComboBox cmbBxOptionStart; - private System.Windows.Forms.Label label3; - private System.Windows.Forms.Label label4; - private System.Windows.Forms.TextBox txtBxDisplayName; - private System.Windows.Forms.Button btnInstall; - private System.Windows.Forms.Label lblProcessResult; + private OpenFileDialog installSvcFileSelectionDialog; + private TextBox txtBxServiceExePath; + private Button btnSelectService; + private Label label1; + private Label label2; + private TextBox txtBxServiceName; + private ComboBox cmbBxOptionStart; + private Label label3; + private Label label4; + private TextBox txtBxDisplayName; + private Button btnInstall; + private Label lblProcessResult; } } \ No newline at end of file diff --git a/src/ServiceBouncer/MainForm.Designer.cs b/src/ServiceBouncer/MainForm.Designer.cs index 125ce16..ba21295 100644 --- a/src/ServiceBouncer/MainForm.Designer.cs +++ b/src/ServiceBouncer/MainForm.Designer.cs @@ -1,3 +1,6 @@ +using System.ComponentModel; +using System.Windows.Forms; + namespace ServiceBouncer { partial class MainForm @@ -5,7 +8,7 @@ partial class MainForm /// /// Required designer variable. /// - private System.ComponentModel.IContainer components = null; + private IContainer components = null; /// /// Clean up any resources being used. @@ -610,54 +613,54 @@ private void InitializeComponent() #endregion - private System.Windows.Forms.ToolStripContainer toolStripContainer; - private System.Windows.Forms.ToolStripButton toolStripStartButton; - private System.Windows.Forms.ToolStripButton toolStripStopButton; - private System.Windows.Forms.DataGridView dataGridView; - private System.Windows.Forms.BindingSource serviceViewModelBindingSource; - private System.Windows.Forms.ToolStripButton toolStripRestartButton; - private System.Windows.Forms.ToolStripTextBox toolStripFilterBox; - private System.Windows.Forms.ToolStripButton toolStripRefreshButton; - private System.Windows.Forms.ToolStripButton toolStripDeleteButton; - private System.Windows.Forms.ContextMenuStrip contextMenu; - private System.Windows.Forms.ToolStripMenuItem contextMenuStartItem; - private System.Windows.Forms.ToolStripMenuItem contextMenuStopItem; - private System.Windows.Forms.ToolStripMenuItem contextMenuRestartItem; - private System.Windows.Forms.ToolStripSeparator contextMenuSpacer2; - private System.Windows.Forms.ToolStripMenuItem contextMenuRefreshItem; - private System.Windows.Forms.ToolStripSeparator contextMenuSpacer1; - private System.Windows.Forms.ToolStripMenuItem contextMenuDeleteItem; - private System.Windows.Forms.ToolStripDropDownButton toolStripStartupTypeButton; - private System.Windows.Forms.ToolStripMenuItem toolStripStartupTypeAutomaticItem; - private System.Windows.Forms.ToolStripMenuItem toolStripStartupTypeManualItem; - private System.Windows.Forms.ToolStripMenuItem toolStripStartupTypeDisabledItem; - private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; - private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; - private System.Windows.Forms.ToolStripLabel toolStripFilterIcon; - private System.Windows.Forms.ToolStripButton toolStripPauseButton; - private System.Windows.Forms.ToolStripMenuItem contextMenuStartupTypeItem; - private System.Windows.Forms.ToolStripMenuItem contextStatupTypeAutomatic; - private System.Windows.Forms.ToolStripMenuItem contextStartupTypeManual; - private System.Windows.Forms.ToolStripMenuItem contextStartupTypeDisabled; - private System.Windows.Forms.ToolStrip toolStrip; - private System.Windows.Forms.ToolStripSeparator contextMenuSpacer3; - private System.Windows.Forms.ToolStripMenuItem contextMenuOpenLocation; - private System.Windows.Forms.ToolStripMenuItem contextMenuAssemblyInfo; - private System.Windows.Forms.ToolStripButton toolStripExplorerButton; - private System.Windows.Forms.ToolStripButton toolStripInfoButton; - private System.Windows.Forms.ToolStripButton toolStripInstallButton; - private System.Windows.Forms.ToolStripButton toolStripConnectButton; - private System.Windows.Forms.ToolStripTextBox toolStripConnectToTextBox; - private System.Windows.Forms.ToolStripSeparator toolStripSeparator3; - private System.Windows.Forms.DataGridViewImageColumn dataGridStatusIcon; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridName; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridDescription; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridStatus; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridStatupType; - private System.Windows.Forms.DataGridViewTextBoxColumn dataGridLogOnAs; - private System.Windows.Forms.StatusStrip statusStrip; - private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel; - private System.Windows.Forms.Timer appTerminationTimer; + private ToolStripContainer toolStripContainer; + private ToolStripButton toolStripStartButton; + private ToolStripButton toolStripStopButton; + private DataGridView dataGridView; + private BindingSource serviceViewModelBindingSource; + private ToolStripButton toolStripRestartButton; + private ToolStripTextBox toolStripFilterBox; + private ToolStripButton toolStripRefreshButton; + private ToolStripButton toolStripDeleteButton; + private ContextMenuStrip contextMenu; + private ToolStripMenuItem contextMenuStartItem; + private ToolStripMenuItem contextMenuStopItem; + private ToolStripMenuItem contextMenuRestartItem; + private ToolStripSeparator contextMenuSpacer2; + private ToolStripMenuItem contextMenuRefreshItem; + private ToolStripSeparator contextMenuSpacer1; + private ToolStripMenuItem contextMenuDeleteItem; + private ToolStripDropDownButton toolStripStartupTypeButton; + private ToolStripMenuItem toolStripStartupTypeAutomaticItem; + private ToolStripMenuItem toolStripStartupTypeManualItem; + private ToolStripMenuItem toolStripStartupTypeDisabledItem; + private ToolStripSeparator toolStripSeparator1; + private ToolStripSeparator toolStripSeparator2; + private ToolStripLabel toolStripFilterIcon; + private ToolStripButton toolStripPauseButton; + private ToolStripMenuItem contextMenuStartupTypeItem; + private ToolStripMenuItem contextStatupTypeAutomatic; + private ToolStripMenuItem contextStartupTypeManual; + private ToolStripMenuItem contextStartupTypeDisabled; + private ToolStrip toolStrip; + private ToolStripSeparator contextMenuSpacer3; + private ToolStripMenuItem contextMenuOpenLocation; + private ToolStripMenuItem contextMenuAssemblyInfo; + private ToolStripButton toolStripExplorerButton; + private ToolStripButton toolStripInfoButton; + private ToolStripButton toolStripInstallButton; + private ToolStripButton toolStripConnectButton; + private ToolStripTextBox toolStripConnectToTextBox; + private ToolStripSeparator toolStripSeparator3; + private DataGridViewImageColumn dataGridStatusIcon; + private DataGridViewTextBoxColumn dataGridName; + private DataGridViewTextBoxColumn dataGridDescription; + private DataGridViewTextBoxColumn dataGridStatus; + private DataGridViewTextBoxColumn dataGridStatupType; + private DataGridViewTextBoxColumn dataGridLogOnAs; + private StatusStrip statusStrip; + private ToolStripStatusLabel toolStripStatusLabel; + private Timer appTerminationTimer; } } diff --git a/src/ServiceBouncer/MainForm.cs b/src/ServiceBouncer/MainForm.cs index dbc32d8..6485bbe 100644 --- a/src/ServiceBouncer/MainForm.cs +++ b/src/ServiceBouncer/MainForm.cs @@ -1,16 +1,17 @@ using CredentialManagement; +using Microsoft.Win32; using ServiceBouncer.ComponentModel; +using ServiceBouncer.Properties; using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Linq; +using System.Management; using System.ServiceProcess; -using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using DialogResult = System.Windows.Forms.DialogResult; -using System.Management; namespace ServiceBouncer { @@ -18,24 +19,22 @@ public partial class MainForm : Form { private readonly List services; private string machineHostname; - private int backgroundRefreshSeconds; private DateTime? machineLockedTime; private DateTime? appDeactivatedTime; - private bool IsActive => machineLockedTime == null || appDeactivatedTime == null; // WMI Events private ManagementEventWatcher modificationEventWatcher; + private ManagementEventWatcher creationEventWatcher; private ManagementEventWatcher deletionEventWatcher; public MainForm(string machine) { InitializeComponent(); - backgroundRefreshSeconds = 1; machineHostname = machine; toolStripConnectToTextBox.Text = machineHostname; services = new List(); - Microsoft.Win32.SystemEvents.SessionSwitch += SessionSwitch; // not sure what to do with this after converting to WMI events. probably good to do something. perhaps stop listening and reload services on unlock? + SystemEvents.SessionSwitch += SessionSwitch; } private void AppTerminationTimerTick(object sender, EventArgs e) @@ -52,13 +51,13 @@ private void AppTerminationTimerTick(object sender, EventArgs e) } // PC Locked - private void SessionSwitch(object sender, Microsoft.Win32.SessionSwitchEventArgs e) + private void SessionSwitch(object sender, SessionSwitchEventArgs e) { - if (e.Reason == Microsoft.Win32.SessionSwitchReason.SessionLock || e.Reason == Microsoft.Win32.SessionSwitchReason.RemoteDisconnect) + if (e.Reason == SessionSwitchReason.SessionLock || e.Reason == SessionSwitchReason.RemoteDisconnect) { machineLockedTime = DateTime.Now; } - else if (e.Reason == Microsoft.Win32.SessionSwitchReason.SessionUnlock || e.Reason == Microsoft.Win32.SessionSwitchReason.RemoteConnect) + else if (e.Reason == SessionSwitchReason.SessionUnlock || e.Reason == SessionSwitchReason.RemoteConnect) { machineLockedTime = null; } @@ -79,15 +78,11 @@ await PerformAction(async () => private void FormActivated(object sender, EventArgs e) { appDeactivatedTime = null; - SetTitle(); - SetConnectedStatusBar(); } private void FormDeactivated(object sender, EventArgs e) { appDeactivatedTime = DateTime.Now; - SetTitle(); - SetConnectedStatusBar(); } private async void RefreshClicked(object sender, EventArgs e) @@ -125,11 +120,15 @@ private async void DeleteClicked(object sender, EventArgs e) await PerformOperationWithCheck(s => { if (s.Count > 1) + { return MessageBox.Show($@"You have selected {s.Count} services(s) to delete, are you sure you want to delete them all?", @"Confirm delete", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) == DialogResult.Yes; + } var service = s.FirstOrDefault(); if (service != null) + { return MessageBox.Show($@"Are you sure you want to delete the '{service.Name}'", @"Confirm delete", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) == DialogResult.Yes; + } return false; }, @@ -222,7 +221,7 @@ private async Task Reload() { try { - ManagementObjectCollection win32_Services = null; + ManagementObjectCollection win32Services = null; await Task.Run(() => { @@ -230,13 +229,12 @@ await Task.Run(() => if (!string.IsNullOrEmpty(machineHostname) && machineHostname != Environment.MachineName) { - ConnectionOptions options = new ConnectionOptions(); - options.Impersonation = System.Management.ImpersonationLevel.Impersonate; + var options = new ConnectionOptions { Impersonation = ImpersonationLevel.Impersonate }; - ManagementScope scope = new ManagementScope("\\\\" + machineHostname + "\\root\\cimv2", options); + var scope = new ManagementScope("\\\\" + machineHostname + "\\root\\cimv2", options); scope.Connect(); - ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_Service"); + var query = new ObjectQuery("SELECT * FROM Win32_Service"); searcher = new ManagementObjectSearcher(scope, query); } else @@ -244,30 +242,27 @@ await Task.Run(() => searcher = new ManagementObjectSearcher("SELECT * FROM Win32_Service"); } - win32_Services = searcher.Get(); + win32Services = searcher.Get(); modificationEventWatcher?.Dispose(); - modificationEventWatcher = new ManagementEventWatcher(searcher.Scope, - new EventQuery("SELECT * FROM __InstanceModificationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_Service'")); + modificationEventWatcher = new ManagementEventWatcher(searcher.Scope, new EventQuery("SELECT * FROM __InstanceModificationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_Service'")); modificationEventWatcher.EventArrived += ModificationEventWatcher_EventArrived; modificationEventWatcher.Start(); creationEventWatcher?.Dispose(); - creationEventWatcher = new ManagementEventWatcher(searcher.Scope, - new EventQuery("SELECT * FROM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_Service'")); + creationEventWatcher = new ManagementEventWatcher(searcher.Scope, new EventQuery("SELECT * FROM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_Service'")); creationEventWatcher.EventArrived += CreationEventWatcher_EventArrived; creationEventWatcher.Start(); deletionEventWatcher?.Dispose(); - deletionEventWatcher = new ManagementEventWatcher(searcher.Scope, - new EventQuery("SELECT * FROM __InstanceDeletionEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_Service'")); - deletionEventWatcher.EventArrived += DeletionEventWatcher_EventArrived; ; + deletionEventWatcher = new ManagementEventWatcher(searcher.Scope, new EventQuery("SELECT * FROM __InstanceDeletionEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_Service'")); + deletionEventWatcher.EventArrived += DeletionEventWatcher_EventArrived; deletionEventWatcher.Start(); }); services.Clear(); - foreach (var model in win32_Services) + foreach (var model in win32Services) { services.Add(new ServiceViewModel(machineHostname, model)); } @@ -308,7 +303,8 @@ private void DeletionEventWatcher_EventArrived(object sender, EventArrivedEventA var serviceName = targetInstance["Name"].ToString(); services.RemoveAll(x => x.ServiceName == serviceName); - this.Invoke(new MethodInvoker(delegate { + Invoke(new MethodInvoker(delegate + { PopulateFilteredDataview(); SetTitle(); })); @@ -320,7 +316,8 @@ private void CreationEventWatcher_EventArrived(object sender, EventArrivedEventA services.Add(new ServiceViewModel(machineHostname, targetInstance)); - this.Invoke(new MethodInvoker(delegate { + Invoke(new MethodInvoker(delegate + { PopulateFilteredDataview(); SetTitle(); })); @@ -328,16 +325,15 @@ private void CreationEventWatcher_EventArrived(object sender, EventArrivedEventA private void ModificationEventWatcher_EventArrived(object sender, EventArrivedEventArgs e) { - var previousInstance = (ManagementBaseObject)e.NewEvent["PreviousInstance"]; var targetInstance = (ManagementBaseObject)e.NewEvent["TargetInstance"]; var serviceName = targetInstance["Name"].ToString(); var modifiedService = services.Find(x => x.ServiceName == serviceName); - if (modifiedService == null) - return; - modifiedService.UpdateFromWmi(targetInstance); + modifiedService?.UpdateFromWmi(targetInstance); + + Invoke(new MethodInvoker(SetTitle)); } private void StartNewProcess(BaseCredentialsPrompt promptResult) @@ -356,7 +352,7 @@ private void StartNewProcess(BaseCredentialsPrompt promptResult) domain = null; } - var commandName = $"{Process.GetCurrentProcess().MainModule.FileName} --machine={machineHostname}"; + var commandName = $"{Process.GetCurrentProcess().MainModule?.FileName} --machine={machineHostname}"; RunAs.StartProcess(username, domain, promptResult.Password, RunAs.LogonFlags.NetworkCredentialsOnly, null, commandName, RunAs.CreationFlags.NewProcessGroup, null); Application.Exit(); @@ -379,7 +375,10 @@ private void PopulateFilteredDataview() { var sortColumn = dataGridView.SortedColumn; var sortOrder = ListSortDirection.Ascending; - if (dataGridView.SortOrder == SortOrder.Descending) sortOrder = ListSortDirection.Descending; + if (dataGridView.SortOrder == SortOrder.Descending) + { + sortOrder = ListSortDirection.Descending; + } var searchTerm = toolStripFilterBox.Text; if (!string.IsNullOrWhiteSpace(searchTerm)) @@ -414,11 +413,9 @@ private async Task Connect() toolStripConnectButton.Text = @"Disconnect"; toolStripConnectButton.ToolTipText = @"Disconnect"; toolStripConnectButton.Tag = @"Connected"; - toolStripConnectButton.Image = Properties.Resources.Disconnect; + toolStripConnectButton.Image = Resources.Disconnect; - backgroundRefreshSeconds = EnvHelper.IsLocalMachine(machineHostname) ? 1 : 30; - - SetConnectedStatusBar(); + toolStripStatusLabel.Text = $@"Connected to {machineHostname}."; foreach (ToolStripItem toolStripItem in toolStrip.Items) { @@ -434,7 +431,7 @@ private void Disconnect() toolStripConnectButton.Text = @"Connect"; toolStripConnectButton.ToolTipText = @"Connect"; toolStripConnectButton.Tag = @"Disconnected"; - toolStripConnectButton.Image = Properties.Resources.Connect; + toolStripConnectButton.Image = Resources.Connect; toolStripStatusLabel.Text = @"Disconnected"; services.Clear(); PopulateFilteredDataview(); @@ -450,7 +447,7 @@ private void Disconnect() private void SetTitle() { - if (IsActive && services.Any()) + if (services.Any()) { var titles = services.GroupBy(s => s.Status).Select(s => (string.IsNullOrWhiteSpace(s.Key) ? "Unknown" : s.Key) + ": " + s.Count()); Text = $@"Service Bouncer - Total: {services.Count}, {string.Join(", ", titles)}"; @@ -461,20 +458,10 @@ private void SetTitle() } } - private void SetConnectedStatusBar() - { - toolStripStatusLabel.Text = $@"Connected to {machineHostname}."; - } - private async Task PerformOperationWithCheck(Func, bool> check, Func actionToPerform) { var selectedServices = dataGridView.SelectedRows.OfType().Select(g => g.DataBoundItem).OfType().ToList(); - await PerformOperation(check, actionToPerform, selectedServices, true); - } - - private async Task PerformBackgroundOperationWithCheck(Func, bool> check, Func actionToPerform) - { - await PerformOperation(check, actionToPerform, services.ToList(), false); + await PerformOperation(check, actionToPerform, selectedServices); } private async Task PerformOperation(Func actionToPerform) @@ -482,12 +469,7 @@ private async Task PerformOperation(Func actionToPerform await PerformOperationWithCheck(i => true, actionToPerform); } - private async Task PerformBackgroundOperation(Func actionToPerform) - { - await PerformBackgroundOperationWithCheck(i => true, actionToPerform); - } - - private async Task PerformOperation(Func, bool> check, Func actionToPerform, IReadOnlyCollection servicesToAction, bool disableToolstrip) + private async Task PerformOperation(Func, bool> check, Func actionToPerform, IReadOnlyCollection servicesToAction) { if (check(servicesToAction)) { @@ -512,29 +494,25 @@ async Task WrappedFunction(ServiceViewModel model) } await Task.WhenAll(tasks); - }, disableToolstrip); + }); } } - private async Task PerformAction(Func actionToPerform, bool disableToolstrip = true) + private async Task PerformAction(Func actionToPerform) { - if (disableToolstrip) + foreach (ToolStripItem toolStripItem in toolStrip.Items) { - foreach (ToolStripItem toolStripItem in toolStrip.Items) - { - toolStripItem.Enabled = false; - } + toolStripItem.Enabled = false; } await actionToPerform(); - if (disableToolstrip) + foreach (ToolStripItem toolStripItem in toolStrip.Items) { - foreach (ToolStripItem toolStripItem in toolStrip.Items) - { - toolStripItem.Enabled = true; - } + toolStripItem.Enabled = true; } + + toolStripDeleteButton.Enabled = machineHostname == Environment.MachineName; } } } diff --git a/src/ServiceBouncer/Program.cs b/src/ServiceBouncer/Program.cs index 5147025..914a9a2 100644 --- a/src/ServiceBouncer/Program.cs +++ b/src/ServiceBouncer/Program.cs @@ -17,13 +17,13 @@ static void Main(string[] commandLine) Application.ThreadException += (sender, args) => MessageBox.Show(args.Exception.Message, @"Unhandled error", MessageBoxButtons.OK); Parser.Default.ParseArguments(commandLine) - .WithParsed((options) => + .WithParsed(options => { var machineName = options.Machine; if (string.IsNullOrWhiteSpace(machineName)) machineName = Environment.MachineName; Application.Run(new MainForm(machineName)); }) - .WithNotParsed((error) => + .WithNotParsed(error => { Application.Run(new MainForm(Environment.MachineName)); }); diff --git a/src/ServiceBouncer/Properties/Resources.Designer.cs b/src/ServiceBouncer/Properties/Resources.Designer.cs index a33104b..06b69fb 100644 --- a/src/ServiceBouncer/Properties/Resources.Designer.cs +++ b/src/ServiceBouncer/Properties/Resources.Designer.cs @@ -8,10 +8,17 @@ // //------------------------------------------------------------------------------ -namespace ServiceBouncer.Properties { - using System; - - +using System.CodeDom.Compiler; +using System.ComponentModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; +using System.Globalization; +using System.Resources; +using System.Runtime.CompilerServices; + +namespace ServiceBouncer.Properties +{ /// /// A strongly-typed resource class, for looking up localized strings, etc. /// @@ -19,244 +26,292 @@ namespace ServiceBouncer.Properties { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { + [GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [DebuggerNonUserCode()] + [CompilerGenerated()] + internal class Resources + { + + private static ResourceManager resourceMan; + + private static CultureInfo resourceCulture; + + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { } - + /// /// Returns the cached ResourceManager instance used by this class. /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ServiceBouncer.Properties.Resources", typeof(Resources).Assembly); + [EditorBrowsable(EditorBrowsableState.Advanced)] + internal static ResourceManager ResourceManager + { + get + { + if (ReferenceEquals(resourceMan, null)) + { + ResourceManager temp = new ResourceManager("ServiceBouncer.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; } } - + /// /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { + [EditorBrowsable(EditorBrowsableState.Advanced)] + internal static CultureInfo Culture + { + get + { return resourceCulture; } - set { + set + { resourceCulture = value; } } - + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap AppIcon { - get { + internal static Bitmap AppIcon + { + get + { object obj = ResourceManager.GetObject("AppIcon", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); + return ((Bitmap)(obj)); } } - + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap Browse { - get { + internal static Bitmap Browse + { + get + { object obj = ResourceManager.GetObject("Browse", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); + return ((Bitmap)(obj)); } } - + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap Connect { - get { + internal static Bitmap Connect + { + get + { object obj = ResourceManager.GetObject("Connect", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); + return ((Bitmap)(obj)); } } - + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap Delete { - get { + internal static Bitmap Delete + { + get + { object obj = ResourceManager.GetObject("Delete", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); + return ((Bitmap)(obj)); } } - + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap Disconnect { - get { + internal static Bitmap Disconnect + { + get + { object obj = ResourceManager.GetObject("Disconnect", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); + return ((Bitmap)(obj)); } } - + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap Filter { - get { + internal static Bitmap Filter + { + get + { object obj = ResourceManager.GetObject("Filter", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); + return ((Bitmap)(obj)); } } - + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap Info { - get { + internal static Bitmap Info + { + get + { object obj = ResourceManager.GetObject("Info", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); + return ((Bitmap)(obj)); } } - + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap Install { - get { + internal static Bitmap Install + { + get + { object obj = ResourceManager.GetObject("Install", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); + return ((Bitmap)(obj)); } } - + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap Pause { - get { + internal static Bitmap Pause + { + get + { object obj = ResourceManager.GetObject("Pause", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); + return ((Bitmap)(obj)); } } - + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap Refresh { - get { + internal static Bitmap Refresh + { + get + { object obj = ResourceManager.GetObject("Refresh", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); + return ((Bitmap)(obj)); } } - + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap Restart { - get { + internal static Bitmap Restart + { + get + { object obj = ResourceManager.GetObject("Restart", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); + return ((Bitmap)(obj)); } } - + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap Running_State_Paused { - get { + internal static Bitmap Running_State_Paused + { + get + { object obj = ResourceManager.GetObject("Running_State_Paused", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); + return ((Bitmap)(obj)); } } - + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap Running_State_Running { - get { + internal static Bitmap Running_State_Running + { + get + { object obj = ResourceManager.GetObject("Running_State_Running", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); + return ((Bitmap)(obj)); } } - + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap Running_State_StartPending { - get { + internal static Bitmap Running_State_StartPending + { + get + { object obj = ResourceManager.GetObject("Running_State_StartPending", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); + return ((Bitmap)(obj)); } } - + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap Running_State_Stopped { - get { + internal static Bitmap Running_State_Stopped + { + get + { object obj = ResourceManager.GetObject("Running_State_Stopped", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); + return ((Bitmap)(obj)); } } - + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap Running_State_StopPending { - get { + internal static Bitmap Running_State_StopPending + { + get + { object obj = ResourceManager.GetObject("Running_State_StopPending", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); + return ((Bitmap)(obj)); } } - + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap Running_State_Unknown { - get { + internal static Bitmap Running_State_Unknown + { + get + { object obj = ResourceManager.GetObject("Running_State_Unknown", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); + return ((Bitmap)(obj)); } } - + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap Start { - get { + internal static Bitmap Start + { + get + { object obj = ResourceManager.GetObject("Start", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); + return ((Bitmap)(obj)); } } - + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap Startup { - get { + internal static Bitmap Startup + { + get + { object obj = ResourceManager.GetObject("Startup", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); + return ((Bitmap)(obj)); } } - + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// - internal static System.Drawing.Bitmap Stop { - get { + internal static Bitmap Stop + { + get + { object obj = ResourceManager.GetObject("Stop", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); + return ((Bitmap)(obj)); } } } diff --git a/src/ServiceBouncer/Properties/Settings.Designer.cs b/src/ServiceBouncer/Properties/Settings.Designer.cs index 9dae427..d74cc80 100644 --- a/src/ServiceBouncer/Properties/Settings.Designer.cs +++ b/src/ServiceBouncer/Properties/Settings.Designer.cs @@ -8,14 +8,18 @@ // //------------------------------------------------------------------------------ +using System.CodeDom.Compiler; +using System.Configuration; +using System.Runtime.CompilerServices; + namespace ServiceBouncer.Properties { - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.4.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + [CompilerGenerated()] + [GeneratedCode("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.4.0.0")] + internal sealed partial class Settings : ApplicationSettingsBase { - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + private static Settings defaultInstance = ((Settings)(Synchronized(new Settings()))); public static Settings Default { get { diff --git a/src/ServiceBouncer/RunAs.cs b/src/ServiceBouncer/RunAs.cs index e104176..9808594 100644 --- a/src/ServiceBouncer/RunAs.cs +++ b/src/ServiceBouncer/RunAs.cs @@ -1,4 +1,6 @@ using System; +using System.ComponentModel; +using System.Diagnostics; using System.Runtime.InteropServices; using System.Security.Permissions; using System.Text; @@ -30,73 +32,90 @@ public struct StartUpInfo /// Size of the structure, in bytes. /// public int cb; + /// /// Reserved. Set this member to NULL before passing the structure to CreateProcess. /// [MarshalAs(UnmanagedType.LPTStr)] public string lpReserved; + /// /// Pointer to a null-terminated string that specifies either the name of the desktop, or the name of both the desktop and window station for this process. A backslash in the string indicates that the string includes both the desktop and window station names. /// [MarshalAs(UnmanagedType.LPTStr)] public string lpDesktop; + /// /// For console processes, this is the title displayed in the title bar if a new console window is created. If NULL, the name of the executable file is used as the window title instead. This parameter must be NULL for GUI or console processes that do not create a new console window. /// [MarshalAs(UnmanagedType.LPTStr)] public string lpTitle; + /// /// The x offset of the upper left corner of a window if a new window is created, in pixels. /// public int dwX; + /// /// The y offset of the upper left corner of a window if a new window is created, in pixels. /// public int dwY; + /// /// The width of the window if a new window is created, in pixels. /// public int dwXSize; + /// /// The height of the window if a new window is created, in pixels. /// public int dwYSize; + /// /// If a new console window is created in a console process, this member specifies the screen buffer width, in character columns. /// public int dwXCountChars; + /// /// If a new console window is created in a console process, this member specifies the screen buffer height, in character rows. /// public int dwYCountChars; + /// /// The initial text and background colors if a new console window is created in a console application. /// public int dwFillAttribute; + /// /// Bit field that determines whether certain StartUpInfo members are used when the process creates a window. /// public int dwFlags; + /// /// This member can be any of the SW_ constants defined in Winuser.h. /// public short wShowWindow; + /// /// Reserved for use by the C Runtime; must be zero. /// public short cbReserved2; + /// /// Reserved for use by the C Runtime; must be null. /// public IntPtr lpReserved2; + /// /// A handle to be used as the standard input handle for the process. /// public IntPtr hStdInput; + /// /// A handle to be used as the standard output handle for the process. /// public IntPtr hStdOutput; + /// /// A handle to be used as the standard error handle for the process. /// @@ -113,14 +132,17 @@ public struct ProcessInformation /// Handle to the newly created process. The handle is used to specify the process in all functions that perform operations on the process object. /// public IntPtr hProcess; + /// /// Handle to the primary thread of the newly created process. The handle is used to specify the thread in all functions that perform operations on the thread object. /// public IntPtr hThread; + /// /// Value that can be used to identify a process. The value is valid from the time the process is created until the time the process is terminated. /// public int dwProcessId; + /// /// Value that can be used to identify a thread. The value is valid from the time the thread is created until the time the thread is terminated. /// @@ -137,30 +159,37 @@ public enum FillAttributes /// Background color is intensified. /// BackgroundIntensity = 128, + /// /// Background color contains red. /// BackgroundRed = 64, + /// /// Background color contains green. /// BackgroundGreen = 32, + /// /// Background color contains blue. /// BackgroundBlue = 16, + /// /// Text color is intensified. /// ForegroundIntensity = 8, + /// /// Text color contains red. /// ForegroundRed = 4, + /// /// Text color contains green. /// ForegroundGreen = 2, + /// /// Text color contains blue. /// @@ -177,6 +206,7 @@ public enum LogonFlags /// Log on, then load the user's profile in the HKEY_USERS registry key. The function returns after the profile has been loaded. Loading the profile can be time-consuming, so it is best to use this value only if you must access the information in the HKEY_CURRENT_USER registry key. /// WithProfile = 1, + /// /// Log on, but use the specified credentials on the network only. The new process uses the same token as the caller, but the system creates a new logon session within LSA, and the process uses the specified credentials as the default credentials. /// @@ -193,22 +223,27 @@ public enum CreationFlags /// The primary thread of the new process is created in a suspended state, and does not run until the ResumeThread function is called. /// Suspended = 0x00000004, + /// /// The new process has a new console, instead of inheriting the parent's console. /// NewConsole = 0x00000010, + /// /// The new process is the root process of a new process group. /// NewProcessGroup = 0x00000200, + /// /// This flag is only valid starting a 16-bit Windows-based application. If set, the new process runs in a private Virtual DOS Machine (VDM). By default, all 16-bit Windows-based applications run in a single, shared VDM. /// SeperateWOWVDM = 0x00000800, + /// /// Indicates the format of the lpEnvironment parameter. If this flag is set, the environment block pointed to by lpEnvironment uses Unicode characters. /// UnicodeEnvironment = 0x00000400, + /// /// The new process does not inherit the error mode of the calling process. /// @@ -225,22 +260,27 @@ public enum PriorityFlags /// Process with no special scheduling needs. /// NormalPriority = 0x00000020, + /// /// Process whose threads run only when the system is idle and are preempted by the threads of any process running in a higher priority class. An example is a screen saver. The idle priority class is inherited by child processes. /// IdlePriority = 0x00000040, + /// /// Process that performs time-critical tasks that must be executed immediately for it to run correctly. The threads of a high-priority class process preempt the threads of normal or idle priority class processes. /// HighPriority = 0x00000080, + /// /// Process that has the highest possible priority. The threads of a real-time priority class process preempt the threads of all other processes, including operating system processes performing important tasks. /// RealTimePriority = 0x00000100, + /// /// Process that has priority above idle but below normal processes. /// BelowNormalPriority = 0x00004000, + /// /// Process that has priority above normal but below high processes. /// @@ -257,54 +297,67 @@ public enum StartUpInfoFlags : uint /// If this value is not specified, the wShowWindow member is ignored. /// UseShowWindow = 0x0000001, + /// /// If this value is not specified, the dwXSize and dwYSize members are ignored. /// UseSize = 0x00000002, + /// /// If this value is not specified, the dwX and dwY members are ignored. /// UsePosition = 0x00000004, + /// /// If this value is not specified, the dwXCountChars and dwYCountChars members are ignored. /// UseCountChars = 0x00000008, + /// /// If this value is not specified, the dwFillAttribute member is ignored. /// UseFillAttribute = 0x00000010, + /// /// Indicates that the process should be run in full-screen mode, rather than in windowed mode. /// RunFullScreen = 0x00000020, + /// /// Indicates that the cursor is in feedback mode after CreateProcess is called. The system turns the feedback cursor off after the first call to GetMessage. /// ForceOnFeedback = 0x00000040, + /// /// Indicates that the feedback cursor is forced off while the process is starting. The Normal Select cursor is displayed. /// ForceOffFeedback = 0x00000080, + /// /// Sets the standard input, standard output, and standard error handles for the process to the handles specified in the hStdInput, hStdOutput, and hStdError members of the StartUpInfo structure. If this value is not specified, the hStdInput, hStdOutput, and hStdError members of the STARTUPINFO structure are ignored. /// UseStandardHandles = 0x00000100, + /// /// When this flag is specified, the hStdInput member is to be used as the hotkey value instead of the standard-input pipe. /// UseHotKey = 0x00000200, + /// /// When this flag is specified, the StartUpInfo's hStdOutput member is used to specify a handle to a monitor, on which to start the new process. This monitor handle can be obtained by any of the multiple-monitor display functions (i.e. EnumDisplayMonitors, MonitorFromPoint, MonitorFromWindow, etc...). /// UseMonitor = 0x00000400, + /// /// Use the HICON specified in the hStdOutput member (incompatible with UseMonitor). /// UseIcon = 0x00000400, + /// /// Program was started through a shortcut. The lpTitle contains the shortcut path. /// TitleShortcut = 0x00000800, + /// /// The process starts with normal priority. After the first call to GetMessage, the priority is lowered to idle. /// @@ -391,27 +444,25 @@ public enum StartUpInfoFlags : uint /// Throws a System.ComponentModel.Win32Exception containing the last error if the /// call failed. /// - public static System.Diagnostics.Process StartProcess(string userName, + public static Process StartProcess(string userName, string domain, string password, LogonFlags logonFlags, string applicationName, string commandLine, CreationFlags creationFlags, IntPtr environment, string currentDirectory, ref StartUpInfo startupInfo, out ProcessInformation processInfo) { - StringBuilder cl = new StringBuilder(commandLine.Length); + var cl = new StringBuilder(commandLine.Length); cl.Append(commandLine); - bool retval = CreateProcessWithLogonW(userName, domain, password, + var retval = CreateProcessWithLogonW(userName, domain, password, (int)logonFlags, applicationName, cl, (uint)creationFlags, environment, currentDirectory, ref startupInfo, out processInfo); if (!retval) { - throw new System.ComponentModel.Win32Exception(); - } - else - { - CloseHandle(processInfo.hProcess); - CloseHandle(processInfo.hThread); - return System.Diagnostics.Process.GetProcessById(processInfo.dwProcessId); + throw new Win32Exception(); } + + CloseHandle(processInfo.hProcess); + CloseHandle(processInfo.hThread); + return Process.GetProcessById(processInfo.dwProcessId); } /// @@ -473,12 +524,11 @@ public static System.Diagnostics.Process StartProcess(string userName, /// Throws a System.ComponentModel.Win32Exception containing the last error if the /// call failed. /// - public static System.Diagnostics.Process StartProcess(string userName, + public static Process StartProcess(string userName, string domain, string password, string applicationName, string commandLine, string currentDirectory) { - ProcessInformation processInfo; - StartUpInfo startupInfo = new StartUpInfo(); + var startupInfo = new StartUpInfo(); startupInfo.cb = Marshal.SizeOf(startupInfo); startupInfo.lpTitle = null; startupInfo.dwFlags = (int)StartUpInfoFlags.UseCountChars; @@ -486,7 +536,7 @@ public static System.Diagnostics.Process StartProcess(string userName, return StartProcess(userName, domain, password, LogonFlags.WithProfile, applicationName, commandLine, CreationFlags.NewConsole, IntPtr.Zero, - currentDirectory, ref startupInfo, out processInfo); + currentDirectory, ref startupInfo, out ProcessInformation processInfo); } /// @@ -528,11 +578,10 @@ public static System.Diagnostics.Process StartProcess(string userName, /// Throws a System.ComponentModel.Win32Exception containing the last error if the /// call failed. /// - public static System.Diagnostics.Process StartProcess(string userName, + public static Process StartProcess(string userName, string domain, string password, string commandLine) { - ProcessInformation processInfo; - StartUpInfo startupInfo = new StartUpInfo(); + var startupInfo = new StartUpInfo(); startupInfo.cb = Marshal.SizeOf(startupInfo); startupInfo.lpTitle = null; startupInfo.dwFlags = (int)StartUpInfoFlags.UseCountChars; @@ -540,7 +589,7 @@ public static System.Diagnostics.Process StartProcess(string userName, return StartProcess(userName, domain, password, LogonFlags.WithProfile, null, commandLine, CreationFlags.NewConsole, IntPtr.Zero, - null, ref startupInfo, out processInfo); + null, ref startupInfo, out ProcessInformation processInfo); } /// @@ -610,12 +659,11 @@ public static System.Diagnostics.Process StartProcess(string userName, /// Throws a System.ComponentModel.Win32Exception containing the last error if the /// call failed. /// - public static System.Diagnostics.Process StartProcess(string userName, + public static Process StartProcess(string userName, string domain, string password, LogonFlags logonFlags, string applicationName, string commandLine, CreationFlags creationFlags, string currentDirectory) { - ProcessInformation processInfo; - StartUpInfo startupInfo = new StartUpInfo(); + var startupInfo = new StartUpInfo(); startupInfo.cb = Marshal.SizeOf(startupInfo); startupInfo.lpTitle = null; startupInfo.dwFlags = (int)StartUpInfoFlags.UseCountChars; ; @@ -623,11 +671,11 @@ public static System.Diagnostics.Process StartProcess(string userName, return StartProcess(userName, domain, password, logonFlags, applicationName, commandLine, creationFlags, IntPtr.Zero, currentDirectory, ref startupInfo, - out processInfo); + out ProcessInformation processInfo); } - private string _userName; + /// /// This is the name of the user account to log on to. If you use the UPN format, /// user@domain, the Domain parameter must be NULL. The user account must have @@ -635,10 +683,12 @@ public static System.Diagnostics.Process StartProcess(string userName, /// public string UserName { - get { return _userName; } - set { _userName = value; } + get => _userName; + set => _userName = value; } + private string _domain; + /// /// Specifies the name of the domain or server whose account database contains the /// user account. If this parameter is NULL, the user name must be specified in @@ -646,28 +696,34 @@ public string UserName /// public string Domain { - get { return _domain; } - set { _domain = value; } + get => _domain; + set => _domain = value; } + private string _password; + /// /// Specifies the clear-text password for the user account. /// public string Password { - get { return _password; } - set { _password = value; } + get => _password; + set => _password = value; } + private LogonFlags _logonFlags; + /// /// Logon option. This parameter can be zero or one value from the LogonFlags enum. /// public LogonFlags LogonFlagsInstance { - get { return _logonFlags; } - set { _logonFlags = value; } + get => _logonFlags; + set => _logonFlags = value; } + private string _applicationName; + /// /// Specifies the module to execute. The specified module can be a Windows-based /// application. It can be some other type of module (for example, MS-DOS or OS/2) @@ -685,10 +741,12 @@ public LogonFlags LogonFlagsInstance /// public string ApplicationName { - get { return _applicationName; } - set { _applicationName = value; } + get => _applicationName; + set => _applicationName = value; } + private string _commandLine; + /// /// Specifies the command line to execute. The maximum length of this string is /// 32,000 characters. The commandline parameter can be NULL. In that case, the @@ -701,10 +759,12 @@ public string ApplicationName /// public string CommandLine { - get { return _commandLine; } - set { _commandLine = value; } + get => _commandLine; + set => _commandLine = value; } + private CreationFlags _creationFlags; + /// /// Use CreationFlags and PriorityFlags enums. Controls how the process is created. /// Also controls the new process's priority class, which is used to determine the @@ -712,10 +772,12 @@ public string CommandLine /// public CreationFlags CreationFlagsInstance { - get { return _creationFlags; } - set { _creationFlags = value; } + get => _creationFlags; + set => _creationFlags = value; } + private string _currentDirectory; + /// /// Specifies the full path to the current directory for the process. The string /// can also specify a UNC path. If this parameter is NULL, the new process will @@ -723,30 +785,36 @@ public CreationFlags CreationFlagsInstance /// public string CurrentDirectory { - get { return _currentDirectory; } - set { _currentDirectory = value; } + get => _currentDirectory; + set => _currentDirectory = value; } + private StartUpInfo _startupInfo; + /// /// Specifies the window station, desktop, standard handles, and appearance of the /// main window for the new process. /// public StartUpInfo StartupInfo { - get { return _startupInfo; } - set { _startupInfo = value; } + get => _startupInfo; + set => _startupInfo = value; } + private ProcessInformation _processInfo; + /// /// ProcessInformation structure that receives identification information for the /// new process, including a handle to the process. /// public ProcessInformation ProcessInfo { - get { return _processInfo; } - set { _processInfo = value; } + get => _processInfo; + set => _processInfo = value; } + private IntPtr _environment; + /// /// Pointer to an environment block for the new process. If this parameter is NULL, /// the new process uses the environment of the specified user instead of the @@ -754,9 +822,10 @@ public ProcessInformation ProcessInfo /// public IntPtr Environment { - get { return _environment; } - set { _environment = value; } + get => _environment; + set => _environment = value; } + /// /// Initializes default values for all parameters. /// @@ -878,7 +947,7 @@ public RunAs() _startupInfo.cb = Marshal.SizeOf(_startupInfo); _startupInfo.dwFlags = (int)StartUpInfoFlags.UseCountChars; _startupInfo.dwYCountChars = 50; - using (System.Diagnostics.Process cp = System.Diagnostics.Process.GetCurrentProcess()) + using (var cp = Process.GetCurrentProcess()) { _applicationName = cp.StartInfo.FileName; _startupInfo.lpTitle = cp.MainWindowTitle; @@ -886,6 +955,7 @@ public RunAs() _processInfo = new ProcessInformation(); _environment = IntPtr.Zero; } + /// /// Creates a new process and its primary thread. The new process then runs the /// specified executable file in the security context of the specified @@ -902,11 +972,11 @@ public RunAs() /// Throws a System.ComponentModel.Win32Exception containing the last error if the /// call failed. /// - public System.Diagnostics.Process StartProcess() + public Process StartProcess() { return StartProcess(UserName, Domain, Password, LogonFlagsInstance, ApplicationName, CommandLine, CreationFlagsInstance, Environment, CurrentDirectory, ref _startupInfo, out _processInfo); } } -} \ No newline at end of file +} diff --git a/src/ServiceBouncer/ServiceBouncer.csproj b/src/ServiceBouncer/ServiceBouncer.csproj index b3912e9..b7f8b2a 100644 --- a/src/ServiceBouncer/ServiceBouncer.csproj +++ b/src/ServiceBouncer/ServiceBouncer.csproj @@ -132,8 +132,7 @@ - - + Form diff --git a/src/ServiceBouncer/ServiceViewModel.cs b/src/ServiceBouncer/ServiceViewModel.cs index e22cc1c..c8fd1dc 100644 --- a/src/ServiceBouncer/ServiceViewModel.cs +++ b/src/ServiceBouncer/ServiceViewModel.cs @@ -1,4 +1,5 @@ using ServiceBouncer.Extensions; +using ServiceBouncer.Properties; using System; using System.Collections.Generic; using System.ComponentModel; @@ -114,7 +115,6 @@ public async Task Delete() { using (var controller = new ServiceController(Name, MachineName)) { - // TODO: log bug. This needs to be disabled for remote machines since the process is only executed locally. if (controller.Status == ServiceControllerStatus.Running) { await Task.Run(() => controller.Stop()); @@ -205,31 +205,22 @@ private string BuildAssemblyInfoText(FileVersionInfo fileVersion) return output.ToString(); } - public enum RefreshData - { - DisplayName, - ServiceName, - Description, - Status, - Startup, - LogOnAs, - } private Image GetIcon(string status) { switch (status.ToLower()) { case "running": - return Properties.Resources.Running_State_Running; + return Resources.Running_State_Running; case "stopped": - return Properties.Resources.Running_State_Stopped; + return Resources.Running_State_Stopped; case "startpending": - return Properties.Resources.Running_State_StartPending; + return Resources.Running_State_StartPending; case "stoppending": - return Properties.Resources.Running_State_StopPending; + return Resources.Running_State_StopPending; case "paused": - return Properties.Resources.Running_State_Paused; + return Resources.Running_State_Paused; default: - return Properties.Resources.Running_State_Unknown; + return Resources.Running_State_Unknown; } } From b37f2e5c48ef5851e07ea4f51359b9db75c52dc5 Mon Sep 17 00:00:00 2001 From: Chris Blyth Date: Tue, 8 Jun 2021 09:57:15 +0100 Subject: [PATCH 4/5] update dependencies --- .config/dotnet-tools.json | 4 +- paket.lock | 651 ++++++++------------------------------ 2 files changed, 136 insertions(+), 519 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 63246f1..b9fdb39 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,13 +3,13 @@ "isRoot": true, "tools": { "fake-cli": { - "version": "5.19.0", + "version": "5.20.4", "commands": [ "fake" ] }, "paket": { - "version": "5.241.2", + "version": "5.257.0", "commands": [ "paket" ] diff --git a/paket.lock b/paket.lock index 794e0f3..db27e04 100644 --- a/paket.lock +++ b/paket.lock @@ -2,542 +2,159 @@ REDIRECTS: ON RESTRICTION: || (== net45) (== net461) (== net471) (== net48) NUGET remote: https://www.nuget.org/api/v2 - CommandLineParser (2.6) + CommandLineParser (2.8) CredentialManagement (1.0.2) GROUP BuildTools RESTRICTION: == netstandard2.0 NUGET remote: https://www.nuget.org/api/v2 - BlackFox.VsWhere (1.0) + BlackFox.VsWhere (1.1) FSharp.Core (>= 4.2.3) - Fake.Core.CommandLineParsing (5.19) - FParsec (>= 1.0.3) - FSharp.Core (>= 4.7) - Fake.Core.Context (5.19) - FSharp.Core (>= 4.7) - Fake.Core.Environment (5.19) - FSharp.Core (>= 4.7) - Fake.Core.FakeVar (5.19) - Fake.Core.Context (>= 5.19) - FSharp.Core (>= 4.7) - Fake.Core.Process (5.19) - Fake.Core.Environment (>= 5.19) - Fake.Core.FakeVar (>= 5.19) - Fake.Core.String (>= 5.19) - Fake.Core.Trace (>= 5.19) - Fake.IO.FileSystem (>= 5.19) - FSharp.Core (>= 4.7) - System.Diagnostics.Process (>= 4.3) - Fake.Core.String (5.19) - FSharp.Core (>= 4.7) - Fake.Core.Target (5.19) - Fake.Core.CommandLineParsing (>= 5.19) - Fake.Core.Context (>= 5.19) - Fake.Core.Environment (>= 5.19) - Fake.Core.FakeVar (>= 5.19) - Fake.Core.Process (>= 5.19) - Fake.Core.String (>= 5.19) - Fake.Core.Trace (>= 5.19) - FSharp.Control.Reactive (>= 4.2) - FSharp.Core (>= 4.7) - System.Reactive.Compatibility (>= 4.3.1) - Fake.Core.Trace (5.19) - Fake.Core.Environment (>= 5.19) - Fake.Core.FakeVar (>= 5.19) - FSharp.Core (>= 4.7) - Fake.DotNet.MSBuild (5.19) - BlackFox.VsWhere (>= 1.0) - Fake.Core.Environment (>= 5.19) - Fake.Core.Process (>= 5.19) - Fake.Core.String (>= 5.19) - Fake.Core.Trace (>= 5.19) - Fake.IO.FileSystem (>= 5.19) - FSharp.Core (>= 4.7) - MSBuild.StructuredLogger (>= 2.0.152) - Fake.IO.FileSystem (5.19) - Fake.Core.String (>= 5.19) - FSharp.Core (>= 4.7) - System.Diagnostics.FileVersionInfo (>= 4.3) - System.IO.FileSystem.Watcher (>= 4.3) - Fake.IO.Zip (5.19) - Fake.Core.String (>= 5.19) - Fake.IO.FileSystem (>= 5.19) - FSharp.Core (>= 4.7) - System.IO.Compression (>= 4.3) - System.IO.Compression.ZipFile (>= 4.3) - FParsec (1.0.3) - FSharp.Core (>= 4.2.3) - NETStandard.Library (>= 1.6.1) - FSharp.Control.Reactive (4.2) - FSharp.Core (>= 4.2.3) - System.Reactive (>= 4.0) - FSharp.Core (4.7) - Microsoft.Build (16.4) - Microsoft.Build.Framework (16.4) - System.Runtime.Serialization.Primitives (>= 4.1.1) - System.Threading.Thread (>= 4.0) - Microsoft.Build.Tasks.Core (16.4) - Microsoft.Build.Framework (>= 16.4) - Microsoft.Build.Utilities.Core (>= 16.4) + Microsoft.Win32.Registry (>= 4.7) + Fake.Core.CommandLineParsing (5.20.4) + FParsec (>= 1.1.1) + FSharp.Core (>= 4.7.2) + Fake.Core.Context (5.20.4) + FSharp.Core (>= 4.7.2) + Fake.Core.Environment (5.20.4) + FSharp.Core (>= 4.7.2) + Fake.Core.FakeVar (5.20.4) + Fake.Core.Context (>= 5.20.4) + FSharp.Core (>= 4.7.2) + Fake.Core.Process (5.20.4) + Fake.Core.Environment (>= 5.20.4) + Fake.Core.FakeVar (>= 5.20.4) + Fake.Core.String (>= 5.20.4) + Fake.Core.Trace (>= 5.20.4) + Fake.IO.FileSystem (>= 5.20.4) + FSharp.Core (>= 4.7.2) + System.Collections.Immutable (>= 1.7.1) + Fake.Core.String (5.20.4) + FSharp.Core (>= 4.7.2) + Fake.Core.Target (5.20.4) + Fake.Core.CommandLineParsing (>= 5.20.4) + Fake.Core.Context (>= 5.20.4) + Fake.Core.Environment (>= 5.20.4) + Fake.Core.FakeVar (>= 5.20.4) + Fake.Core.Process (>= 5.20.4) + Fake.Core.String (>= 5.20.4) + Fake.Core.Trace (>= 5.20.4) + FSharp.Control.Reactive (>= 4.4.2) + FSharp.Core (>= 4.7.2) + Fake.Core.Trace (5.20.4) + Fake.Core.Environment (>= 5.20.4) + Fake.Core.FakeVar (>= 5.20.4) + FSharp.Core (>= 4.7.2) + Fake.DotNet.MSBuild (5.20.4) + BlackFox.VsWhere (>= 1.1) + Fake.Core.Environment (>= 5.20.4) + Fake.Core.Process (>= 5.20.4) + Fake.Core.String (>= 5.20.4) + Fake.Core.Trace (>= 5.20.4) + Fake.IO.FileSystem (>= 5.20.4) + FSharp.Core (>= 4.7.2) + MSBuild.StructuredLogger (>= 2.1.176) + Fake.IO.FileSystem (5.20.4) + Fake.Core.String (>= 5.20.4) + FSharp.Core (>= 4.7.2) + Fake.IO.Zip (5.20.4) + Fake.Core.String (>= 5.20.4) + Fake.IO.FileSystem (>= 5.20.4) + FSharp.Core (>= 4.7.2) + FParsec (1.1.1) + FSharp.Core (>= 4.3.4) + FSharp.Control.Reactive (5.0.2) + FSharp.Core (>= 4.7.2) + System.Reactive (>= 5.0) + FSharp.Core (5.0.1) + Microsoft.Build (16.10) + Microsoft.Build.Framework (16.10) + System.Security.Permissions (>= 4.7) + Microsoft.Build.Tasks.Core (16.10) + Microsoft.Build.Framework (>= 16.10) + Microsoft.Build.Utilities.Core (>= 16.10) + Microsoft.NET.StringTools (>= 1.0) Microsoft.Win32.Registry (>= 4.3) System.CodeDom (>= 4.4) - System.Collections.Immutable (>= 1.5) - System.Linq.Parallel (>= 4.0.1) - System.Net.Http (>= 4.3.4) + System.Collections.Immutable (>= 5.0) System.Reflection.Metadata (>= 1.6) - System.Reflection.TypeExtensions (>= 4.1) System.Resources.Extensions (>= 4.6) - System.Resources.Writer (>= 4.0) + System.Security.Cryptography.Pkcs (>= 4.7) + System.Security.Cryptography.Xml (>= 4.7) + System.Security.Permissions (>= 4.7) System.Threading.Tasks.Dataflow (>= 4.9) - Microsoft.Build.Utilities.Core (16.4) - Microsoft.Build.Framework (>= 16.4) + Microsoft.Build.Utilities.Core (16.10) + Microsoft.Build.Framework (>= 16.10) + Microsoft.NET.StringTools (>= 1.0) Microsoft.Win32.Registry (>= 4.3) - System.Collections.Immutable (>= 1.5) + System.Collections.Immutable (>= 5.0) + System.Configuration.ConfigurationManager (>= 4.7) + System.Security.Permissions (>= 4.7) System.Text.Encoding.CodePages (>= 4.0.1) - Microsoft.NETCore.Platforms (3.1) - Microsoft.NETCore.Targets (3.1) - Microsoft.Win32.Primitives (4.3) - Microsoft.NETCore.Platforms (>= 1.1) - Microsoft.NETCore.Targets (>= 1.1) - System.Runtime (>= 4.3) - Microsoft.Win32.Registry (4.7) - System.Buffers (>= 4.5) - System.Memory (>= 4.5.3) - System.Security.AccessControl (>= 4.7) - System.Security.Principal.Windows (>= 4.7) - MSBuild.StructuredLogger (2.0.152) - Microsoft.Build (>= 15.8.166) - Microsoft.Build.Framework (>= 15.8.166) - Microsoft.Build.Tasks.Core (>= 15.8.166) - Microsoft.Build.Utilities.Core (>= 15.8.166) - NETStandard.Library (2.0.3) - Microsoft.NETCore.Platforms (>= 1.1) - NuGet.CommandLine (5.4) - runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) - runtime.debian.9-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) - runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) - runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) - runtime.fedora.27-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) - runtime.fedora.28-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) - runtime.native.System (4.3.1) - Microsoft.NETCore.Platforms (>= 1.1.1) - Microsoft.NETCore.Targets (>= 1.1.3) - runtime.native.System.IO.Compression (4.3.2) - Microsoft.NETCore.Platforms (>= 1.1.1) - Microsoft.NETCore.Targets (>= 1.1.3) - runtime.native.System.Net.Http (4.3.1) - Microsoft.NETCore.Platforms (>= 1.1.1) - Microsoft.NETCore.Targets (>= 1.1.3) - runtime.native.System.Security.Cryptography.Apple (4.3.1) - runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple (>= 4.3.1) - runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) - runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3) - runtime.debian.9-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3) - runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3) - runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3) - runtime.fedora.27-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3) - runtime.fedora.28-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3) - runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3) - runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3) - runtime.opensuse.42.3-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3) - runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3) - runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3) - runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3) - runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3) - runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3) - runtime.ubuntu.18.04-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3) - runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) - runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) - runtime.opensuse.42.3-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) - runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple (4.3.1) - runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) - runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) - runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) - runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) - runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) - runtime.ubuntu.18.04-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) - System.Buffers (4.5) - System.CodeDom (4.7) - System.Collections (4.3) - Microsoft.NETCore.Platforms (>= 1.1) - Microsoft.NETCore.Targets (>= 1.1) - System.Runtime (>= 4.3) - System.Collections.Concurrent (4.3) - System.Collections (>= 4.3) - System.Diagnostics.Debug (>= 4.3) - System.Diagnostics.Tracing (>= 4.3) - System.Globalization (>= 4.3) - System.Reflection (>= 4.3) - System.Resources.ResourceManager (>= 4.3) - System.Runtime (>= 4.3) - System.Runtime.Extensions (>= 4.3) - System.Threading (>= 4.3) - System.Threading.Tasks (>= 4.3) - System.Collections.Immutable (1.7) - System.Memory (>= 4.5.3) - System.Diagnostics.Debug (4.3) - Microsoft.NETCore.Platforms (>= 1.1) - Microsoft.NETCore.Targets (>= 1.1) - System.Runtime (>= 4.3) - System.Diagnostics.DiagnosticSource (4.7) - System.Memory (>= 4.5.3) - System.Diagnostics.FileVersionInfo (4.3) - Microsoft.NETCore.Platforms (>= 1.1) - System.Globalization (>= 4.3) - System.IO (>= 4.3) - System.IO.FileSystem (>= 4.3) - System.IO.FileSystem.Primitives (>= 4.3) - System.Reflection.Metadata (>= 1.4.1) - System.Runtime (>= 4.3) - System.Runtime.Extensions (>= 4.3) - System.Runtime.InteropServices (>= 4.3) - System.Diagnostics.Process (4.3) - Microsoft.NETCore.Platforms (>= 1.1) - Microsoft.Win32.Primitives (>= 4.3) - Microsoft.Win32.Registry (>= 4.3) - runtime.native.System (>= 4.3) - System.Collections (>= 4.3) - System.Diagnostics.Debug (>= 4.3) - System.Globalization (>= 4.3) - System.IO (>= 4.3) - System.IO.FileSystem (>= 4.3) - System.IO.FileSystem.Primitives (>= 4.3) - System.Resources.ResourceManager (>= 4.3) - System.Runtime (>= 4.3) - System.Runtime.Extensions (>= 4.3) - System.Runtime.Handles (>= 4.3) - System.Runtime.InteropServices (>= 4.3) - System.Text.Encoding (>= 4.3) - System.Text.Encoding.Extensions (>= 4.3) - System.Threading (>= 4.3) - System.Threading.Tasks (>= 4.3) - System.Threading.Thread (>= 4.3) - System.Threading.ThreadPool (>= 4.3) - System.Diagnostics.Tracing (4.3) - Microsoft.NETCore.Platforms (>= 1.1) - Microsoft.NETCore.Targets (>= 1.1) - System.Runtime (>= 4.3) - System.Globalization (4.3) - Microsoft.NETCore.Platforms (>= 1.1) - Microsoft.NETCore.Targets (>= 1.1) - System.Runtime (>= 4.3) - System.Globalization.Calendars (4.3) - Microsoft.NETCore.Platforms (>= 1.1) - Microsoft.NETCore.Targets (>= 1.1) - System.Globalization (>= 4.3) - System.Runtime (>= 4.3) - System.Globalization.Extensions (4.3) - Microsoft.NETCore.Platforms (>= 1.1) - System.Globalization (>= 4.3) - System.Resources.ResourceManager (>= 4.3) - System.Runtime (>= 4.3) - System.Runtime.Extensions (>= 4.3) - System.Runtime.InteropServices (>= 4.3) - System.IO (4.3) - Microsoft.NETCore.Platforms (>= 1.1) - Microsoft.NETCore.Targets (>= 1.1) - System.Runtime (>= 4.3) - System.Text.Encoding (>= 4.3) - System.Threading.Tasks (>= 4.3) - System.IO.Compression (4.3) - Microsoft.NETCore.Platforms (>= 1.1) - runtime.native.System (>= 4.3) - runtime.native.System.IO.Compression (>= 4.3) - System.Buffers (>= 4.3) - System.Collections (>= 4.3) - System.Diagnostics.Debug (>= 4.3) - System.IO (>= 4.3) - System.Resources.ResourceManager (>= 4.3) - System.Runtime (>= 4.3) - System.Runtime.Extensions (>= 4.3) - System.Runtime.Handles (>= 4.3) - System.Runtime.InteropServices (>= 4.3) - System.Text.Encoding (>= 4.3) - System.Threading (>= 4.3) - System.Threading.Tasks (>= 4.3) - System.IO.Compression.ZipFile (4.3) - System.Buffers (>= 4.3) - System.IO (>= 4.3) - System.IO.Compression (>= 4.3) - System.IO.FileSystem (>= 4.3) - System.IO.FileSystem.Primitives (>= 4.3) - System.Resources.ResourceManager (>= 4.3) - System.Runtime (>= 4.3) - System.Runtime.Extensions (>= 4.3) - System.Text.Encoding (>= 4.3) - System.IO.FileSystem (4.3) - Microsoft.NETCore.Platforms (>= 1.1) - Microsoft.NETCore.Targets (>= 1.1) - System.IO (>= 4.3) - System.IO.FileSystem.Primitives (>= 4.3) - System.Runtime (>= 4.3) - System.Runtime.Handles (>= 4.3) - System.Text.Encoding (>= 4.3) - System.Threading.Tasks (>= 4.3) - System.IO.FileSystem.Primitives (4.3) - System.Runtime (>= 4.3) - System.IO.FileSystem.Watcher (4.3) - Microsoft.NETCore.Platforms (>= 1.1) - Microsoft.Win32.Primitives (>= 4.3) - runtime.native.System (>= 4.3) - System.Collections (>= 4.3) - System.IO.FileSystem (>= 4.3) - System.IO.FileSystem.Primitives (>= 4.3) - System.Resources.ResourceManager (>= 4.3) - System.Runtime (>= 4.3) - System.Runtime.Extensions (>= 4.3) - System.Runtime.Handles (>= 4.3) - System.Runtime.InteropServices (>= 4.3) - System.Text.Encoding (>= 4.3) - System.Threading (>= 4.3) - System.Threading.Overlapped (>= 4.3) - System.Threading.Tasks (>= 4.3) - System.Threading.Thread (>= 4.3) - System.Linq (4.3) - System.Collections (>= 4.3) - System.Diagnostics.Debug (>= 4.3) - System.Resources.ResourceManager (>= 4.3) - System.Runtime (>= 4.3) - System.Runtime.Extensions (>= 4.3) - System.Linq.Parallel (4.3) - System.Collections (>= 4.3) - System.Collections.Concurrent (>= 4.3) - System.Diagnostics.Debug (>= 4.3) - System.Diagnostics.Tracing (>= 4.3) - System.Linq (>= 4.3) - System.Resources.ResourceManager (>= 4.3) - System.Runtime (>= 4.3) - System.Runtime.Extensions (>= 4.3) - System.Threading (>= 4.3) - System.Threading.Tasks (>= 4.3) - System.Memory (4.5.3) - System.Buffers (>= 4.4) + Microsoft.NET.StringTools (1.0) + System.Memory (>= 4.5.4) + System.Runtime.CompilerServices.Unsafe (>= 5.0) + Microsoft.NETCore.Platforms (5.0.2) + Microsoft.NETCore.Targets (5.0) + Microsoft.Win32.Registry (5.0) + System.Buffers (>= 4.5.1) + System.Memory (>= 4.5.4) + System.Security.AccessControl (>= 5.0) + System.Security.Principal.Windows (>= 5.0) + MSBuild.StructuredLogger (2.1.507) + Microsoft.Build (>= 16.4) + Microsoft.Build.Framework (>= 16.4) + Microsoft.Build.Tasks.Core (>= 16.4) + Microsoft.Build.Utilities.Core (>= 16.4) + NuGet.CommandLine (5.9.1) + System.Buffers (4.5.1) + System.CodeDom (5.0) + System.Collections.Immutable (5.0) + System.Memory (>= 4.5.4) + System.Configuration.ConfigurationManager (5.0) + System.Security.Cryptography.ProtectedData (>= 5.0) + System.Security.Permissions (>= 5.0) + System.Formats.Asn1 (5.0) + System.Buffers (>= 4.5.1) + System.Memory (>= 4.5.4) + System.Memory (4.5.4) + System.Buffers (>= 4.5.1) System.Numerics.Vectors (>= 4.4) - System.Runtime.CompilerServices.Unsafe (>= 4.5.2) - System.Net.Http (4.3.4) - Microsoft.NETCore.Platforms (>= 1.1.1) - runtime.native.System (>= 4.3) - runtime.native.System.Net.Http (>= 4.3) - runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.2) - System.Collections (>= 4.3) - System.Diagnostics.Debug (>= 4.3) - System.Diagnostics.DiagnosticSource (>= 4.3) - System.Diagnostics.Tracing (>= 4.3) - System.Globalization (>= 4.3) - System.Globalization.Extensions (>= 4.3) - System.IO (>= 4.3) - System.IO.FileSystem (>= 4.3) - System.Net.Primitives (>= 4.3) - System.Resources.ResourceManager (>= 4.3) - System.Runtime (>= 4.3) - System.Runtime.Extensions (>= 4.3) - System.Runtime.Handles (>= 4.3) - System.Runtime.InteropServices (>= 4.3) - System.Security.Cryptography.Algorithms (>= 4.3) - System.Security.Cryptography.Encoding (>= 4.3) - System.Security.Cryptography.OpenSsl (>= 4.3) - System.Security.Cryptography.Primitives (>= 4.3) - System.Security.Cryptography.X509Certificates (>= 4.3) - System.Text.Encoding (>= 4.3) - System.Threading (>= 4.3) - System.Threading.Tasks (>= 4.3) - System.Net.Primitives (4.3.1) - Microsoft.NETCore.Platforms (>= 1.1.1) - Microsoft.NETCore.Targets (>= 1.1.3) - System.Runtime (>= 4.3.1) - System.Runtime.Handles (>= 4.3) + System.Runtime.CompilerServices.Unsafe (>= 4.5.3) System.Numerics.Vectors (4.5) - System.Reactive (4.3.1) + System.Reactive (5.0) System.Runtime.InteropServices.WindowsRuntime (>= 4.3) - System.Threading.Tasks.Extensions (>= 4.5.3) - System.Reactive.Compatibility (4.3.1) - System.Reactive.Core (>= 4.3.1) - System.Reactive.Interfaces (>= 4.3.1) - System.Reactive.Linq (>= 4.3.1) - System.Reactive.PlatformServices (>= 4.3.1) - System.Reactive.Providers (>= 4.3.1) - System.Reactive.Core (4.3.1) - System.Reactive (>= 4.3.1) - System.Threading.Tasks.Extensions (>= 4.5.3) - System.Reactive.Interfaces (4.3.1) - System.Reactive (>= 4.3.1) - System.Threading.Tasks.Extensions (>= 4.5.3) - System.Reactive.Linq (4.3.1) - System.Reactive (>= 4.3.1) - System.Threading.Tasks.Extensions (>= 4.5.3) - System.Reactive.PlatformServices (4.3.1) - System.Reactive (>= 4.3.1) - System.Threading.Tasks.Extensions (>= 4.5.3) - System.Reactive.Providers (4.3.1) - System.Reactive (>= 4.3.1) - System.Threading.Tasks.Extensions (>= 4.5.3) - System.Reflection (4.3) - Microsoft.NETCore.Platforms (>= 1.1) - Microsoft.NETCore.Targets (>= 1.1) - System.IO (>= 4.3) - System.Reflection.Primitives (>= 4.3) - System.Runtime (>= 4.3) - System.Reflection.Metadata (1.8) - System.Collections.Immutable (>= 1.7) - System.Reflection.Primitives (4.3) - Microsoft.NETCore.Platforms (>= 1.1) - Microsoft.NETCore.Targets (>= 1.1) - System.Runtime (>= 4.3) - System.Reflection.TypeExtensions (4.7) - System.Resources.Extensions (4.7) - System.Memory (>= 4.5.3) - System.Resources.ResourceManager (4.3) - Microsoft.NETCore.Platforms (>= 1.1) - Microsoft.NETCore.Targets (>= 1.1) - System.Globalization (>= 4.3) - System.Reflection (>= 4.3) - System.Runtime (>= 4.3) - System.Resources.Writer (4.3) - System.Collections (>= 4.3) - System.IO (>= 4.3) - System.Resources.ResourceManager (>= 4.3) - System.Runtime (>= 4.3) - System.Runtime.Extensions (>= 4.3) - System.Text.Encoding (>= 4.3) + System.Threading.Tasks.Extensions (>= 4.5.4) + System.Reflection.Metadata (5.0) + System.Collections.Immutable (>= 5.0) + System.Resources.Extensions (5.0) + System.Memory (>= 4.5.4) System.Runtime (4.3.1) Microsoft.NETCore.Platforms (>= 1.1.1) Microsoft.NETCore.Targets (>= 1.1.3) - System.Runtime.CompilerServices.Unsafe (4.7) - System.Runtime.Extensions (4.3.1) - Microsoft.NETCore.Platforms (>= 1.1.1) - Microsoft.NETCore.Targets (>= 1.1.3) - System.Runtime (>= 4.3.1) - System.Runtime.Handles (4.3) - Microsoft.NETCore.Platforms (>= 1.1) - Microsoft.NETCore.Targets (>= 1.1) - System.Runtime (>= 4.3) - System.Runtime.InteropServices (4.3) - Microsoft.NETCore.Platforms (>= 1.1) - Microsoft.NETCore.Targets (>= 1.1) - System.Reflection (>= 4.3) - System.Reflection.Primitives (>= 4.3) - System.Runtime (>= 4.3) - System.Runtime.Handles (>= 4.3) + System.Runtime.CompilerServices.Unsafe (5.0) System.Runtime.InteropServices.WindowsRuntime (4.3) System.Runtime (>= 4.3) - System.Runtime.Numerics (4.3) - System.Globalization (>= 4.3) - System.Resources.ResourceManager (>= 4.3) - System.Runtime (>= 4.3) - System.Runtime.Extensions (>= 4.3) - System.Runtime.Serialization.Primitives (4.3) - System.Resources.ResourceManager (>= 4.3) - System.Runtime (>= 4.3) - System.Security.AccessControl (4.7) - System.Security.Principal.Windows (>= 4.7) - System.Security.Cryptography.Algorithms (4.3.1) - Microsoft.NETCore.Platforms (>= 1.1) - runtime.native.System.Security.Cryptography.Apple (>= 4.3.1) - runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.2) - System.Collections (>= 4.3) - System.IO (>= 4.3) - System.Resources.ResourceManager (>= 4.3) - System.Runtime (>= 4.3) - System.Runtime.Extensions (>= 4.3) - System.Runtime.Handles (>= 4.3) - System.Runtime.InteropServices (>= 4.3) - System.Runtime.Numerics (>= 4.3) - System.Security.Cryptography.Encoding (>= 4.3) - System.Security.Cryptography.Primitives (>= 4.3) - System.Text.Encoding (>= 4.3) - System.Security.Cryptography.Cng (4.7) - System.Security.Cryptography.Csp (4.3) - Microsoft.NETCore.Platforms (>= 1.1) - System.IO (>= 4.3) - System.Reflection (>= 4.3) - System.Resources.ResourceManager (>= 4.3) - System.Runtime (>= 4.3) - System.Runtime.Extensions (>= 4.3) - System.Runtime.Handles (>= 4.3) - System.Runtime.InteropServices (>= 4.3) - System.Security.Cryptography.Algorithms (>= 4.3) - System.Security.Cryptography.Encoding (>= 4.3) - System.Security.Cryptography.Primitives (>= 4.3) - System.Text.Encoding (>= 4.3) - System.Threading (>= 4.3) - System.Security.Cryptography.Encoding (4.3) - Microsoft.NETCore.Platforms (>= 1.1) - runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3) - System.Collections (>= 4.3) - System.Collections.Concurrent (>= 4.3) - System.Linq (>= 4.3) - System.Resources.ResourceManager (>= 4.3) - System.Runtime (>= 4.3) - System.Runtime.Extensions (>= 4.3) - System.Runtime.Handles (>= 4.3) - System.Runtime.InteropServices (>= 4.3) - System.Security.Cryptography.Primitives (>= 4.3) - System.Text.Encoding (>= 4.3) - System.Security.Cryptography.OpenSsl (4.7) - System.Security.Cryptography.Primitives (4.3) - System.Diagnostics.Debug (>= 4.3) - System.Globalization (>= 4.3) - System.IO (>= 4.3) - System.Resources.ResourceManager (>= 4.3) - System.Runtime (>= 4.3) - System.Threading (>= 4.3) - System.Threading.Tasks (>= 4.3) - System.Security.Cryptography.X509Certificates (4.3.2) - Microsoft.NETCore.Platforms (>= 1.1) - runtime.native.System (>= 4.3) - runtime.native.System.Net.Http (>= 4.3) - runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.2) - System.Collections (>= 4.3) - System.Diagnostics.Debug (>= 4.3) - System.Globalization (>= 4.3) - System.Globalization.Calendars (>= 4.3) - System.IO (>= 4.3) - System.IO.FileSystem (>= 4.3) - System.IO.FileSystem.Primitives (>= 4.3) - System.Resources.ResourceManager (>= 4.3) - System.Runtime (>= 4.3) - System.Runtime.Extensions (>= 4.3) - System.Runtime.Handles (>= 4.3) - System.Runtime.InteropServices (>= 4.3) - System.Runtime.Numerics (>= 4.3) - System.Security.Cryptography.Algorithms (>= 4.3) - System.Security.Cryptography.Cng (>= 4.3) - System.Security.Cryptography.Csp (>= 4.3) - System.Security.Cryptography.Encoding (>= 4.3) - System.Security.Cryptography.OpenSsl (>= 4.3) - System.Security.Cryptography.Primitives (>= 4.3) - System.Text.Encoding (>= 4.3) - System.Threading (>= 4.3) - System.Security.Principal.Windows (4.7) - System.Text.Encoding (4.3) - Microsoft.NETCore.Platforms (>= 1.1) - Microsoft.NETCore.Targets (>= 1.1) - System.Runtime (>= 4.3) - System.Text.Encoding.CodePages (4.7) - System.Runtime.CompilerServices.Unsafe (>= 4.7) - System.Text.Encoding.Extensions (4.3) - Microsoft.NETCore.Platforms (>= 1.1) - Microsoft.NETCore.Targets (>= 1.1) - System.Runtime (>= 4.3) - System.Text.Encoding (>= 4.3) - System.Threading (4.3) - System.Runtime (>= 4.3) - System.Threading.Tasks (>= 4.3) - System.Threading.Overlapped (4.3) - Microsoft.NETCore.Platforms (>= 1.1) - System.Resources.ResourceManager (>= 4.3) - System.Runtime (>= 4.3) - System.Runtime.Handles (>= 4.3) - System.Threading.Tasks (4.3) - Microsoft.NETCore.Platforms (>= 1.1) - Microsoft.NETCore.Targets (>= 1.1) - System.Runtime (>= 4.3) - System.Threading.Tasks.Dataflow (4.11) - System.Threading.Tasks.Extensions (4.5.3) - System.Runtime.CompilerServices.Unsafe (>= 4.5.2) - System.Threading.Thread (4.3) - System.Runtime (>= 4.3) - System.Threading.ThreadPool (4.3) - System.Runtime (>= 4.3) - System.Runtime.Handles (>= 4.3) + System.Security.AccessControl (5.0) + System.Security.Principal.Windows (>= 5.0) + System.Security.Cryptography.Cng (5.0) + System.Security.Cryptography.Pkcs (5.0.1) + System.Buffers (>= 4.5.1) + System.Formats.Asn1 (>= 5.0) + System.Memory (>= 4.5.4) + System.Security.Cryptography.Cng (>= 5.0) + System.Security.Cryptography.ProtectedData (5.0) + System.Memory (>= 4.5.4) + System.Security.Cryptography.Xml (5.0) + System.Memory (>= 4.5.4) + System.Security.Cryptography.Pkcs (>= 5.0) + System.Security.Permissions (>= 5.0) + System.Security.Permissions (5.0) + System.Security.AccessControl (>= 5.0) + System.Security.Principal.Windows (5.0) + System.Text.Encoding.CodePages (5.0) + System.Runtime.CompilerServices.Unsafe (>= 5.0) + System.Threading.Tasks.Dataflow (5.0) + System.Threading.Tasks.Extensions (4.5.4) + System.Runtime.CompilerServices.Unsafe (>= 4.5.3) From 7aad017bd032314b0d8059e06119551e04e58968 Mon Sep 17 00:00:00 2001 From: Chris Blyth Date: Tue, 8 Jun 2021 10:29:41 +0100 Subject: [PATCH 5/5] Ensure all updates are done on the right thread --- src/ServiceBouncer/MainForm.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/ServiceBouncer/MainForm.cs b/src/ServiceBouncer/MainForm.cs index 6485bbe..3417508 100644 --- a/src/ServiceBouncer/MainForm.cs +++ b/src/ServiceBouncer/MainForm.cs @@ -331,9 +331,11 @@ private void ModificationEventWatcher_EventArrived(object sender, EventArrivedEv var modifiedService = services.Find(x => x.ServiceName == serviceName); - modifiedService?.UpdateFromWmi(targetInstance); - - Invoke(new MethodInvoker(SetTitle)); + Invoke(new MethodInvoker(delegate + { + modifiedService?.UpdateFromWmi(targetInstance); + SetTitle(); + })); } private void StartNewProcess(BaseCredentialsPrompt promptResult)