I need to check a group of servers to see whether the anti virus is up-to-date and running. Tricky thing is that they are spread over Windows 2003 and 2008 servers and I need to be able to check them all.
Is there any way of doing this with C# or VB.NET?
I have briefly looked around using WMI, but it appears on 2008/win7 computers Microsoft has changed what information they give back to you.
In summary, I need the following:
AV name
AV version
AV Up-to-Date
AV Enabled/Running
Can anyone help?
Sample can be found here using WMI as you mentioned. The poster states this is being done on a Win 7 machine; so the code below should get you started...
ConnectionOptions _connectionOptions = new ConnectionOptions();
//Not required while checking it in local machine.
//For remote machines you need to provide the credentials
//options.Username = "";
//options.Password = "";
_connectionOptions.EnablePrivileges = true;
_connectionOptions.Impersonation = ImpersonationLevel.Impersonate;
//Connecting to SecurityCenter2 node for querying security details
ManagementScope _managementScope = new ManagementScope(string.Format("\\\\{0}\\root\\SecurityCenter2", ipAddress), _connectionOptions);
_managementScope.Connect();
//Querying
ObjectQuery _objectQuery = new ObjectQuery("SELECT * FROM AntivirusProduct");
ManagementObjectSearcher _managementObjectSearcher =
new ManagementObjectSearcher(_managementScope, _objectQuery);
ManagementObjectCollection _managementObjectCollection = _managementObjectSearcher.Get();
if (_managementObjectCollection.Count > 0)
{
foreach (ManagementObject item in _managementObjectCollection)
{
Console.WriteLine(item["displayName"]);
//For Kaspersky AntiVirus, I am getting a null reference here.
//Console.WriteLine(item["productUptoDate"]);
//If the value of ProductState is 266240 or 262144, its an updated one.
Console.WriteLine(item["productState"]);
}
}
Depending on how your environment is setup you may need to specify your security and permissions. You should also note that some antivirus products (like McAfee) do not make data available through WMI.
You can query the Antivirus information from WMI using this snippet:
string computer = Environment.MachineName;
string wmipath = #"\\" + computer + #"\root\SecurityCenter";
string query = #"SELECT * FROM AntivirusProduct";
ManagementObjectSearcher searcher = new ManagementObjectSearcher(wmipath, query);
ManagementObjectCollection results = searcher.Get();
foreach (ManagementObject result in results)
{
// do something with `result[value]`);
}
Related
My requirement is to get installed software details of vm machine of azure and store the details in db. but when I try to get the details using System.Management class I am getting the below error
System.Runtime.InteropServices.COMException: 'The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)'
below is my sample code I am using to get the software details
string SoftwareQuery = "SELECT * FROM Win32_Product";
ConnectionOptions connection = new ConnectionOptions();
connection.Username = "bla bla";
connection.Password = "Password";
connection.EnablePrivileges = true;
connection.Impersonation = ImpersonationLevel.Impersonate;
ManagementScope managementScope = new ManagementScope(#"\\xxxx.xxxx.cloudapp.azure.com:3389\root\CIMV2", connection);
managementScope.Path = ManagementPath.DefaultPath;
managementScope.Connect();
ObjectQuery queryObj = new ObjectQuery(SoftwareQuery);
ManagementObjectSearcher searcher = new ManagementObjectSearcher(managementScope, queryObj);
foreach (ManagementBaseObject managementObj in searcher.Get())
{
//get the software list here
}
Note: The above code is working on intranet properly
Please let me know anyone have solution on this.
It might be related to the Windows Management Instrumentation service being in a stopped state. Take a look at Starting and Stopping the WMI Service.
Hope it helps!
I'm having trouble connecting to remote computer to grab a list of processes running.
For my test machine I'm using the username #"ownme\veritas". The password is just "veritas".
The sample domain is "ownme".
return new System.Management.ConnectionOptions()
{
//certainly these variables have been checked and are correct
Username = UserCredential.DomainUser,
Password = UserCredential.Password
};
This is where I'm trying to do the connection. I don't know, but this might actually be the issue here. It could also be I didn't fill out enough fields in the ConnectionOptions above.
I referred to these two articles:
https://www.experts-exchange.com/questions/23514935/How-to-use-GetProcess-for-remote-sytems.html
https://msdn.microsoft.com/en-us/library/system.management.connectionoptions.authentication.aspx
I can't figure out what I'm doing wrong
ManagementScope scope = new ManagementScope($"\\\\{computer.DnsHostname}\\root\\cimv2", connectionOptions);
scope.Connect();
//Error: Access is denied
var processes = System.Diagnostics.Process.GetProcesses(dnsHostName);
GetProcesses will use the current users credentials to connect to the remote machine, not the credentials you specified via ConnectionOptions.
You need to use the WMI scope object that you created with the correct credentials to issue a query for the processes like this:
//..
SelectQuery query = new SelectQuery("select * from Win32_Process"); //query processes
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query))
{
using (ManagementObjectCollection collection = searcher.Get())
{
foreach (var process in collection) //loop through results
{
var name = process["name"]; //process name
//Do something with process
}
}
}
I didn't realize this was such a highly viewed question: I found the answer a long time ago. I actually didn't use WMI to do it. We actually filed a ticket with Microsoft and the discounted us for free after they gave us the answer. The answer is:
LogonUser + NEW_CREDENTIALS
I am trying to figure out if the Active Directory Domain Services are installed a windows server.
I know they show up in the Server Manager, but can I programmatically get if the role is installed on a server using C# code
If you know the name of the server you want to test and can run the program with domain admin privileges remotely, you can use WMI:
internal static bool IsDomainController(string ServerName)
{
StringBuilder Results = new StringBuilder();
try
{
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("\\\\" + ServerName + "\\root\\CIMV2",
"SELECT * FROM Win32_ServerFeature WHERE ID = 10");
foreach (ManagementObject queryObj in searcher.Get())
{
Results.AppendLine(queryObj.GetPropertyValue("ID").ToString());
}
}
catch (ManagementException)
{
//handle exception
}
if (Results.Length > 0)
return true;
else
return false;
}
If you're running that locally on the server, the WMI path changes to:
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\CIMV2",
"SELECT * FROM Win32_ServerFeature WHERE ID = 10");
See the MSDN reference on Win32_ServerFeature for a full list of roles and their ID numbers.
If your question is to see if a server is a domain controller, you can enumerate the domain controllers in the domain and check the hostname of the server you are sitting on to see if it matches any of them. To get the list of domain controllers:
var domainControllers = new List<string>();
var domain = Domain.GetCurrentDomain();
foreach (var dc in domain.DomainControllers)
{
domainControllers.Add(dc.Name);
}
string whoami = Dns.GetHostname();
Make sure to add requisite error handling (like if you run this on a workgroup computer, it will die).
EDIT:
Alternate ways of detecting DCPROMO (because it's possible to install Domain Services without DCPROMO, and that is a bad thing):
1) Parse out (and check for the existence of) the debug log that is created when DCPROMO does its thing. Should be located at c:\windows\debug\dcpromo.log
2) This DSQUERY command is FAST and will give you all the servers where DCPROMO was ran:
dsquery * "cn=Sites,cn=Configuration,dc=MyDomain,dc=com" -Filter "(cn=NTDS Settings)" -attr distinguishedName whenCreated
Problem is getting that from command line output if you started it using Process. Working on a way to do this and will update once I have it tested, as I haven't done AD filtering in a query for a while.
From C# (.NET 4.0), we're making a WMI call like this:
var connectOptions = new ConnectionOptions
{
Authority = "ntlmdomain:" + paramValues.Domain,
Username = paramValues.UserName,
Password = paramValues.Password
};
var scopeString = #"\\" + paramValues.Server + #"\root\cimv2";
var scope = new ManagementScope(scopeString, connectOptions);
scope.Connect();
var queryString = String.Format("SELECT * FROM Win32_NTLogEvent WHERE LogFile = 'Security' AND TimeGenerated > '{0:yyyyMMddHHmm00.000000+0000}'";,
paramValues.StartTime);
var query = new ObjectQuery(queryString);
var searcher = new ManagementObjectSearcher(scope, query);
var queryCollection = searcher.Get();
This works fine, with the exception of a failure against only one of our servers. In that case, the searcher.Get() call hangs. Looking at the network traffic through Wireshark reveals that the Event Log entries are being correctly returned, but at some point the remote server simply terminates the TCP connection.
I found a WMI Tester utility online (http://www.paessler.com/tools/wmitester) that appears not to be written against the .NET framework (using DCOM). I can supply the same credentials and the same WMI query using that tool and get back the expected results.
Am I right to suspect that something is different between the .NET code and the DCOM call, or am I chasing the wrong thing? So far this is the only difference between the working and non-working code that I can find.
i want to create a wrapper class for specific WMI functions that affect Bitlocker functionality. The first step is to get all the Bitlocker volumes of a machine so I created a Console Application and did this:
private static ManagementClass management;
private static ManagementObjectCollection Volumes = null;
static void Main(string[] args)
{
ManagementPath path = new ManagementPath();
path.Server = "";
path.NamespacePath = "\\ROOT\\CIMV2\\Security\\MicrosoftVolumeEncryption";
path.ClassName = "Win32_EncryptableVolume";
ConnectionOptions options = new ConnectionOptions();
options.Authentication = AuthenticationLevel.PacketPrivacy;
options.Impersonation = ImpersonationLevel.Impersonate;
ManagementScope scope = new ManagementScope(path, options);
ObjectGetOptions getOptions = new ObjectGetOptions();
management = new ManagementClass(scope, path, getOptions);
management.Get();
Volumes = management.GetInstances();
}
When I run this on a non-Bitlocker machine the Volumes Collection gets initialized OK, only that it has a Count of 0 of course. Now I copied the code over to a WinForms App and when I click a button to run this code it steps through OK but when I try to expand the collection during debugging the App hangs and I get a "Function evaluation timed out". It's the same code just in another Application. What could be the reason for this?
Hm. I got a null reference exception if I didn't run it as administrator, but when I ran it as administrator (Win 7 x64, btw), I got four Volumes back.
I just had a similar issue, I will post my code for you hopefully it helps.
ManagementObjectSearcher Encryption = new ManagementObjectSearcher(#"root\cimv2\Security\MicrosoftVolumeEncryption", "SELECT * FROM Win32_EncryptableVolume");
foreach (ManagementObject QueryObj in Encryption.Get())
{
string EncryptionStatus = QueryObj.GetPropertyValue("ProtectionStatus").ToString();
if (EncryptionStatus == "0")
{
EncryptionDialog.Text = "Unencrypted";
}
else if (EncryptionStatus == "1")
{
EncryptionDialog.Text = "Encrypted - SysPrep will not complete";
}
else if (EncryptionStatus == "2")
{
EncryptionDialog.Text = "Cannot Determine Encryption";
}
}
I'm using this to display the status for a sysprep tool i'm creating so the "EncryptionDialog.Text = ..." can be replaced with any other calls you may need. you also need to remember "which caused me issues at least" if you are using visual studio you will need to add a file to your project labeled "Application Manifest File" in the "Add New File" Dialog. The reason for this is that the application will need to be opened in Administrator mode(Just an FYI in case you haven't made it that far)