From 678884d3c3bea3790389cbdb49a63cf0bf2dfac4 Mon Sep 17 00:00:00 2001 From: Jordan Date: Wed, 15 Dec 2021 11:33:50 -0800 Subject: [PATCH 1/4] Add MicrophoneProcessSensor --- UserInterface/Views/AddSensorDialog.axaml.cs | 43 +++--- documentation/Sensors.md | 6 +- .../InterProcessApi.cs | 9 +- .../ServiceContractModels.cs | 3 +- .../Data/ConfigurationService.cs | 5 +- .../Domain/Sensors/MicrophoneProcessSensor.cs | 130 ++++++++++++++++++ 6 files changed, 171 insertions(+), 25 deletions(-) create mode 100644 hass-workstation-service/Domain/Sensors/MicrophoneProcessSensor.cs diff --git a/UserInterface/Views/AddSensorDialog.axaml.cs b/UserInterface/Views/AddSensorDialog.axaml.cs index 9ab9bde..b75f2aa 100644 --- a/UserInterface/Views/AddSensorDialog.axaml.cs +++ b/UserInterface/Views/AddSensorDialog.axaml.cs @@ -102,7 +102,7 @@ namespace UserInterface.Views item.ShowWindowNameInput = false; item.UpdateInterval = 5; break; - + case AvailableSensors.DummySensor: item.Description = "This sensor spits out a random number every second. Useful for testing, maybe you'll find some other use for it."; item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/Sensors.md#dummysensor"; @@ -110,7 +110,7 @@ namespace UserInterface.Views item.ShowWindowNameInput = false; item.UpdateInterval = 1; break; - + case AvailableSensors.CPULoadSensor: item.Description = "This sensor checks the current CPU load. It averages the load on all logical cores every second and rounds the output to two decimals."; item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/Sensors.md#cpuloadsensor"; @@ -118,7 +118,7 @@ namespace UserInterface.Views item.ShowWindowNameInput = false; item.UpdateInterval = 5; break; - + case AvailableSensors.CurrentClockSpeedSensor: item.Description = "This sensor returns the BIOS configured baseclock for the processor."; item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/Sensors.md#currentclockspeedsensor"; @@ -126,7 +126,7 @@ namespace UserInterface.Views item.ShowWindowNameInput = false; item.UpdateInterval = 3600; break; - + case AvailableSensors.WMIQuerySensor: item.Description = "This advanced sensor executes a user defined WMI query and exposes the result. The query should return a single value."; item.MoreInfoLink = "https://github.com/sleevezipperhass-workstation-service/blob/master/documentation/WMIQuery.md#wmiquerysensor"; @@ -134,7 +134,7 @@ namespace UserInterface.Views item.ShowWindowNameInput = false; item.UpdateInterval = 10; break; - + case AvailableSensors.MemoryUsageSensor: item.Description = "This sensor calculates the percentage of used memory."; item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/Sensors.md#memoryusagesensorsensor"; @@ -142,7 +142,7 @@ namespace UserInterface.Views item.ShowWindowNameInput = false; item.UpdateInterval = 10; break; - + case AvailableSensors.ActiveWindowSensor: item.Description = "This sensor exposes the name of the currently active window."; item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/Sensors.md#activewindowsensor"; @@ -150,28 +150,35 @@ namespace UserInterface.Views item.ShowWindowNameInput = false; item.UpdateInterval = 5; break; - + case AvailableSensors.WebcamActiveSensor: item.Description = "This sensor shows if the webcam is currently being used."; item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/Sensors.md#webcamactivesensor"; item.ShowQueryInput = false; item.UpdateInterval = 10; break; - + case AvailableSensors.WebcamProcessSensor: item.Description = "This sensor shows which process is using the webcam."; item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/Sensors.md#webcamprocesssensor"; item.ShowQueryInput = false; item.UpdateInterval = 10; break; - + case AvailableSensors.MicrophoneActiveSensor: item.Description = "This sensor shows if the microphone is currently in use."; item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/Sensors.md#microphoneactivesensor"; item.ShowQueryInput = false; item.UpdateInterval = 10; break; - + + case AvailableSensors.MicrophoneProcessSensor: + item.Description = "This sensor shows which process is using the microphone."; + item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/Sensors.md#microphoneprocesssensor"; + item.ShowQueryInput = false; + item.UpdateInterval = 10; + break; + case AvailableSensors.NamedWindowSensor: item.Description = "This sensor returns true if a window was found with the name you search for. "; item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/Sensors.md#namedwindowsensor"; @@ -179,7 +186,7 @@ namespace UserInterface.Views item.ShowWindowNameInput = true; item.UpdateInterval = 5; break; - + case AvailableSensors.LastActiveSensor: item.Description = "This sensor returns the date/time that the workstation was last active."; item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/Sensors.md#lastactivesensor"; @@ -187,7 +194,7 @@ namespace UserInterface.Views item.ShowWindowNameInput = false; item.UpdateInterval = 5; break; - + case AvailableSensors.LastBootSensor: item.Description = "This sensor returns the date/time that Windows was last booted"; item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/Sensors.md#lastbootsensor"; @@ -195,7 +202,7 @@ namespace UserInterface.Views item.ShowWindowNameInput = false; item.UpdateInterval = 5; break; - + case AvailableSensors.SessionStateSensor: item.Description = "This sensor returns the state of the Windows session."; item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/Sensors.md#sessionstatesensor"; @@ -203,7 +210,7 @@ namespace UserInterface.Views item.ShowWindowNameInput = false; item.UpdateInterval = 5; break; - + case AvailableSensors.CurrentVolumeSensor: item.Description = "This sensor returns the volume of currently playing audio."; item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/Sensors.md#currentvolumesensor"; @@ -211,7 +218,7 @@ namespace UserInterface.Views item.ShowWindowNameInput = false; item.UpdateInterval = 5; break; - + case AvailableSensors.MasterVolumeSensor: item.Description = "This sensor returns the master volume of the currently selected default audio device as a percentage value."; item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/Sensors.md#mastervolumesensor"; @@ -219,7 +226,7 @@ namespace UserInterface.Views item.ShowWindowNameInput = false; item.UpdateInterval = 5; break; - + case AvailableSensors.GPUTemperatureSensor: item.Description = "This sensor returns the current temperature of the GPU in °C."; item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/Sensors.md#gputemperaturesensor"; @@ -227,7 +234,7 @@ namespace UserInterface.Views item.ShowWindowNameInput = false; item.UpdateInterval = 5; break; - + case AvailableSensors.GPULoadSensor: item.Description = "This sensor returns the current GPU load."; item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/Sensors.md#gpuloadsensor"; @@ -235,7 +242,7 @@ namespace UserInterface.Views item.ShowWindowNameInput = false; item.UpdateInterval = 5; break; - + default: item.Description = null; item.MoreInfoLink = null; diff --git a/documentation/Sensors.md b/documentation/Sensors.md index 2938c7d..6d35695 100644 --- a/documentation/Sensors.md +++ b/documentation/Sensors.md @@ -24,7 +24,7 @@ This sensor returns the current volume of playing audio. **It does not return th This sensor returns the master volume for the currently selected default audio device. -### DummySensor +### DummySensor This sensor produces a random output every second, and is intended to test latency and connectivity. @@ -89,6 +89,10 @@ The webcam active sensor returns the status of the webcam. The webcam process sensor returns the process which is using the webcam. +### MicrophoneProcessSensor + +The microphone process sensor returns the process which is using the microphone. + ### WMIQuerySensor Please see the specific documentaion page [here](https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/WMIQuery.md#wmiquerysensor). diff --git a/hass-workstation-service/Communication/InterProcesCommunication/InterProcessApi.cs b/hass-workstation-service/Communication/InterProcesCommunication/InterProcessApi.cs index 9c9824e..bf4b3a4 100644 --- a/hass-workstation-service/Communication/InterProcesCommunication/InterProcessApi.cs +++ b/hass-workstation-service/Communication/InterProcesCommunication/InterProcessApi.cs @@ -30,7 +30,7 @@ namespace hass_workstation_service.Communication.InterProcesCommunication /// /// You can use this to check if the application responds. - /// + /// /// /// public string Ping(string str) => str == "ping" ? "pong" : "what?"; @@ -44,7 +44,7 @@ namespace hass_workstation_service.Communication.InterProcesCommunication public void WriteMqttBrokerSettingsAsync(MqttSettings settings) => _configurationService.WriteMqttBrokerSettingsAsync(settings); /// - /// Enables or disables autostart. + /// Enables or disables autostart. /// /// public void EnableAutostart(bool enable) => _configurationService.EnableAutoStart(enable); @@ -108,7 +108,7 @@ namespace hass_workstation_service.Communication.InterProcesCommunication public void RemoveCommandById(Guid id) => _configurationService.DeleteConfiguredCommand(id); /// - /// Adds a command to the configured commands. This properly initializes the class and writes it to the config file. + /// Adds a command to the configured commands. This properly initializes the class and writes it to the config file. /// /// /// @@ -123,7 +123,7 @@ namespace hass_workstation_service.Communication.InterProcesCommunication } /// - /// Adds a command to the configured commands. This properly initializes the class, subscribes to the command topic and writes it to the config file. + /// Adds a command to the configured commands. This properly initializes the class, subscribes to the command topic and writes it to the config file. /// /// /// @@ -179,6 +179,7 @@ namespace hass_workstation_service.Communication.InterProcesCommunication AvailableSensors.WebcamActiveSensor => new WebcamActiveSensor(_publisher, (int)model.UpdateInterval, model.Name), AvailableSensors.WebcamProcessSensor => new WebcamProcessSensor(_publisher, (int)model.UpdateInterval, model.Name), AvailableSensors.MicrophoneActiveSensor => new MicrophoneActiveSensor(_publisher, (int)model.UpdateInterval, model.Name), + AvailableSensors.MicrophoneProcessSensor => new MicrophoneProcessSensor(_publisher, (int)model.UpdateInterval, model.Name), AvailableSensors.NamedWindowSensor => new NamedWindowSensor(_publisher, model.WindowName, model.Name, (int)model.UpdateInterval), AvailableSensors.LastActiveSensor => new LastActiveSensor(_publisher, (int)model.UpdateInterval, model.Name), AvailableSensors.LastBootSensor => new LastBootSensor(_publisher, (int)model.UpdateInterval, model.Name), diff --git a/hass-workstation-service/Communication/InterProcesCommunication/ServiceContractModels.cs b/hass-workstation-service/Communication/InterProcesCommunication/ServiceContractModels.cs index fafa58d..86f7065 100644 --- a/hass-workstation-service/Communication/InterProcesCommunication/ServiceContractModels.cs +++ b/hass-workstation-service/Communication/InterProcesCommunication/ServiceContractModels.cs @@ -45,7 +45,7 @@ namespace hass_workstation_service.Communication.InterProcesCommunication.Models { this.WindowName = namedWindowSensor.WindowName; } - this.UpdateInterval = sensor.UpdateInterval; + this.UpdateInterval = sensor.UpdateInterval; this.UnitOfMeasurement = ((SensorDiscoveryConfigModel)sensor.GetAutoDiscoveryConfig()).Unit_of_measurement; } public ConfiguredSensorModel() @@ -95,6 +95,7 @@ namespace hass_workstation_service.Communication.InterProcesCommunication.Models WebcamActiveSensor, WebcamProcessSensor, MicrophoneActiveSensor, + MicrophoneProcessSensor, ActiveWindowSensor, NamedWindowSensor, LastActiveSensor, diff --git a/hass-workstation-service/Data/ConfigurationService.cs b/hass-workstation-service/Data/ConfigurationService.cs index 3ef2a15..f00bb3c 100644 --- a/hass-workstation-service/Data/ConfigurationService.cs +++ b/hass-workstation-service/Data/ConfigurationService.cs @@ -135,6 +135,9 @@ namespace hass_workstation_service.Data case "MicrophoneActiveSensor": sensor = new MicrophoneActiveSensor(publisher, configuredSensor.UpdateInterval, configuredSensor.Name, configuredSensor.Id); break; + case "MicrophoneProcessSensor": + sensor = new MicrophoneProcessSensor(publisher, configuredSensor.UpdateInterval, configuredSensor.Name, configuredSensor.Id); + break; case "SessionStateSensor": sensor = new SessionStateSensor(publisher, configuredSensor.UpdateInterval, configuredSensor.Name, configuredSensor.Id); break; @@ -462,7 +465,7 @@ namespace hass_workstation_service.Data } /// - /// + /// /// /// The Id of the sensor to replace /// The new sensor diff --git a/hass-workstation-service/Domain/Sensors/MicrophoneProcessSensor.cs b/hass-workstation-service/Domain/Sensors/MicrophoneProcessSensor.cs new file mode 100644 index 0000000..17ec875 --- /dev/null +++ b/hass-workstation-service/Domain/Sensors/MicrophoneProcessSensor.cs @@ -0,0 +1,130 @@ +using hass_workstation_service.Communication; +using Microsoft.Win32; +using System; +using System.Linq; +using System.Runtime.InteropServices; +using System.Runtime.Versioning; + +namespace hass_workstation_service.Domain.Sensors +{ + public class MicrophoneProcessSensor : AbstractSensor + { + public MicrophoneProcessSensor(MqttPublisher publisher, int? updateInterval = null, string name = "MicrophoneProcess", Guid id = default) : base(publisher, name ?? "MicrophoneProcess", updateInterval ?? 10, id) + { + } + + public override string GetState() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return IsMicrophoneInUseRegistry(); + } + else + { + return "unsupported"; + } + } + public override SensorDiscoveryConfigModel GetAutoDiscoveryConfig() + { + return this._autoDiscoveryConfigModel ?? SetAutoDiscoveryConfigModel(new SensorDiscoveryConfigModel() + { + Name = this.Name, + NamePrefix = Publisher.NamePrefix, + Unique_id = this.Id.ToString(), + Device = this.Publisher.DeviceConfigModel, + State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{DiscoveryConfigModel.GetNameWithPrefix(Publisher.NamePrefix, this.ObjectId)}/state", + Availability_topic = $"homeassistant/sensor/{Publisher.DeviceConfigModel.Name}/availability" + }); + } + + [SupportedOSPlatform("windows")] + private string IsMicrophoneInUseRegistry() + { + using (var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\microphone")) + { + foreach (var subKeyName in key.GetSubKeyNames()) + { + // NonPackaged has multiple subkeys + if (subKeyName == "NonPackaged") + { + using (var nonpackagedkey = key.OpenSubKey(subKeyName)) + { + foreach (var nonpackagedSubKeyName in nonpackagedkey.GetSubKeyNames()) + { + using (var subKey = nonpackagedkey.OpenSubKey(nonpackagedSubKeyName)) + { + if (subKey.GetValueNames().Contains("LastUsedTimeStop")) + { + var endTime = subKey.GetValue("LastUsedTimeStop") is long ? (long)subKey.GetValue("LastUsedTimeStop") : -1; + if (endTime <= 0) + { + return nonpackagedSubKeyName; + } + } + } + } + } + } + else + { + using (var subKey = key.OpenSubKey(subKeyName)) + { + if (subKey.GetValueNames().Contains("LastUsedTimeStop")) + { + var endTime = subKey.GetValue("LastUsedTimeStop") is long ? (long)subKey.GetValue("LastUsedTimeStop") : -1; + if (endTime <= 0) + { + return subKeyName; + } + } + } + } + } + } + + using (var key = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\microphone")) + { + foreach (var subKeyName in key.GetSubKeyNames()) + { + // NonPackaged has multiple subkeys + if (subKeyName == "NonPackaged") + { + using (var nonpackagedkey = key.OpenSubKey(subKeyName)) + { + foreach (var nonpackagedSubKeyName in nonpackagedkey.GetSubKeyNames()) + { + using (var subKey = nonpackagedkey.OpenSubKey(nonpackagedSubKeyName)) + { + if (subKey.GetValueNames().Contains("LastUsedTimeStop")) + { + var endTime = subKey.GetValue("LastUsedTimeStop") is long ? (long)subKey.GetValue("LastUsedTimeStop") : -1; + if (endTime <= 0) + { + return nonpackagedSubKeyName; + } + } + } + } + } + } + else + { + using (var subKey = key.OpenSubKey(subKeyName)) + { + if (subKey.GetValueNames().Contains("LastUsedTimeStop")) + { + var endTime = subKey.GetValue("LastUsedTimeStop") is long ? (long)subKey.GetValue("LastUsedTimeStop") : -1; + if (endTime <= 0) + { + return subKeyName; + } + } + } + } + } + } + + return "off"; + } + } +} From 93cdde4cde07f710a379d672295d6d67655f7c5b Mon Sep 17 00:00:00 2001 From: Jordan Janzen Date: Wed, 15 Dec 2021 15:00:04 -0800 Subject: [PATCH 2/4] Make microphone and webcam sensors report all active processes --- .../Domain/Sensors/MicrophoneProcessSensor.cs | 99 ++++++----------- .../Domain/Sensors/WebcamProcessSensor.cs | 101 ++++++------------ 2 files changed, 63 insertions(+), 137 deletions(-) diff --git a/hass-workstation-service/Domain/Sensors/MicrophoneProcessSensor.cs b/hass-workstation-service/Domain/Sensors/MicrophoneProcessSensor.cs index 17ec875..f834740 100644 --- a/hass-workstation-service/Domain/Sensors/MicrophoneProcessSensor.cs +++ b/hass-workstation-service/Domain/Sensors/MicrophoneProcessSensor.cs @@ -4,11 +4,14 @@ using System; using System.Linq; using System.Runtime.InteropServices; using System.Runtime.Versioning; +using System.Collections.Generic; namespace hass_workstation_service.Domain.Sensors { public class MicrophoneProcessSensor : AbstractSensor { + private List processes = new List(); + public MicrophoneProcessSensor(MqttPublisher publisher, int? updateInterval = null, string name = "MicrophoneProcess", Guid id = default) : base(publisher, name ?? "MicrophoneProcess", updateInterval ?? 10, id) { } @@ -38,92 +41,52 @@ namespace hass_workstation_service.Domain.Sensors } [SupportedOSPlatform("windows")] - private string IsMicrophoneInUseRegistry() + private void CheckLastUsed(RegistryKey key) { - using (var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\microphone")) + foreach (var subKeyName in key.GetSubKeyNames()) { - foreach (var subKeyName in key.GetSubKeyNames()) + // NonPackaged has multiple subkeys + if (subKeyName == "NonPackaged") { - // NonPackaged has multiple subkeys - if (subKeyName == "NonPackaged") + using (var nonpackagedkey = key.OpenSubKey(subKeyName)) { - using (var nonpackagedkey = key.OpenSubKey(subKeyName)) - { - foreach (var nonpackagedSubKeyName in nonpackagedkey.GetSubKeyNames()) - { - using (var subKey = nonpackagedkey.OpenSubKey(nonpackagedSubKeyName)) - { - if (subKey.GetValueNames().Contains("LastUsedTimeStop")) - { - var endTime = subKey.GetValue("LastUsedTimeStop") is long ? (long)subKey.GetValue("LastUsedTimeStop") : -1; - if (endTime <= 0) - { - return nonpackagedSubKeyName; - } - } - } - } - } + CheckLastUsed(nonpackagedkey); } - else + } + else + { + using (var subKey = key.OpenSubKey(subKeyName)) { - using (var subKey = key.OpenSubKey(subKeyName)) + if (subKey.GetValueNames().Contains("LastUsedTimeStop")) { - if (subKey.GetValueNames().Contains("LastUsedTimeStop")) + var endTime = subKey.GetValue("LastUsedTimeStop") is long ? (long)subKey.GetValue("LastUsedTimeStop") : -1; + if (endTime <= 0) { - var endTime = subKey.GetValue("LastUsedTimeStop") is long ? (long)subKey.GetValue("LastUsedTimeStop") : -1; - if (endTime <= 0) - { - return subKeyName; - } + this.processes.Add(subKeyName); } } } } } + } + + [SupportedOSPlatform("windows")] + private string IsMicrophoneInUseRegistry() + { + using (var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\microphone")) + { + CheckLastUsed(key); + } using (var key = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\microphone")) { - foreach (var subKeyName in key.GetSubKeyNames()) - { - // NonPackaged has multiple subkeys - if (subKeyName == "NonPackaged") - { - using (var nonpackagedkey = key.OpenSubKey(subKeyName)) - { - foreach (var nonpackagedSubKeyName in nonpackagedkey.GetSubKeyNames()) - { - using (var subKey = nonpackagedkey.OpenSubKey(nonpackagedSubKeyName)) - { - if (subKey.GetValueNames().Contains("LastUsedTimeStop")) - { - var endTime = subKey.GetValue("LastUsedTimeStop") is long ? (long)subKey.GetValue("LastUsedTimeStop") : -1; - if (endTime <= 0) - { - return nonpackagedSubKeyName; - } - } - } - } - } - } - else - { - using (var subKey = key.OpenSubKey(subKeyName)) - { - if (subKey.GetValueNames().Contains("LastUsedTimeStop")) - { - var endTime = subKey.GetValue("LastUsedTimeStop") is long ? (long)subKey.GetValue("LastUsedTimeStop") : -1; - if (endTime <= 0) - { - return subKeyName; - } - } - } - } - } + CheckLastUsed(key); } + if (this.processes.Count() > 0) + { + return String.Join(",", this.processes.ToArray()); + } return "off"; } } diff --git a/hass-workstation-service/Domain/Sensors/WebcamProcessSensor.cs b/hass-workstation-service/Domain/Sensors/WebcamProcessSensor.cs index 9210654..a35b390 100644 --- a/hass-workstation-service/Domain/Sensors/WebcamProcessSensor.cs +++ b/hass-workstation-service/Domain/Sensors/WebcamProcessSensor.cs @@ -4,15 +4,18 @@ using System; using System.Linq; using System.Runtime.InteropServices; using System.Runtime.Versioning; +using System.Collections.Generic; namespace hass_workstation_service.Domain.Sensors { public class WebcamProcessSensor : AbstractSensor { + private List processes = new List(); + public WebcamProcessSensor(MqttPublisher publisher, int? updateInterval = null, string name = "WebcamProcess", Guid id = default) : base(publisher, name ?? "WebcamProcess", updateInterval ?? 10, id) { } - + public override string GetState() { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) @@ -38,92 +41,52 @@ namespace hass_workstation_service.Domain.Sensors } [SupportedOSPlatform("windows")] - private string IsWebCamInUseRegistry() + private void CheckLastUsed(RegistryKey key) { - using (var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\webcam")) + foreach (var subKeyName in key.GetSubKeyNames()) { - foreach (var subKeyName in key.GetSubKeyNames()) + // NonPackaged has multiple subkeys + if (subKeyName == "NonPackaged") { - // NonPackaged has multiple subkeys - if (subKeyName == "NonPackaged") + using (var nonpackagedkey = key.OpenSubKey(subKeyName)) { - using (var nonpackagedkey = key.OpenSubKey(subKeyName)) - { - foreach (var nonpackagedSubKeyName in nonpackagedkey.GetSubKeyNames()) - { - using (var subKey = nonpackagedkey.OpenSubKey(nonpackagedSubKeyName)) - { - if (subKey.GetValueNames().Contains("LastUsedTimeStop")) - { - var endTime = subKey.GetValue("LastUsedTimeStop") is long ? (long)subKey.GetValue("LastUsedTimeStop") : -1; - if (endTime <= 0) - { - return nonpackagedSubKeyName; - } - } - } - } - } + CheckLastUsed(nonpackagedkey); } - else + } + else + { + using (var subKey = key.OpenSubKey(subKeyName)) { - using (var subKey = key.OpenSubKey(subKeyName)) + if (subKey.GetValueNames().Contains("LastUsedTimeStop")) { - if (subKey.GetValueNames().Contains("LastUsedTimeStop")) + var endTime = subKey.GetValue("LastUsedTimeStop") is long ? (long)subKey.GetValue("LastUsedTimeStop") : -1; + if (endTime <= 0) { - var endTime = subKey.GetValue("LastUsedTimeStop") is long ? (long)subKey.GetValue("LastUsedTimeStop") : -1; - if (endTime <= 0) - { - return subKeyName; - } + this.processes.Add(subKeyName); } } } } } + } + + [SupportedOSPlatform("windows")] + private string IsWebCamInUseRegistry() + { + using (var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\webcam")) + { + CheckLastUsed(key); + } using (var key = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\webcam")) { - foreach (var subKeyName in key.GetSubKeyNames()) - { - // NonPackaged has multiple subkeys - if (subKeyName == "NonPackaged") - { - using (var nonpackagedkey = key.OpenSubKey(subKeyName)) - { - foreach (var nonpackagedSubKeyName in nonpackagedkey.GetSubKeyNames()) - { - using (var subKey = nonpackagedkey.OpenSubKey(nonpackagedSubKeyName)) - { - if (subKey.GetValueNames().Contains("LastUsedTimeStop")) - { - var endTime = subKey.GetValue("LastUsedTimeStop") is long ? (long)subKey.GetValue("LastUsedTimeStop") : -1; - if (endTime <= 0) - { - return nonpackagedSubKeyName; - } - } - } - } - } - } - else - { - using (var subKey = key.OpenSubKey(subKeyName)) - { - if (subKey.GetValueNames().Contains("LastUsedTimeStop")) - { - var endTime = subKey.GetValue("LastUsedTimeStop") is long ? (long)subKey.GetValue("LastUsedTimeStop") : -1; - if (endTime <= 0) - { - return subKeyName; - } - } - } - } - } + CheckLastUsed(key); } + if (this.processes.Count() > 0) + { + return String.Join(",", this.processes.ToArray()); + } return "off"; } } From a892409543eab14f3104970ac7a5ae7bd3571cc6 Mon Sep 17 00:00:00 2001 From: Jordan Janzen Date: Wed, 15 Dec 2021 15:06:50 -0800 Subject: [PATCH 3/4] Use HashSet instead of List --- .../Domain/Sensors/MicrophoneProcessSensor.cs | 2 +- hass-workstation-service/Domain/Sensors/WebcamProcessSensor.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hass-workstation-service/Domain/Sensors/MicrophoneProcessSensor.cs b/hass-workstation-service/Domain/Sensors/MicrophoneProcessSensor.cs index f834740..645c67b 100644 --- a/hass-workstation-service/Domain/Sensors/MicrophoneProcessSensor.cs +++ b/hass-workstation-service/Domain/Sensors/MicrophoneProcessSensor.cs @@ -10,7 +10,7 @@ namespace hass_workstation_service.Domain.Sensors { public class MicrophoneProcessSensor : AbstractSensor { - private List processes = new List(); + private HashSet processes = new HashSet(); public MicrophoneProcessSensor(MqttPublisher publisher, int? updateInterval = null, string name = "MicrophoneProcess", Guid id = default) : base(publisher, name ?? "MicrophoneProcess", updateInterval ?? 10, id) { diff --git a/hass-workstation-service/Domain/Sensors/WebcamProcessSensor.cs b/hass-workstation-service/Domain/Sensors/WebcamProcessSensor.cs index a35b390..bc4c90b 100644 --- a/hass-workstation-service/Domain/Sensors/WebcamProcessSensor.cs +++ b/hass-workstation-service/Domain/Sensors/WebcamProcessSensor.cs @@ -10,7 +10,7 @@ namespace hass_workstation_service.Domain.Sensors { public class WebcamProcessSensor : AbstractSensor { - private List processes = new List(); + private HashSet processes = new HashSet(); public WebcamProcessSensor(MqttPublisher publisher, int? updateInterval = null, string name = "WebcamProcess", Guid id = default) : base(publisher, name ?? "WebcamProcess", updateInterval ?? 10, id) { From d33cb53e3e8ce5fd111cded95def0f9a9f85d6a7 Mon Sep 17 00:00:00 2001 From: Jordan Janzen Date: Wed, 15 Dec 2021 15:17:04 -0800 Subject: [PATCH 4/4] Ensure processes are removed --- .../Domain/Sensors/MicrophoneProcessSensor.cs | 3 +++ hass-workstation-service/Domain/Sensors/WebcamProcessSensor.cs | 3 +++ 2 files changed, 6 insertions(+) diff --git a/hass-workstation-service/Domain/Sensors/MicrophoneProcessSensor.cs b/hass-workstation-service/Domain/Sensors/MicrophoneProcessSensor.cs index 645c67b..e266194 100644 --- a/hass-workstation-service/Domain/Sensors/MicrophoneProcessSensor.cs +++ b/hass-workstation-service/Domain/Sensors/MicrophoneProcessSensor.cs @@ -73,6 +73,9 @@ namespace hass_workstation_service.Domain.Sensors [SupportedOSPlatform("windows")] private string IsMicrophoneInUseRegistry() { + // Clear old values + this.processes.Clear(); + using (var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\microphone")) { CheckLastUsed(key); diff --git a/hass-workstation-service/Domain/Sensors/WebcamProcessSensor.cs b/hass-workstation-service/Domain/Sensors/WebcamProcessSensor.cs index bc4c90b..4e5ebdf 100644 --- a/hass-workstation-service/Domain/Sensors/WebcamProcessSensor.cs +++ b/hass-workstation-service/Domain/Sensors/WebcamProcessSensor.cs @@ -73,6 +73,9 @@ namespace hass_workstation_service.Domain.Sensors [SupportedOSPlatform("windows")] private string IsWebCamInUseRegistry() { + // Clear old values + this.processes.Clear(); + using (var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\webcam")) { CheckLastUsed(key);