diff --git a/ConnectForm.xaml b/ConnectForm.xaml deleted file mode 100644 index cb70948..0000000 --- a/ConnectForm.xaml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ConnectForm.xaml.cs b/ConnectForm.xaml.cs deleted file mode 100644 index dafdbca..0000000 --- a/ConnectForm.xaml.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System.Security; -using System.Windows; - -namespace GetWMIBasic -{ - public partial class ConnectForm : Window - { - /* - * Global properties - */ - private bool isConnectLocally; - - public ConnectForm() - { - isConnectLocally = false; - InitializeComponent(); - } - - /* - * Button-based methods - */ - - private void ConnetToExternal_Button(object sender, RoutedEventArgs e) - { - if ( - ComputerName_TextBox.Text.Length == 0 || - UserName_TextBox.Text.Length == 0 || - Password_TextBox.Password.Length == 0) - { - MessageBox.Show("Please don't leave anything empty", "Error", MessageBoxButton.OK, MessageBoxImage.Warning); - } - else - { - DialogResult = true; - } - } - - private void ConnectToLocal_Button(object sender, RoutedEventArgs e) - { - isConnectLocally = true; - DialogResult = true; - } - - private void Cancel_Button(object sender, RoutedEventArgs e) - { - Close(); - } - - /* - * Non-button methods - */ - public (string, string, SecureString) ReturnValue() - { - ShowDialog(); - - string computerName = (isConnectLocally) ? "localhost" : ComputerName_TextBox.Text; - string userName = (isConnectLocally) ? "" : UserName_TextBox.Text; - SecureString password = new SecureString(); - - if (!isConnectLocally) - { - foreach (char c in Password_TextBox.Password) - { - password.AppendChar(c); - } - } - - return (computerName, userName, password); - } - } -} diff --git a/DefaultUI/ConnectForm.xaml b/DefaultUI/ConnectForm.xaml new file mode 100644 index 0000000..6dd79a4 --- /dev/null +++ b/DefaultUI/ConnectForm.xaml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/DefaultUI/ConnectForm.xaml.cs b/DefaultUI/ConnectForm.xaml.cs new file mode 100644 index 0000000..7e8cc71 --- /dev/null +++ b/DefaultUI/ConnectForm.xaml.cs @@ -0,0 +1,110 @@ +using System.Security; +using System.Windows; + +/* The Default UI includes + * 1. ConnectForm.xaml - A form to connect to a local or remote computer + * 2. ExceptionView.xaml - A window to handle exception messages + */ +namespace GetWMIBasic.DefaultUI +{ + /* + * Connection Form class + * It is used to get connection information from the user + * Expected behaviour: + * 1. User enter the computer name, username, and password to connect to a remote computer + * 2. The application tries verify the connection information + * 3. If what user enters is valid, the form closes and returns the information + */ + public partial class ConnectForm : Window + { + /* + * Global properties + * isConnectLocally: A boolean to indicate whether the user wants to connect to the local computer + * - false when the user wants to connect to a remote computer + * - true when the user wants to connect to the local computer + */ + private bool isConnectLocally; + + // Constructor of the ConnectForm class + public ConnectForm() + { + // Set the default value of isConnectLocally to false + isConnectLocally = false; + + // Initialize the components of the form + InitializeComponent(); + } + + // Button-based methods + + /* + * Connect to External Button Click Event - The "Connect" button + * Validates the input fields and sets the DialogResult to true if valid + */ + private void ConnetToExternal_Button(object sender, RoutedEventArgs e) + { + // Validate that none of the input fields are empty + if ( + ComputerName_TextBox.Text.Length == 0 || + UserName_TextBox.Text.Length == 0 || + Password_TextBox.Password.Length == 0) + { + _ = MessageBox.Show("Please don't leave anything empty", "Error", MessageBoxButton.OK, MessageBoxImage.Warning); + } + else + { + // Close the form with a DialogResult of true + DialogResult = true; + } + } + + /* + * Connect to Local Button Click Event - The "Connect to Local" button + * Sets the isConnectLocally flag to true and sets the DialogResult to true + */ + private void ConnectToLocal_Button(object sender, RoutedEventArgs e) + { + isConnectLocally = true; + DialogResult = true; + } + + /* + * Cancel Button Click Event - The "Cancel" button + * Closes the form without setting a DialogResult + */ + private void Cancel_Button(object sender, RoutedEventArgs e) + { + Close(); + } + + + // Non-button methods + + /* + * Return Value Method + * Returns a tuple containing the computer name, username, and password as a SecureString + */ + public (string, string, SecureString) ReturnValue() + { + // Show the dialog and wait for user interaction + _ = ShowDialog(); + + // Prepare the return values based on whether connecting locally or remotely + string computerName = (isConnectLocally) ? "localhost" : ComputerName_TextBox.Text; + string userName = (isConnectLocally) ? "" : UserName_TextBox.Text; + SecureString password = new SecureString(); + + // Only populate the password if connecting remotely + if (!isConnectLocally) + { + foreach (char c in Password_TextBox.Password) + { + password.AppendChar(c); + } + } + + // Return the collected values as a tuple + return (computerName, userName, password); + } + } +} diff --git a/DefaultUI/ExceptionView.xaml b/DefaultUI/ExceptionView.xaml new file mode 100644 index 0000000..3bebf69 --- /dev/null +++ b/DefaultUI/ExceptionView.xaml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + An exception has occurred in the application. + + You may choose to close the application or ignore the error. + + + + + + + + + + + + + + + + + + + + + + diff --git a/DefaultUI/ExceptionView.xaml.cs b/DefaultUI/ExceptionView.xaml.cs new file mode 100644 index 0000000..d50bc86 --- /dev/null +++ b/DefaultUI/ExceptionView.xaml.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Management; +using System.Runtime.InteropServices; +using System.Windows; +using GetWMIBasic.WMIMethods; + +/* The Default UI includes + * 1. ConnectForm.xaml - A form to connect to a local or remote computer + * 2. ExceptionView.xaml - A window to handle exception messages + */ +namespace GetWMIBasic.DefaultUI +{ + /* + * Exception View class + * It is used to handle exception messages + * + * Excepted behaviour: + * 1. An exception is passed to the HandleException method + * 2. If the exception is of an allowed type, show the exception message + * and give the user the option to ignore it; else, force close the application + */ + public partial class ExceptionView : Window + { + /* + * Global properties + * allowedExceptionTypes: A list of exception types that are allowed to be ignored + */ + private readonly HashSet allowedExceptionTypes = new HashSet + { + typeof(UnauthorizedAccessException), + typeof(COMException), + typeof(ManagementException) + }; + + // Constructor of the Exception View class + public ExceptionView() + { + InitializeComponent(); + } + + // Button-based methods + + /* + * Click Ignore Exception Button - The "Ignore" button + * Let user ignore the exception and continue using the application + */ + private void Click_IgnoreException(object sender, RoutedEventArgs e) + { + Close(); + } + + /* + * Click Close Application Button - The "Close Application" button + * Close the application in case of a critical or unhandled exception + */ + private void Click_CloseApp(object sender, RoutedEventArgs e) + { + Application.Current.Shutdown(); + } + + // Non-button methods + + /* + * Handle Exception Method + * Get the exception info, and decide whether to allow the user to ignore it + */ + public void HandleException(Exception e) + { + // If the exception is null, ignore it + if (e == null) + { + return; + } + + // Check if the exception type is in the allowed list + bool isAllowed = this.allowedExceptionTypes.Any(t => t.IsInstanceOfType(e)); + + // If not allowed, change the message and hide the ignore button + if (!isAllowed) + { + // Reset the exception message + ExceptionMessage_TextBlock.Text = "An unexpected error has occurred.\n" + + "You should close the application and check for the system"; + // Hide the ignore button + Button_Ignore.Visibility = Visibility.Collapsed; + } + + // Show the detailed exception info +#if !DEBUG + DetailedExceptionDetail_TextBox.Text = e.Message; +#else + DetailedExceptionDetail_TextBox.Text = e.ToString(); +#endif + + // Show the exception view window + ShowDialog(); + } + } +} diff --git a/Get WMI Basic.csproj b/Get WMI Basic.csproj index bb5bc06..24f2f35 100644 --- a/Get WMI Basic.csproj +++ b/Get WMI Basic.csproj @@ -99,8 +99,15 @@ MSBuild:Compile Designer + + ExceptionView.xaml + - + + Designer + MSBuild:Compile + + Designer MSBuild:Compile @@ -112,7 +119,7 @@ App.xaml Code - + ConnectForm.xaml diff --git a/MainWindow.xaml b/MainWindow.xaml index 238a08c..3dad6af 100644 --- a/MainWindow.xaml +++ b/MainWindow.xaml @@ -6,15 +6,17 @@ xmlns:local="clr-namespace:GetWMIBasic" mc:Ignorable="d" Title="Get WMI Basic" - Height="192" + Height="200" Width="800" + MinWidth="600" + MaxWidth="1000" ResizeMode="NoResize" SizeToContent="WidthAndHeight"> - - - + + + @@ -29,22 +31,26 @@ + + + + - + - - + + - - + + @@ -53,13 +59,13 @@ - + - + - + - + @@ -67,8 +73,8 @@ - - + + @@ -77,26 +83,26 @@ - + - + - + - + - + - - + + - Welcome + Welcome diff --git a/MainWindow.xaml.cs b/MainWindow.xaml.cs index 4d0f7fe..3239dc6 100644 --- a/MainWindow.xaml.cs +++ b/MainWindow.xaml.cs @@ -1,177 +1,255 @@ -using System; +using GetWMIBasic.DefaultUI; +using GetWMIBasic.WMIMethods; +using System; using System.Linq; using System.Management; -using System.Runtime.InteropServices; using System.Security; using System.Threading.Tasks; using System.Windows; -using GetWMIBasic.WMIMethods; - +/* + * Primary namespace for the application + * It includes the MainWindow class which is the main UI window of the application + * and additional UI for each featuring + */ namespace GetWMIBasic { + /* + * Main Window class + * It is used to display the main UI of the application + */ + public partial class MainWindow : Window { + //////////////////////////////////////////////////////////////// + /// Global Properties and Constructors Region + /// This region contains global properties and constructors + /// for the MachineMethods class. + //////////////////////////////////////////////////////////////// + /* - * Global properties + * Global properties + * machine: An instance of the MachineMethods class to perform WMI operations */ protected MachineMethods machine; + /* + * Constructor of the MainWindow class + * Initializes the components and sets up event handlers + */ public MainWindow() { + // Initialize components InitializeComponent(); + + // Initialize the MachineMethods instance for local machine machine = new MachineMethods(); + + // Set up the sync loading event handler. See the method below for further info. Loaded += MainWindow_Loaded; } - + + /* + * Main Windows async loading method. + * It is used prevent long loading times on the UI thread + */ private async void MainWindow_Loaded(object sender, RoutedEventArgs e) { + // Call the Refresh method to load initial data await Refresh(); } - /* - * Button-based methods + //////////////////////////////////////////////////////////////// + /// User Action Methods Region + /// This region contains methods that handle user actions. + /// For example, button clicks, changes in order. + //////////////////////////////////////////////////////////////// + + /* + * Actions for button "Connect to Another Computer" */ private async void ConnectToAnotherComputer_Button(object sender, RoutedEventArgs e) { - ConnectForm connectForm = new ConnectForm(); - - (string computerName, string username, SecureString password) userCredential = connectForm.ReturnValue(); + // Get the user credentials from the ConnectForm + (string computerName, string username, SecureString password) userCredential = (new ConnectForm()).ReturnValue(); + // If the computer name is not empty, create a new MachineMethods instance if (userCredential.computerName != "") { - machine = null; - if (!userCredential.computerName.Equals("localhost")) - { - machine = new MachineMethods(userCredential); - } - else - { - machine = new MachineMethods(); - } - - await Refresh(); + machine = !userCredential.computerName.Equals("localhost") ? new MachineMethods(userCredential) : new MachineMethods(); } + + // Refresh the data on the UI + await Refresh(); } + /* + * Actons for button "Exit Application" + */ private void Exit_Button(object sender, RoutedEventArgs e) { Application.Current.Shutdown(); } + /* + * + */ private async void Restart_Button(object sender, RoutedEventArgs e) { + // Confirm the restart action with the user if (MessageBox.Show($"Do you want to restart the computer {machine.GetComputerName()}?", "Proceed?", MessageBoxButton.YesNo) == MessageBoxResult.Yes) { + // Update the status bar to indicate loading StatusBarChange("Loading", true); + /* + * Try to restart the remote machine using WMI, with the target computer name + * Catch the exception and display it using the ExceptionView if any error occurs + * In any case, no matter if it succeeds or fails, update the status bar to "Done" + */ try { + // Since the local machine cannot be restarted remotely, throw an exception if the target is localhost + // It should be done via the user context menu instead if (machine.GetComputerName() == "localhost") { throw new ManagementException("Local Host cannot be restarted"); } + // Connect to the WMI namespace machine.Connect("root\\cimv2"); + + // Call the Win32Shutdown method with the restart flag (6) await machine.CallMethod("Win32_OperatingSystem", "*", "Win32Shutdown", new object[] { 6 }); } - catch (UnauthorizedAccessException ex) + catch (Exception ex) { -#if DEBUG - MessageBox.Show(ex.ToString(), "Error", MessageBoxButton.OK, MessageBoxImage.Error); -#else - MessageBox.Show($"Failed to catch the Authenticate with {machine.GetComputerName()}: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error); -#endif - } - catch (COMException ex) - { -#if DEBUG - MessageBox.Show(ex.ToString(), "Error", MessageBoxButton.OK, MessageBoxImage.Error); -#else - MessageBox.Show($"Failed to reach {machine.GetComputerName()}: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error); -#endif - } - - catch (ManagementException ex) - { -#if DEBUG - MessageBox.Show(ex.ToString(), "Error", MessageBoxButton.OK, MessageBoxImage.Error); -#else - MessageBox.Show($"Failed to catch the Management Method: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error); -#endif + // Handle any exceptions using the ExceptionView + (new ExceptionView()).HandleException(ex); } finally { + // Update the status bar to indicate completion StatusBarChange("Done", false); } } } + /* + * Actions for button "Shutdown Computer" + */ private async void Shutdown_Button(object sender, RoutedEventArgs e) { + // Confirm the shutdown action with the user if (MessageBox.Show($"Do you want to shutdown the computer {machine.GetComputerName()}?", "Proceed?", MessageBoxButton.YesNo) == MessageBoxResult.Yes) { + // Update the status bar to indicate loading StatusBarChange("Loading", true); + /* + * Try to shutdown the remote machine using WMI, with the target computer name + * Catch the exception and display it using the ExceptionView if any error occurs + * In any case, no matter if it succeeds or fails, update the status bar to "Done" + */ try { + // Since the local machine cannot be shutdown remotely, throw an exception if the target is localhost + // It should be done via the user context menu instead if (machine.GetComputerName() == "localhost") { throw new ManagementException("Local Host cannot be shut down"); } + // Connect to the WMI namespace machine.Connect("root\\cimv2"); + + // Call the Win32Shutdown method with the shutdown flag (5) await machine.CallMethod("Win32_OperatingSystem", "*", "Win32Shutdown", new object[] { 5 }); } - catch (UnauthorizedAccessException ex) + catch (Exception ex) { -#if DEBUG - MessageBox.Show(ex.ToString(), "Error", MessageBoxButton.OK, MessageBoxImage.Error); -#else - MessageBox.Show($"Failed to catch the Authenticate with {machine.GetComputerName()}: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error); -#endif - } - catch (COMException ex) - { -#if DEBUG - MessageBox.Show(ex.ToString(), "Error", MessageBoxButton.OK, MessageBoxImage.Error); -#else - MessageBox.Show($"Failed to reach {machine.GetComputerName()}: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error); -#endif - } - - catch (ManagementException ex) - { -#if DEBUG - MessageBox.Show(ex.ToString(), "Error", MessageBoxButton.OK, MessageBoxImage.Error); -#else - MessageBox.Show($"Failed to catch the Management Method: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error); -#endif + // Handle any exceptions using the ExceptionView + (new ExceptionView()).HandleException(ex); } finally { + // Update the status bar to indicate completion StatusBarChange("Done", false); } } } + /* + * Actions for button "Refresh Information" + */ private async void Refresh_Button(object sender, RoutedEventArgs e) { + // Call the Refresh method to update the data on the UI await Refresh(); } /* - * Non-button methods + * Actions for button "Regular Exception Example" + * (It will throw and catch a common exception to demonstrate the ExceptionView) + */ + private void RegularException_Click(object sender, RoutedEventArgs e) + { + try + { + throw new ManagementException("Unable to manage (example exception handler)."); + } + catch (Exception ex) + { + (new ExceptionView()).HandleException(ex); + } + } + + /* + * Actions for button "Critical Exception Example" + * (It will throw and catch a critical exception to demonstrate the ExceptionView) + */ + private void CriticalException_Click(object sender, RoutedEventArgs e) + { + try + { + throw new Exception("Critical exception (example exception handler)."); + } + catch (Exception ex) + { + (new ExceptionView()).HandleException(ex); + } + } + + //////////////////////////////////////////////////////////////// + /// Non-User Action Methods Region + /// + /// This region contains methods that do not handle user actions. + /// + /// Think about this is the back-end section. + /// It should not be in a seperated class, because it directly interacts with the UI elements. + //////////////////////////////////////////////////////////////// + + /* + * Refresh method to update the information displayed on the UI */ private async Task Refresh() { + // Update the status bar to indicate loading StatusBarChange("Loading", true); + /* + * Try to get info from the remote machine using WMI, with the target computer name + * Catch the exception and display it using the ExceptionView if any error occurs + * In any case, no matter if it succeeds or fails, update the status bar to "Done" + */ try { + // Connect to the WMI namespace machine.Connect("root\\cimv2"); - var biosProperties = machine.GetObjects("Win32_BIOS", "*"); + // Get BIOS properties + // In case the property is null, set the text to an empty string + Task biosProperties = machine.GetObjects("Win32_BIOS", "Manufacturer, Name, SerialNumber, Version"); foreach (ManagementObject biosProperty in (await biosProperties).Cast()) { BIOS_Manufacturer.Text = biosProperty["Manufacturer"]?.ToString() ?? string.Empty; @@ -180,7 +258,9 @@ private async Task Refresh() BIOS_Version.Text = biosProperty["Version"]?.ToString() ?? string.Empty; } - var osProperties = machine.GetObjects("Win32_ComputerSystem", "*"); + // Get Operating System properties + // In case the property is null, set the text to an empty string + Task osProperties = machine.GetObjects("Win32_ComputerSystem", "Name, Domain, TotalPhysicalMemory, SystemType"); foreach (ManagementObject osProperty in (await osProperties).Cast()) { Computer_Name.Text = osProperty["Name"]?.ToString() ?? string.Empty; @@ -189,37 +269,21 @@ private async Task Refresh() Computer_SysType.Text = osProperty["SystemType"]?.ToString() ?? string.Empty; } } - catch (UnauthorizedAccessException ex) - { -#if DEBUG - MessageBox.Show(ex.ToString(), "Error", MessageBoxButton.OK, MessageBoxImage.Error); -#else - MessageBox.Show($"Failed to catch the Authenticate with {machine.GetComputerName()}: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error); -#endif - } - catch (COMException ex) + catch (Exception ex) { -#if DEBUG - MessageBox.Show(ex.ToString(), "Error", MessageBoxButton.OK, MessageBoxImage.Error); -#else - MessageBox.Show($"Failed to reach {machine.GetComputerName()}: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error); -#endif - } - - catch (ManagementException ex) - { -#if DEBUG - MessageBox.Show(ex.ToString(), "Error", MessageBoxButton.OK, MessageBoxImage.Error); -#else - MessageBox.Show($"Failed to catch the Management Method: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error); -#endif + // Handle any exceptions using the ExceptionView + (new ExceptionView()).HandleException(ex); } finally { + // Update the status bar to indicate completion StatusBarChange("Done", false); } } + /* + * Set the status bar text and progress bar state + */ protected void StatusBarChange(string label, bool progressbarLoading) { Bottom_Label.Text = label; diff --git a/WMIMethods/MachineMethods.cs b/WMIMethods/MachineMethods.cs index 038f336..d822809 100644 --- a/WMIMethods/MachineMethods.cs +++ b/WMIMethods/MachineMethods.cs @@ -3,14 +3,42 @@ using System.Security; using System.Threading.Tasks; +/* + * The default WMI method class includes: + * 1. CriticalException.cs - A custom exception class for critical WMI errors + * 2. CommonException.cs - A custom exception class for common WMI errors + * 3. MachineMethods.cs - A base class for WMI operations on local and remote machines + */ namespace GetWMIBasic.WMIMethods { + /* + * Machine Method class + * It is used to connect and perform WMI tasks to local and remote machines through WMI + * + * Security Note: + * 1. When connecting to remote machines, ensure that the credentials are handled securely. + * 2. Use SecureString for passwords to enhance security. + * 3. The application should run with appropriate permissions to access WMI on the target machines. + * For example, locally it may require administrative privileges and do not run with external credentials. + */ public class MachineMethods { + + //////////////////////////////////////////////////////////////// + /// Global Properties and Constructors Region + /// This region contains global properties and constructors + /// for the MachineMethods class. + //////////////////////////////////////////////////////////////// + /* - * Class properties + * Global properties + * userCredential: A tuple to store computer name, username, and password + * credential: A ConnectionOptions object to store WMI connection options + * scope: A ManagementScope object to define the WMI scope + * searcher: A ManagementObjectSearcher object to perform WMI queries + * scopePath: A string to store the WMI scope path + * isLocal: A boolean to indicate whether the connection is local or remote */ - protected (string computerName, string username, SecureString password) userCredential; protected ConnectionOptions credential; protected ManagementScope scope; @@ -20,15 +48,19 @@ public class MachineMethods protected bool isLocal; /* - * Machine Method - * 1. Empty - Local - * 2. Or Connect through WMI + * Constructor for local connection + * Note: Local connections do not require username and password. + * It uses current user context. */ - public MachineMethods() { + // Set default computer name to localhost userCredential.computerName = "localhost"; + + // Set local connection flag isLocal = true; + + // Set default connection options for local connection credential = new ConnectionOptions { Impersonation = ImpersonationLevel.Impersonate, @@ -37,12 +69,21 @@ public MachineMethods() }; } + /* + * Constructor for remote connection + * Note: Remote connections require username and password. + */ public MachineMethods((string computerName, string username, SecureString password) userCredential) { + // Set user credentials for remote connection this.userCredential.computerName = userCredential.computerName; this.userCredential.username = userCredential.username; this.userCredential.password = userCredential.password; + + // Set remote connection flag isLocal = false; + + // Set connection options for remote connection credential = new ConnectionOptions { Username = userCredential.username, @@ -53,8 +94,32 @@ public MachineMethods((string computerName, string username, SecureString passwo }; } + //////////////////////////////////////////////////////////////// + /// Connect to a name space region + /// This region contains methods to connect to a WMI name space. + /// For example, "root\\cimv2". + //////////////////////////////////////////////////////////////// + + public void Connect(string nameSpace) + { + // Set the scope path based on local or remote connection + scopePath = $"\\\\{userCredential.computerName}\\{nameSpace}"; + + // Create the ManagementScope object and connect + scope = (isLocal) ? new ManagementScope(scopePath) : new ManagementScope(scopePath, credential); + + // Connect to the WMI scope + scope.Connect(); + } + + //////////////////////////////////////////////////////////////// + /// Get methods region (connection setting, not the WMI data) + /// Various get methods to retrieve information about the machine + /// For example, computer name, current user name, etc. + //////////////////////////////////////////////////////////////// + /* - * Get value + * Get methods for computer name */ public string GetComputerName() { @@ -62,42 +127,53 @@ public string GetComputerName() } /* - * Connection method + * Get methods for current user name */ - - public void Connect(string nameSpace) + public string GetUsername() { - scopePath = $"\\\\{userCredential.computerName}\\{nameSpace}"; - scope = (isLocal) ? new ManagementScope(scopePath) : new ManagementScope(scopePath, credential); - scope.Connect(); + return userCredential.username; } + //////////////////////////////////////////////////////////////// + /// Get methods region (for WMI data) + //////////////////////////////////////////////////////////////// + /* * Get WMI objects */ public async Task GetObjects(string className, string fields) { + // Create the WMI query ObjectQuery query = new ObjectQuery($"SELECT {fields} FROM {className}"); + + // Create the ManagementObjectSearcher object searcher = new ManagementObjectSearcher(scope, query); + + // Execute the query and return the results asynchronously return await Task.Run(() => searcher?.Get()); } + //////////////////////////////////////////////////////////////// + /// Set methods region (for WMI object) + //////////////////////////////////////////////////////////////// + /* * Call WMI Method */ public async Task CallMethod(string className, string fields, string methodName, object[] args) { - ObjectQuery query = new ObjectQuery($"SELECT {fields} FROM {className}"); - await Task.Run(() => - { - using (var searcher = new ManagementObjectSearcher(scope, query)) + // Get the WMI objects asynchronously + using (Task manageObject = GetObjects(className, fields)) { + await Task.Run(() => { - foreach (ManagementObject manageObject in searcher.Get().Cast()) + // Invoke the method on each object returned by the query + foreach (ManagementObject obj in manageObject.Result.Cast()) { - manageObject.InvokeMethod(methodName, args); + // Invoke the specified method with arguments + _ = obj.InvokeMethod(methodName, args); } - } - }); + }); + } } } }