WMI - Performance Data NonAnonymousUsersPerSec - c#

I want to monitor my IIS (SharePoint Farm) with WMI. I am trying to get the following information from the system:
CurrentConnections
NonAnonymousUsersPerSec
AnonymousUsersPerSec
My problem is that I want the same data as in the "Reliability and Performance Monitor" (perfmon) when I add the \Web Service(_Total)\Anonymous User/ses and \web Service(_Total)/NonAnonymous Users/ses to the monitor.
This monitor is showing me nearly 20 NonAnonymous users per second and 0 Anonymous.
I think that these values are correct. The number of connection is the same, in the perfmon-monitor and the WMI query.
But the value for the CurrentUser is totaly different to the value in the monitor.
How can I get this data with WMI querys?
Win32_PerfFormattedData_W3SVC_WebService class
SelectQuery queryCurrentUser = new SelectQuery("SELECT * FROM Win32_PerfFormattedData_W3SVC_WebService WHERE Name LIKE \"_Total\"");
CurrentConnections : ~150
NonAnonymousUsersPerSec : 0
AnonymousUsersPerSec : 0
Win32_PerfRawData_W3SVC_WebService class
SelectQuery queryCurrentUser = new SelectQuery("SELECT * FROM Win32_PerfRawData_W3SVC_WebService WHERE Name LIKE \"_Total\"");
CurrentConnections : ~150
NonAnonymousUsersPerSec : ~150000
AnonymousUsersPerSec : ~2000000
Code:
ManagementScope scope = new ManagementScope("\\\\" + stringServer + "\\root\\CIMV2");
//PerfRawData query
SelectQuery queryCurrentUser = new SelectQuery("SELECT * FROM Win32_PerfRawData_W3SVC_WebService WHERE Name LIKE \"_Total\"");
//PerfFormattedData query
SelectQuery queryCurrentUser = new SelectQuery("SELECT * FROM Win32_PerfFormattedData_W3SVC_WebService WHERE Name LIKE \"_Total\"");
ManagementObjectSearcher currentUsers = new ManagementObjectSearcher(scope, queryCurrentUser);
ManagementObjectCollection currentUsersCollection = currentUsers.Get();
foreach (ManagementObject queryObj in currentUsersCollection)
{
Console.WriteLine("CurrentConnections {0}", queryObj["CurrentConnections"]);
Console.WriteLine("NonAnonymousUsersPerSec {0}", queryObj["NonAnonymousUsersPerSec"]);
Console.WriteLine("AnonymousUsersPerSec {0}", queryObj["AnonymousUsersPerSec"]);
}

I found a solution!
The Win32_PerfFormattedData_ASPNET_ASPNETApplications class.
The values are in RequestsPerSec and AnonymousRequestsPerSec

Related

How do I create this query in C#

I am trying to perform this same WMI query from a C# function.
PS> Get-WMIObject - Namespace root/cimv2/mdm/dmmap - Class MDM_DevDetail_Ext01 - Filter "InstanceID='Ext' AND ParentID='./DevDetail'"
This is the C# code but I get an exception 'Invalid query'
What is the correct way to perform this same query in C#?
ManagementScope scope = new ManagementScope(#"\\localhost\root\cimv2\mdm\dmmap");
scope.Connect();
//Query system for hardware information
ObjectQuery query = new ObjectQuery(
"SELECT * FROM meta_class where __class = 'MDM_DevDetail_Ext01'
and InstanceID='Ext' and ParentID='./DevDetail'");
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query))

Finding wrong escape of WMI query

I somewhere did a wrong escape of wmi query, can someone help fixing it? Because it shows Invalid query
string deviceid = "Disk #0, Partition #0";
string antecedent = #"\\" + Environment.MachineName + "\\root\\cimv2:Win32_DiskPartition.DeviceID=\"" + deviceid + "\"";
ManagementObjectSearcher assosiaciation_query2 = new ManagementObjectSearcher("select Dependent from Win32_LogicalDiskToPartition where Antecedent = \"" + antecedent + "\"");
foreach (ManagementObject assosiaciation_query_data2 in assosiaciation_query2.Get())
{
Console.WriteLine("Dependent: " + assosiaciation_query_data2["Dependent"]);
}
Thank you.
Ok since in mysql you could use LIKE to find simillar tables, also I read that is possible https://msdn.microsoft.com/en-us/library/aa392263%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396 to use LIKE in wmi query
string deviceid = "Disk #0, Partition #0"; ManagementObjectSearcher assosiaciation_query2 = new ManagementObjectSearcher("select Dependent from Win32_LogicalDiskToPartition where Antecedent LIKE '%" + deviceid + "%'");
So ant still it show that query is invalid
You put 2 doublequote inside 2 other doublequote, and that broke your code. You should use WMI escape code inside your antecedent string:
string antecedent = #"\\" + Environment.MachineName + "\\root\\cimv2:Win32_DiskPartition.DeviceID=\\\"" + deviceid + "\\\"";
When WMI receive the command it should be something like that:
\"yourdeviceid\"
that inserted into 2 apex shoud work correctly :) Example:
Mycommand"myOtherCommand\"myvalue\""
EDIT:
I completely misunderstant your goal, sorry, there is an error in your query, because '#' is MySQL Wildcard that mess your query (is MySql inline comment),
Nope, it doesn't works even if i use where Ascendent like 'aaa', idk why your where condition mess up the code :/.
If you use the following piece of code it works:
string query = "select * from Win32_LogicalDiskToPartition";
string antecedent = #"\\" + Environment.MachineName + "\\root\\cimv2:Win32_DiskPartition.DeviceID=\"" + deviceid + "\"";
ManagementObjectSearcher moSearch = new ManagementObjectSearcher(query);
ManagementObjectCollection moCollection = moSearch.Get();
foreach (ManagementObject mo in moCollection)
{
if (string.Equals(mo["Antecedent"].ToString(), antecedent))
Console.WriteLine("Dependent: " + mo["Dependent"]);
}

Formatting a WQL Output in C#

I'm trying to build a query, to list all the known computers in SCCM with a specific name.
The query looks like this:
string query = string.Format("Select Name From SMS_R_System Where Name like '" + "%" + computerName + "%" + "'");
If results are found, it puts the result(s) in a dropdown box.
My problem in these case, the output looks like this:
"instance of SMS_R_System{Name = "DC01";};"
But of course, for our use case we only need DC01 as output.
Any tips?
The full Code for the ButtonEvent:
private void ChkBtn_Click(object sender, EventArgs e)
{
string computerName = PCDropDown.Text;
lBox.Items.Clear();
SmsNamedValuesDictionary namedValues = new SmsNamedValuesDictionary();
WqlConnectionManager connection = new WqlConnectionManager(namedValues);
// Connect to remote computer.
try
{
connection.Connect(PrimarySiteServer.ToString());
// Set the query.
string query1 = string.Format("Select Name From SMS_R_System Where Name like '" + "%" + computerName + "%" + "'");
string query2 = string.Format("Select * From SMS_UserMachineRelationship WHERE ResourceName like '" + "%" + computerName + "%" + "' AND IsActive = '1' AND Types = '1'");
// Get the query results
IResultObject queryResults = connection.QueryProcessor.ExecuteQuery(query1);
// Check for results and display in infobox
bool resultsFound = false;
foreach (IResultObject queryResult in queryResults)
{
resultsFound = true;
lBox.Items.Add("Rechner ist vorhanden");
PCDropDown.Items.Add(queryResult.ToString());
}
if (resultsFound == false)
{
lBox.Items.Add("Rechnername nicht gefunden");
}
}
catch
{
MessageBox.Show("No Connection to Config-Manager - Als ZZA ausgeführt? SCCM-Servername richtig?");
}
}
Instead of adding queryResult.ToString() like you do here:
PCDropDown.Items.Add(queryResult.ToString());
you need to add the correct field of queryResult, so in this case:
PCDropDown.Items.Add(queryResult["Name"].StringValue);
Also a quick note. I don't know for who you are writing this and what the next step would be but if this is a read only application that is only used by SCCM Admins I would consider ignoring WMI and going to the SCCM DB via SQL instead. It is a lot faster, SQL has far more powerful options for queries and it does not need the integration of those strange sccm console Dlls (although that is not 100% necessary for WMI either).
If you need write access to create devices or collections etc., or you need to work with the roles the sccm access rights systems implements however WMI is the better or only choice. (And in this case I'd rather really use those strange dlls because all of the MS examples rely on them and it can be hard to translate those tutorials to the vanilla WMI solution C# offers.

How to get serial number of USB-Stick

ManagementObjectSearcher theSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive WHERE InterfaceType='USB'");
foreach (ManagementObject currentObject in theSearcher.Get())
{
ManagementObject theSerialNumberObjectQuery = new ManagementObject("Win32_PhysicalMedia.Tag='" + currentObject["DeviceID"] + "'");
MessageBox.Show(theSerialNumberObjectQuery["SerialNumber"].ToString());
}
How do I get the internal serial number of a USB-Stick or USB-HardDrive?
If i insert Hp or SanDisk Pen Drive it will display correct and whole serial number but if i insert some other pen drive means it will display only the first digit of the serial number. Why the problem occurs I don't know so please make me correct.
Try using ...
currentObject["PNPDeviceID"] instead of currentObject["DeviceID"]
Edit : Change your query to Select * From __InstanceOperationEvent Within 1 Where TargetInstance ISA 'Win32_DiskDrive' and TargetInstance.InterfaceType='USB' and check..

WMI __InstanceModificationEvent filtering

We are designing a monitoring solution for our system, and we're looking into WMI as a possible option.
In short, we want to create a generic system where it shall be possible to subscribe to multiple changes in WMI data instances. We're looking into the __InstanceModificationEvent to do this:
The following prototype code monitors all changes on any instance of notepad:
void StartMonitor()
{
var query = "SELECT * "
+ "FROM __InstanceModificationEvent "
+ "WITHIN 1 "
+ "WHERE TargetInstance Isa \"Win32_PerfFormattedData_PerfProc_Process\" "
+ "AND TargetInstance.Name = \"notepad\"";
var scope = new ManagementScope(#"root\cimv2", null);
scope.Connect();
EventQuery qry = new EventQuery(query);
ManagementEventWatcher w = new ManagementEventWatcher(scope, qry);
w.EventArrived += EventArrived;
w.Start();
}
void EventArrived(object sender, EventArrivedEventArgs e)
{
var targetInstance = (ManagementBaseObject)e.NewEvent["TargetInstance"];
foreach (var p in targetInstance.Properties)
{
Console.WriteLine(p.Name + ":\t" + (p.Value != null ? p.Value.ToString() : "{null}"));
}
}
So whenever any instance of notepad is changes, we will get an output like this (excerpt)
PageFileBytes: 1499136
PageFileBytesPeak: 1740800
PercentPrivilegedTime: 0
PercentProcessorTime: 0
PercentUserTime: 0
PoolNonpagedBytes: 7040
PoolPagedBytes: 172856
This is fine, however we need to improve this a bit. For example, let's pretend we are only interested in the changes to PercentProcessorTime. With the current code, the event will be fired whenever anything in the object changes. This is not good enough, because we might monitor hundreds of processes across multiple computers.
Thus, we need a way to specify that we only want the event to be triggered whenever this or that property changes, not the entire instance
Is this possible using WMI? What's the best practice to achieve what we want?
Edit: I know that it is possible to write a query such as the one below and cycically poll for the value, however we were hoping to avoid that approach.
SELECT PercentProcessorTime
FROM Win32_PerfFormattedData_PerfProc_Process
WHERE Name = "notepad"
The __InstanceModificationEvent has a reference to the previous instance so you might be able to compare values between the PreviousInstance and TargetInstance. For example, to filter for PercentProcessorTime changes:
var query = "SELECT * "
+ "FROM __InstanceModificationEvent "
+ "WITHIN 1 "
+ "WHERE TargetInstance Isa \"Win32_PerfFormattedData_PerfProc_Process\" "
+ "AND TargetInstance.Name = \"notepad\" "
+ "AND PreviousInstance.PercentProcessorTime != TargetInstance.PercentProcessorTime ";

Categories