I can use PowerShell to do this fairly easily, but I am looking for a C# way to do this. With PS, I can use Get-Service to iterate over the collection and check collections in there called DependentServices and RequiredServices to get the list of the dependent and required services for a given service.
I've looked into the WMI model using the query "Select * from Win32_Service", but this returns a collection of Win32_Service objects that does not seem to have the collections I am interested in. I feel like I am missing something here. I have looked around and tried various searches, but I've not turned up a C#-centric way of doing this.
I want to query a given service and get back the collections mentioned above (DependentServices and RequiredServices). Sorry if I missed the obvious, but I really have not been able to find relevant topics.
You can use the ServiceController class:
StringBuilder sb = new System.Text.StringBuilder();
foreach (var svc in System.ServiceProcess.ServiceController.GetServices())
{
sb.AppendLine("============================");
sb.AppendLine(svc.DisplayName);
foreach (var dep in svc.DependentServices)
{
sb.AppendFormat("\t{0}", dep.DisplayName);
sb.AppendLine();
}
}
MessageBox.Show(sb.ToString());
You can use the Win32_DependentService WMI class and the Associators of sentence to retrieve the dependent services.
Try this sample
using System;
using System.Collections.Generic;
using System.Management;
using System.Text;
namespace GetWMI_Info
{
class Program
{
static void Main(string[] args)
{
try
{
string ComputerName = "localhost";
ManagementScope Scope;
Scope = new ManagementScope(String.Format("\\\\{0}\\root\\CIMV2", ComputerName), null);
Scope.Connect();
ObjectQuery Query = new ObjectQuery("Associators of {Win32_Service.Name='NetMan'} Where AssocClass=Win32_DependentService ResultClass=Win32_Service");
ManagementObjectSearcher Searcher = new ManagementObjectSearcher(Scope, Query);
foreach (ManagementObject WmiObject in Searcher.Get())
{
Console.WriteLine("{0,-35} {1,-40}","Name",WmiObject["Name"]);// String
}
}
catch (Exception e)
{
Console.WriteLine(String.Format("Exception {0} Trace {1}",e.Message,e.StackTrace));
}
Console.WriteLine("Press Enter to exit");
Console.Read();
}
}
}
You can use this property -
http://msdn.microsoft.com/en-us/library/system.serviceprocess.servicecontroller.dependentservices.aspx
ServiceController sc = new ServiceController("Event Log");
ServiceController[] scServices = sc.DependentServices;
// Display the list of services dependent on the Event Log service.
if (scServices.Length == 0)
{
Console.WriteLine("There are no services dependent on {0}",
sc.ServiceName);
}
else
{
Console.WriteLine("Services dependent on {0}:",
sc.ServiceName);
foreach (ServiceController scTemp in scServices)
{
Console.WriteLine(" {0}", scTemp.DisplayName);
}
}
Related
I've 2 devices My-PC and another-PC
another-PC are connected to switch which connected to main switch with-in the same LAN
My question is how to get all devices information such as (IP,MAC,Serial Number) from My-PC to another-PC
Refer to the documentation for the System.Management namespace on MSDN. All you need is in there. There are also numerous examples out there if you search for retrieving WMI information with C#. A small example:
using System;
using System.Management;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
// create management class object
ManagementClass mc = new
ManagementClass("Win32_ComputerSystem");
//collection to store all management objects
ManagementObjectCollection moc = mc.GetInstances();
if (moc.Count != 0)
{
foreach (ManagementObject mo in mc.GetInstances())
{
// display general system information
Console.WriteLine("\nMachine Make: {0}", mo["Manufacturer"].ToString());
}
}
//wait for user action
Console.ReadLine();
}
}
}
I need to dynamically determine which property of a WMI class is the primary key in C#.
I can manually locate this information using CIM Studio or the WMI Delphi Code Creator but I need to find all property names of a class and flag which is / are the key / keys... and I already know how to find the property names of a class.
Manual identification of the key is covered in a related answer and I'm hoping the author (I'm looking at RRUZ) might be able to fill me in on how they locate the key (or anyone else who might know).
Many thanks.
To get the key field of a WMI class, you must iterate over the qualifiers of the properties for the WMI class and then search for the qualifier called key and finally check if the value of that qualifier is true.
Try this sample
using System;
using System.Collections.Generic;
using System.Management;
using System.Text;
namespace GetWMI_Info
{
class Program
{
static string GetKeyField(string WmiCLass)
{
string key = null;
ManagementClass manClass = new ManagementClass(WmiCLass);
manClass.Options.UseAmendedQualifiers = true;
foreach (PropertyData Property in manClass.Properties)
foreach (QualifierData Qualifier in Property.Qualifiers)
if (Qualifier.Name.Equals("key") && ((System.Boolean)Qualifier.Value))
return Property.Name;
return key;
}
static void Main(string[] args)
{
try
{
Console.WriteLine(String.Format("The Key field of the WMI class {0} is {1}", "Win32_DiskPartition", GetKeyField("Win32_DiskPartition")));
Console.WriteLine(String.Format("The Key field of the WMI class {0} is {1}", "Win32_Process", GetKeyField("Win32_Process")));
}
catch (Exception e)
{
Console.WriteLine(String.Format("Exception {0} Trace {1}", e.Message, e.StackTrace));
}
Console.WriteLine("Press Enter to exit");
Console.Read();
}
}
}
For those interested I've expanded on RRUZ's answer by:
allowing the query to be run against a remote machine, and
adding support for classes with multiple primary keys (as is the case with Win32_DeviceBus).
static void Main(string[] args)
{
foreach (var key in GetPrimaryKeys(#"root\cimv2\win32_devicebus"))
{
Console.WriteLine(key);
}
}
static List<string> GetPrimaryKeys(string classPath, string computer = ".")
{
var keys = new List<string>();
var scope = new ManagementScope(string.Format(#"\\{0}\{1}", computer, System.IO.Path.GetDirectoryName(classPath)));
var path = new ManagementPath(System.IO.Path.GetFileName(classPath));
var options = new ObjectGetOptions(null, TimeSpan.MaxValue, true);
using (var mc = new ManagementClass(scope, path, options))
{
foreach (var property in mc.Properties)
{
foreach (var qualifier in property.Qualifiers)
{
if (qualifier.Name.Equals("key") && ((System.Boolean)qualifier.Value))
{
keys.Add(property.Name);
break;
}
}
}
}
return keys;
}
Im trying to get tcp/ip info and physical info from a NIC card. I have queries for both (from win_32 NetworkAdapter and win32_NetworkAdapterConfiguration) But i want to join them together so i can select a specific network card from a combobox and get both sets of info.
I have been told I can use win_32 NetworkAdaptersetting but Im pretty new to this stuff so I don't know how!! It must be in c#.
Here is an example:
using System;
using System.Management;
namespace WMITest
{
class Program
{
static void Main(string[] args)
{
ManagementObjectSearcher searcher =
new ManagementObjectSearcher(
"Select * From Win32_NetworkAdapter");
foreach (ManagementObject adapter in searcher.Get())
{
Console.WriteLine(adapter["Name"]);
foreach(ManagementObject configuration in
adapter.GetRelated("Win32_NetworkAdapterConfiguration"))
{
Console.WriteLine(configuration["Caption"]);
}
Console.WriteLine();
}
}
}
}
I am trying to query the names all of the WMI classes within the root\CIMV2 namespace. Is there a way to use a powershell command to retrieve this information in C# ?
Along the lines of Keith's approach
using System;
using System.Management.Automation;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var script = #"
Get-WmiObject -list -namespace root\cimv2 | Foreach {$_.Name}
";
var powerShell = PowerShell.Create();
powerShell.AddScript(script);
foreach (var className in powerShell.Invoke())
{
Console.WriteLine(className);
}
}
}
}
I'm not sure why you mentioned PowerShell; you can do this in pure C# and WMI (the System.Management namespace, that is).
To get a list of all WMI classes, use the SELECT * FROM Meta_Class query:
using System.Management;
...
try
{
EnumerationOptions options = new EnumerationOptions();
options.ReturnImmediately = true;
options.Rewindable = false;
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\cimv2", "SELECT * FROM Meta_Class", options);
ManagementObjectCollection classes = searcher.Get();
foreach (ManagementClass cls in classes)
{
Console.WriteLine(cls.ClassPath.ClassName);
}
}
catch (ManagementException exception)
{
Console.WriteLine(exception.Message);
}
Personally I would go with Helen's approach and eliminate taking a dependency on PowerShell. That said, here's how you would code this in C# to use PowerShell to retrieve the desired info:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Management.Automation;
namespace RunspaceInvokeExp
{
class Program
{
static void Main()
{
using (var invoker = new RunspaceInvoke())
{
string command = #"Get-WmiObject -list -namespace root\cimv2" +
" | Foreach {$_.Name}";
Collection<PSObject> results = invoker.Invoke(command);
var classNames = results.Select(ps => (string)ps.BaseObject);
foreach (var name in classNames)
{
Console.WriteLine(name);
}
}
}
}
}
Just to note that there is a tool available that allows you to create, run, and save WMI scripts written in PowerShell, the PowerShell Scriptomatic tool, available for download from the Microsoft TechNet site.
Using this tool, you could explore all of the WMI classes within the root\CIMV2 or any other WMI namespace.
You'd probably want to just use the System.Management namespace like Helen answered, but you can also host powershell within your application. See http://www.codeproject.com/KB/cs/HowToRunPowerShell.aspx
Can anybody explain me what I wrong I am doing in the following piece of code:
DataTable dt=SmoApplication.EnumAvailableSqlServer(true);
Server sr = new Server("Test");
foreach(DataBase db in sr.DataBases)
{
Console.WriteLine(db["name"]);
}
It gives an exception in sr.Databases that can not be connected.
Take a look at the following links they may be helpful:
Enumerate SQL Server Instances in C#, Using ODBC
How to get a list of available SQL Servers using C# (MSDN)
Populating a list of SQL Servers
Alternatively you could change your code to this:
DataTable dt = SmoApplication.EnumAvailableSqlServers(false);
if (dt.Rows.Count > 0)
{
foreach (DataRow dr in dt.Rows)
{
Console.WriteLine(dr["Name"]);
}
}
Hope this solves your problem.
Do you have a SQL Server with the instance name Test? If not, that is your problem.
It looks like you are trying to enumerate all of the local SQL Server instances. If so, this code will work:
DataTable dt = SmoApplication.EnumAvailableSqlServers(true);
foreach (DataRow dr in dt.Rows)
{
Console.WriteLine(dr["Name"]);
Console.WriteLine(" " + dr["Server"]);
Console.WriteLine(" " + dr["Instance"]);
Console.WriteLine(" " + dr["Version"]);
Console.WriteLine(" " + dr["IsLocal"]);
}
Just in case the question is titled wrong i.e. he wants to find the databases in the particular instance:
using System;
using Microsoft.SqlServer.Management.Smo;
using System.Data;
using System.Windows.Forms;
namespace ConsoleApplication1
{
class Program
{
static void Main()
{
Server sr = new Server("MACHINE_NAME\\INSTANCE_NAME");
try
{
foreach (Database db in sr.Databases)
{
Console.WriteLine(db.Name);
}
Console.Read();
}
catch (Exception Ex)
{
MessageBox.Show(Ex.ToString());
}
}
}
}
Else Lucas Aardvark answer is most appropriate.
using Microsoft.Win32;
RegistryKey rk = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\Microsoft\Microsoft SQL Server");
String[] instances = (String[])rk.GetValue("InstalledInstances");
if (instances.Length > 0)
{
foreach (String element in instances)
{
Console.WriteLine(element); // element is your server name
}
}