How to get Battery Health Using C# - c#

I'm trying to get two values, DesignCapacity and FullChargeCacity, but they are not returning a value.
I'm using the code below:
public static bool CheckBattery()
{
bool _testResult = false;
string computer = ".";
try
{
ManagementScope scp = new ManagementScope(#"\\" + computer + #"\root\cimv2");
scp.Connect();
SelectQuery sql = new SelectQuery("CIM_Battery");
ManagementObjectSearcher mos = new ManagementObjectSearcher(scp,sql);
ManagementObjectCollection moc = mos.Get();
List<string> resultList = new List<string>();
foreach (ManagementObject o in moc)
{
foreach (PropertyData property in o.Properties)
{
resultList.Add( property.Name + ":" +property.Value);
}
File.WriteAllLines("bat.txt", resultList.ToArray());
//UInt16 availability = (UInt16)o["Availability"];
//resultList.Add("Availability," + availability.ToString());
//UInt16 batterystatus = (UInt16)o["BatteryStatus"];
//resultList.Add("BatteryStatus," + batterystatus.ToString());
//string status = (string)o["Status"];
//resultList.Add("Status," + status);
//UInt32 Desigcap = (UInt32)o["DesignCapacity"];
}
}
catch (Exception ex)
{
string errr = ex.Message;
}
return _testResult;
}
How Can I avoid to get null values in this properties? In fact iterating the objects im getting this information:
Availability:2
BatteryRechargeTime:
BatteryStatus:2
Caption:Internal Battery
Chemistry:2
ConfigManagerErrorCode:?
ConfigManagerUserConfig:?
CreationClassName:Win32_Battery
Description:Internal Battery
DesignCapacity:?
DesignVoltage:17119
DeviceID:3338SANYO AL12A32
ErrorCleared:?
ErrorDescription:?
EstimatedChargeRemaining:100
EstimatedRunTime:71582788
ExpectedBatteryLife:
ExpectedLife:?
FullChargeCapacity:?
InstallDate:?
LastErrorCode:
MaxRechargeTime:
Name:AL12A32
PNPDeviceID:
PowerManagementCapabilities:System.UInt16[]
PowerManagementSupported:False
SmartBatteryVersion:
Status:OK
StatusInfo:?
SystemCreationClassName:Win32_ComputerSystem
SystemName:MX02L180
TimeOnBattery:?
TimeToFullCharge:?

To get those particular values you need to do separate queries against different classes.
DesignCapacity can be queried from BatteryStaticData
FullChargeCacity can be queried from BatteryFullChargedCapacity
You'll need to use a different scope in the code also for the query. These classes are found in root/WMI instead of root/cimv2
string scope = "root/WMI";
string query = "SELECT DesignedCapacity FROM BatteryStaticData";
using (ManagementObjectSearcher batteriesQuery = new ManagementObjectSearcher(scope, query))
{
using (ManagementObjectCollection batteries = batteriesQuery.Get())
{
foreach (ManagementObject battery in batteries)
{
if (battery != null)
{
foreach (var property in battery.Properties)
{
Console.Log("Property name: " + property.Name + " Property value: " + property.Value);
}
}
}
}
}

Related

Getting MSFT_Partition from MSFT_Disk using Associators

I am trying to get a list of MSFT_Partitions from a MSFT_Disk object and loop over them.
This is the code I have been using so far but it always outputs an System.Management.ManagementException: 'Invalid query ' exception.
This is the code I am using at the moment:
public static void GetDiskInfo() {
var rawDiskInfos = new ManagementObjectSearcher("root\\Microsoft\\Windows\\Storage", "SELECT * FROM MSFT_Disk");
foreach(var rawDiskInfo in rawDiskInfos.Get()) {
Console.WriteLine(rawDiskInfo["FriendlyName"]);
GetPartitionInfo(rawDiskInfo["ObjectId"]);
}
}
public static void GetPartitionInfo(object objectId) {
ManagementScope scope = new ManagementScope("\\\\.\\ROOT\\Microsoft\\Windows\\Storage");
var query = new ObjectQuery("ASSOCIATORS OF {MSFT_Disk.ObjectId=\"" + objectId + "\"} WHERE AssocClass = MSFT_DiskToPartition");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
ManagementObjectCollection queryCollection = searcher.Get();
foreach(var partiton in queryCollection) {
Console.WriteLine(partiton["Guid"]);
}
}
I already tried a lot of solutions I found online and all of them resulted in the same exception.
Thank you very much for your help!
Most queries you'll find on the internet don't do it, but in the general case, you must escape raw strings you pass to WQL queries (in your case objectId contains special characters), using the backslash character, with a method like this:
public static string EscapeWql(string text)
{
if (text == null)
return null;
var sb = new StringBuilder(text.Length);
foreach (var c in text)
{
if (c == '\\' || c == '\'' || c == '"')
{
sb.Append('\\');
}
sb.Append(c);
}
return sb.ToString();
}
So your method should now look like this:
public static void GetPartitionInfo(object objectId)
{
var scope = new ManagementScope(#"root\Microsoft\Windows\Storage");
var query = new ObjectQuery("ASSOCIATORS OF {MSFT_Disk.ObjectId=\"" + EscapeWql((string)objectId) + "\"} WHERE AssocClass = MSFT_DiskToPartition");
using (var searcher = new ManagementObjectSearcher(scope, query))
{
using (var queryCollection = searcher.Get())
{
foreach (var partition in queryCollection)
{
Console.WriteLine(partition["Guid"]);
}
}
}
}
PS: don't forget using statements on IDisposable classes.

ALL employees under a director or above using Active Directory and c#

I'm attempting to create a cascading drop down in which the first populates a list of Director level employees (directors have multiple managers and the managers have multiple employees) which would then populate the second dropdown through ajax. I'm trying to put together the logic that given a displayname will grab all direct reports and the direct reports of the direct reports. With the logic I've put together it will print everyone im looking for but only returns the reports to the original Director. I'm struggling to put everything together. The code isnt at all pretty and if there's an easier way to do this I'm open for suggestions.
There are three methods in which I'm attempting to populate the directReports list in the DirectReports method with all employees
public List<string> DirectReports(string name)
{
List<string> directReports = new List<string>();
var domain = new PrincipalContext(ContextType.Domain, "somedomain");
UserPrincipal user = new UserPrincipal(domain);
user.DisplayName = name;
PrincipalSearcher ps = new PrincipalSearcher();
ps.QueryFilter = user;
DirectorySearcher ds = ps.GetUnderlyingSearcher() as DirectorySearcher;
ds.SearchScope = SearchScope.Subtree;
ds.Filter = "(&(objectClass=user)(objectCategory=person)(displayName=" + name + "))";
ds.PropertiesToLoad.Add("DirectReports");
SearchResultCollection results = ds.FindAll();
foreach(SearchResult result in results)
{
if (hasDirectReports(result))
{
//directReports.AddRange(GetReportsFinal(GetDirectReportsList(result)));
directReports.AddRange(GetDirectReportsList(result));
directReports.Add(result.Properties["displayname"][0].ToString() + " (" + result.Properties["samaccountname"][0].ToString()+")");
}
else
{
directReports.Add(result.Properties["displayname"][0].ToString() + " (" + result.Properties["samaccountname"][0].ToString() + ")");
}
}
foreach(var item in directReports)
{
Debug.WriteLine(item);
}
return directReports;
}
public bool hasDirectReports(SearchResult result)
{
if(result.Properties["directreports"].Count >= 1)
{
return true;
}
else
{
return false;
}
}
public List<string> GetDirectReportsList(SearchResult result)
{
List<string> formattedDirectReportsList = new List<string>();
foreach (var thing in result.Properties["directreports"])
{
string employeeString = thing.ToString();
//employeeString = employeeString.Split(setp, StringSplitOptions.None)[0];
employeeString = employeeString.Replace("CN=", "");
employeeString = employeeString.TrimEnd(',');
employeeString = employeeString.Replace("\\, ", ", ");
//Debug.WriteLine(employeeString);
if (employeeString.Split(',')[2] == "OU=Users")
{
string fn = employeeString.Split(',')[1];
string ln = employeeString.Split(',')[0];
var domain = new PrincipalContext(ContextType.Domain, "somedomain");
UserPrincipal directreportname = new UserPrincipal(domain);
directreportname.Name = ln + "," + fn;
PrincipalSearcher prinsearcher = new PrincipalSearcher();
prinsearcher.QueryFilter = directreportname;
DirectorySearcher dirsearcher = prinsearcher.GetUnderlyingSearcher() as DirectorySearcher;
Principal reportResults = prinsearcher.FindOne();
formattedDirectReportsList.Add(reportResults.DisplayName + " (" + reportResults.SamAccountName + ")");
DirectReports(reportResults.DisplayName);
}
}
return formattedDirectReportsList;
}

C# - How to get list of USERs/GROUPs having access to shared folder on a Remote Machine

I wanted to write a code in C# to list all the users/groups having access (Read/Write/Full) to a shared folder on a server.
For Example: I have a shared folder \servername\MyData. Now I wanted to list the users/groups who have access to this folder.
This should get you pointed in the right direction, I can't test it atm but should be something similar.
private bool CheckAccess(DirectoryInfo directory)
{
// Get the collection of authorization rules that apply to the current directory
AuthorizationRuleCollection acl = directory.GetAccessControl().GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier));
foreach (var rule in acl)
{
// do something here
}
}
private DataTable GetSharedFolderAccessRule()
{
DataTable DT = new DataTable();
try
{
DT.Columns.Add("ShareName");
DT.Columns.Add("Caption");
DT.Columns.Add("Path");
DT.Columns.Add("Domain");
DT.Columns.Add("User");
DT.Columns.Add("AccessMask");
DT.Columns.Add("AceType");
ManagementScope Scope = new ManagementScope(#"\\.\root\cimv2");
Scope.Connect();
ObjectQuery Query = new ObjectQuery("SELECT * FROM Win32_LogicalShareSecuritySetting");
ManagementObjectSearcher Searcher = new ManagementObjectSearcher(Scope, Query);
ManagementObjectCollection QueryCollection = Searcher.Get();
foreach (ManagementObject SharedFolder in QueryCollection)
{
{
String ShareName = (String) SharedFolder["Name"];
String Caption = (String)SharedFolder["Caption"];
String LocalPath = String.Empty;
ManagementObjectSearcher Win32Share = new ManagementObjectSearcher("SELECT Path FROM Win32_share WHERE Name = '" + ShareName + "'");
foreach (ManagementObject ShareData in Win32Share.Get())
{
LocalPath = (String) ShareData["Path"];
}
ManagementBaseObject Method = SharedFolder.InvokeMethod("GetSecurityDescriptor", null, new InvokeMethodOptions());
ManagementBaseObject Descriptor = (ManagementBaseObject)Method["Descriptor"];
ManagementBaseObject[] DACL = (ManagementBaseObject[])Descriptor["DACL"];
foreach (ManagementBaseObject ACE in DACL)
{
ManagementBaseObject Trustee = (ManagementBaseObject)ACE["Trustee"];
DataRow Row = DT.NewRow();
Row["ShareName"] = ShareName;
Row["Caption"] = Caption;
Row["Path"] = LocalPath;
Row["Domain"] = (String) Trustee["Domain"];
Row["User"] = (String) Trustee["Name"];
Row["AccessMask"] = (UInt32) ACE["AccessMask"];
Row["AceType"] = (UInt32)ACE["AceType"];
DT.Rows.Add(Row);
DT.AcceptChanges();
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.StackTrace, ex.Message);
}
return DT;
}

C# + WMI + LPT help!

I'm making an application that needs to list all the LPT ports in a machine with their IO addresses. (ie it's output : LPT1 [starting ; ending] ....)
Using WMI you can get this info.. the name/number from Win32_ParallelPort and the addresses from Win32_PortResource.
The problem is that i don't know how to associate the portname with it's addresses.
You have to query three times and loop over the results to get the matching records from ParallelPort, PnPAllocatedResource and PortResource. The following code does exactly that:
var parallelPort = new ManagementObjectSearcher("Select * From Win32_ParallelPort");
//Dump(parallelPort.Get());
foreach (var rec in parallelPort.Get())
{
var wql = "Select * From Win32_PnPAllocatedResource";
var pnp = new ManagementObjectSearcher(wql);
var searchTerm = rec.Properties["PNPDeviceId"].Value.ToString();
// compensate for escaping
searchTerm = searchTerm.Replace(#"\", #"\\");
foreach (var pnpRec in pnp.Get())
{
var objRef = pnpRec.Properties["dependent"].Value.ToString();
var antref = pnpRec.Properties["antecedent"].Value.ToString();
if (objRef.Contains(searchTerm))
{
var wqlPort = "Select * From Win32_PortResource";
var port = new ManagementObjectSearcher(wqlPort);
foreach (var portRec in port.Get())
{
if (portRec.ToString() == antref)
{
Console.WriteLine( "{0} [{1};{2}]",
rec.Properties["Name"].Value,
portRec.Properties["StartingAddress"].Value,
portRec.Properties["EndingAddress"].Value );
}
}
}
}
}

how to refresh management object

i had written a code to display the description(Name) of connected USB devices.once i removed a device,then i need to refresh the ManagementObject and have to display the connected device description.
Here is my Code,
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("SELECT * FROM Win32_USBControllerDevice");
foreach (ManagementObject mo in searcher.Get())
{
string str1 = mo["CurrentRefreshRate"].ToString();
Console.WriteLine(str1);
string dependent = mo["Dependent"].ToString();
string deviceId = dependent.Split('=')[1];
deviceId = deviceId.Replace('\"', '\'');
ManagementObjectSearcher searcher2 =
new ManagementObjectSearcher("SELECT * FROM Win32_PnPEntity Where DeviceID = " + deviceId);
foreach (ManagementObject mo2 in searcher2.Get())
{
HardwareDetails Detail = new HardwareDetails();
Detail.Description = mo2["Description"].ToString();
Detail.DeviceId = mo2["DeviceId"].ToString();
string[] str = Detail.DeviceId.Split('\\');
string Id = str[1];
if (Id.Contains('&'))
{
string[] separate = Id.Split('&');
Detail.Vid = separate[0].Contains('_') ? separate[0].Split('_')[1] : separate[0].Split('D')[1];
Detail.Pid = separate[1].Contains('_') ? separate[1].Split('_')[1] : separate[1].Split('D')[1];
//Detail.Pid = pid1[1];
}
else
{
Detail.Vid = "";
Detail.Pid = "";
}
if (list.Count > 0)
{
foreach (HardwareDetails h in list)
{
if (!(h.Description == Detail.Description))
{
list.Add(Detail);
break;
}
}
}
else
list.Add(Detail);
}
}
// remove duplicates, sort alphabetically and convert to array
HardwareDetails[] usbDevices = list.ToArray();
return usbDevices;
Did you try this?
WqlEventQuery query = new WqlEventQuery(
"SELECT * FROM Win32_DeviceChangeEvent");
ManagementEventWatcher watcher = new ManagementEventWatcher(query);
watcher.EventArrived +=
new EventArrivedEventHandler(HandleEvent);
// Start listening for events
watcher.Start();
.........
// Stop listening for events
watcher.Stop();
And in the HandleEvent add or remove device from the list
Hope this helps!

Categories