Summary: is it possible to specify a port to use when querying WMI using System.Management;
I have a python script under Linux that queries, using WBEM, classes on a number of ESXi servers to check for warnings or errors on various subsystems. Previously, separately, I have written a WPF application that queries a number of WinTel boxes for their disk consumption etc. using WMI.
I am wanting to write a new WPF application that will perform the same function as the script and I thought I would be able to do this with WMI. Below is my testing code with the error handling removed for brevity, SetOptions is a private function that provides the username and password:
foreach (string hostname in Properties.Settings.Default.Hosts)
foreach (string WMIclass in Properties.Settings.Default.Classes)
{
ObjectQuery Query = new ObjectQuery("SELECT * FROM " + WMIclass);
ManagementObjectSearcher mos = GetMos(Query, hostname);
foreach (ManagementObject mo in mos.Get())
foreach (PropertyData pdc in mo.Properties)
Debug.WriteLine(pdc.Name + " \t\t: " + pdc.Value);
}
private ManagementObjectSearcher GetMos(ObjectQuery Query, string Hostname)
{
ConnectionOptions Options = SetOptions();
ManagementScope Scope = new ManagementScope("\\\\" + Hostname + "\\root\\cimv2", Options);
return new ManagementObjectSearcher(Scope, Query);
}
The trouble is I get a RPC unavailable on the remote server. I think that is because I am first trying to establish a RPC call on 135 which is not hosted by an ESX server. My question is how can one specify the port 5989 or is there something straightforward I can use in .net to perform what I need to do. Naively I'm thinking the class structure looks the same between WMI/WBEM surely it can be done :-/
System.Management can only be used to connect to other Windows machines running WMI, and doesn't support WBEM. The only C# WBEM client library I seen is http://code.google.com/p/wbemtools/, but it doesn't look very mature.
As said WMI Classes in .net don't support WBEM. In the end I ended up writing some code around the VMware.Vim.dll which has some good documentation on what I needed to do.
Related
I am programming a little script to change the IPv4 address of a specific Wireless80211 or Ethernet network interface. So far everything is working fine. The script sets the IPv4 with the command prompt and netsh (to control it with C# I use System.Diagnostics).
I want to add the feature, that the script disables or enables all Wireless80211 and Ethernet network interfaces (without a specific one) which you can find in "Control Panel>Network and Internet>Network Connections".
The script is mainly used for ArtNet to DMX to automatically prepare everything to use ArtNet (for people, which do not know anything of the Control Panel and to automate the workflow).
I have already tried it with the System.Net.NetworkInformation namespace, but I have only found a way to get enabled network interfaces. As soon as I disable an interface System.Net.NetworkInformation does not show this interface.
I wasn't aware that NetworkInterface.GetAllNetworkInterfaces() didn't return disabled interfaces.
Anyway, you could try using the WMI api via System.Management.dll that's available in the .NET framework (you must add this reference to your project), I did a test and it allows you to interact even with disabled network interfaces.
The following example give you an idea of how to work with WMI via this api, I pretty much extracted it from the documentation:
using System;
using System.Management;
...
void ListNetworkAdapters()
{
var query = new ObjectQuery("SELECT * FROM Win32_NetworkAdapter");
using (var searcher = new ManagementObjectSearcher(query))
{
var queryCollection = searcher.Get();
foreach (var m in queryCollection)
{
Console.WriteLine("ServiceName : {0}", m["Name"]);
Console.WriteLine("MACAddress : {0}", m["Description"]);
Console.WriteLine();
}
Console.ReadLine();
}
}
The documentation can be found here:
https://learn.microsoft.com/en-us/windows/desktop/cimwin32prov/win32-networkadapter
NetworkInterface.GetAllNetworkInterfaces()
Then check the OperationalStatus property
https://learn.microsoft.com/en-us/dotnet/api/system.net.networkinformation.networkinterface?view=netframework-4.7.2
I'm trying to disconnect network connections which are not mapped to a local drive (e.g. net use \server\share).
I know the command net use U: /D to delete a network connection which is mapped to U:.
Now I want to disconnect that connection using it's UNC Path (e.g. net use \server\ /D).
I want to implement this in a C# Application using the Windows Networking API (WNetCancelConnection-Function) but this function can't handle the UNC Path, too.
I receive all connected UNC Paths with the following code:
var searcher = new ManagementObjectSearcher(
"SELECT * FROM Win32_NetworkConnection");
foreach (ManagementObject queryObj in searcher.Get())
{
Console.WriteLine(queryObj["RemoteName"]);
Console.WriteLine(queryObj["RemotePath"]);
}
Console.ReadKey();
Hope so can help me solving that problem.
Edit:
i = WNetCancelConnection2A(ls_ShareName, iFlags, 1);
ls_ShareName = "\\server\share" (escaped)
iFlags = 0
results in: This network connection does not exist.
I'm 100% sure that my "shareName" is correct... also net use \server\share /D does not work.
Not sure where can be your problem without seeing your code. But after
net use \\192.168.1.45\ipc$
the following code
#include "windows.h"
void main(void){
WNetCancelConnection2("\\\\192.168.1.45\\ipc$",0,TRUE);
}
disconnects the resource without problems.
What's the best way to reset network connections using C#/.NET?
My company has several machines out with customers that connect by various means (3G, wifi, ethernet cable) and sometimes (especially with 3G) are reporting to Windows that they're still connected when they're not. I have a way to check if the connection is really live, but I'm struggling to reset them. Here's one problem:
var searcher = new ManagementObjectSearcher("select * from Win32_NetworkAdapter");
var managementObject = searcher.Get();
foreach (ManagementObject obj in managementObject)
{
var name = obj.Properties["Name"].Value.ToString();
Console.WriteLine(name);
obj.InvokeMethod("Disable", null);
obj.InvokeMethod("Enable", null);
}
As you can see, that will go through ALL network adapters and reset them, which I don't want to do. Furthermore, some adapters won't accept the null parameter.
I can get the NetworkInterface objects I want with this:
var interfaces = NetworkInterface.GetAllNetworkInterfaces().Where(ni => ni.IsReceiveOnly == false &&
ni.OperationalStatus == OperationalStatus.Up && ni.NetworkInterfaceType != NetworkInterfaceType.Loopback);
But the NetworkInterface class seems to have no Start(), Stop(), Reset() etc methods. Where do I go from here?
After some searching and experimentation, I found this blog post:
Disable/Enable Network Connections Under Vista
It is a much better approach.
The just of it, is to use a utility called mgmtclassgen.exe to generate a wrapper class around the WMI Win32_NetworkAdapter class. Use the following command in a developer command prompt at the folder of your choosing:
mgmtclassgen Win32_NetworkAdapter -p NetworkAdapter.cs
After you've generated NetworkAdapter.cs you can import it into a new project, add System.Management.dll to your project references, and use the following code to disable or enable an adapter of your choosing:
SelectQuery query = new SelectQuery("Win32_NetworkAdapter", "NetConnectionStatus=2");
ManagementObjectSearcher search = new ManagementObjectSearcher(query);
foreach(ManagementObject result in search.Get())
{
NetworkAdapter adapter = new NetworkAdapter(result);
// Identify the adapter you wish to disable here.
// In particular, check the AdapterType and
// Description properties.
// Here, we're selecting the LAN adapters.
if (adapter.AdapterType.Equals("Ethernet 802.3"))
{
adapter.Disable();
}
}
Also keep in mind, your program will have to be run as an administrator on any systems where UAC is enabled - to do this it is recommended to create an application manifest. You can do that by changing the requestedExecutionLevel entry in your manifest file to this:
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
Might be a bit simplistic, but could you call ipconfig /renew from a new process?
Process.Start("ipconfig", "/renew");
Alternatively, this similar question talks about using netsh, which I guess you could call from a process too How to disable (or reset) a network adapter programmatically in C#
You need Win32 API :
GetExtendedTcpTable : Get all exists tcp connection.
SetTcpEntry : Change tcp connection state.
Example code:
MIB_TCPROW row = new MIB_TCPROW();
row.dwState = TcpState.DeleteTcb;
row.dwLocalAddr = ...;
row.dwLocalPort = ...;
row.dwRemoteAddr = ...;
row.dwRemotePort = ...;
SetTcpEntry(ref row);
I have been working on a small WMI Info grabber for my job as I work with hundreds of servers and being able to grab certain information can be quite beneficial when having to get it on more than 5 servers.
List<string> output = new List<string>();
ObjectQuery query = new ObjectQuery("SELECT * FROM ComputerSystem");
ManagementObjectSearcher objectSearcher = new ManagementObjectSearcher(ServerConnect.HardwareScope, query);
ManagementObjectCollection retObject = objectSearcher.Get();
foreach (ManagementObject manObj in retObject)
{
string[] data = ((string)manObj["Description"]).Split('-');
string IPMI = data[1].Substring(7);
string firmware = data[2].Substring(5);
output.Add("IPMI Version: " + IPMI);
output.Add("BMC Firmware Version: " + firmware);
}
return output;
This is currently what I am using to grab some basic data from the ComputerSystem, this which works on some servers but crashes on others obtains the correct information that I am wanting; however, I need to prevent it from crashing with a COMException.
It says it breaks out with the System.Runtime.InteropServices.COMException at the following line of code:
foreach (ManagementObject manObj in retObject)
I have been trying to solve this issue as to why some servers get this exception returned rather than being able to grab the information and if it is possible to fix it.
I have been trying to fix this for the last couple weeks and have finally decided to ask for help about this specific problem that I am having.
UPDATE
I have ran the same name space and selection for the servers giving me issues in WMI Code Creator ( http://www.microsoft.com/en-us/download/confirmation.aspx?id=8572 ) and it is able to obtain the data I need however when ran through my program it gives the COMException. I have gone over the code that Code Creator makes, and my code and have modified some of it and it still gives me the error.
Ideally I want to do this inside of C# so I'm including the C# tag.
I have several Window Communication Foundation Services that are running and open up TCP ports (one each) using System.ServiceModel.ServiceHost. I have a listing of the port numbers that are being using but I want to use the running service to map from the port number to the executable.
I have tried to use netstat, TCPView, and few other similar tools I've found trying to search this solution but nothing display my process, the closest I can get is the System (PID 4).
All of these are Windows WCF Services, operate as intended, and do show up in netstat and TCPView (by port number) but can only supply the "System" as the process.
The code is being managed by several different departments, so I'm not considering an common interface approach as a valid solution. I do have full admin rights to the machine.
The WCF provides a WMI interface for diagnostics which you should be able to use in order to associate a WCF service port with a particular process. In particular the Service class looks promising.
(Please feel free to attach your example code here as discussed, or post it as another answer.)
Adding my sample code to #HarryJohnston's answer:
String wcfNamespace = String.Format(#"\\{0}\Root\ServiceModel", "MachineName");
ConnectionOptions connection = new ConnectionOptions();
connection.Authentication = AuthenticationLevel.PacketPrivacy;
ManagementScope scope = new ManagementScope(wcfNamespace, connection);
scope.Connect();
ObjectQuery query = new ObjectQuery("Select * From Service");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
ManagementObjectCollection queryCollection = searcher.Get();
ManagementObject[] listing = queryCollection.OfType<ManagementObject>().ToArray();
Dictionary<int, int> portToPID = new Dictionary<int, int>();
foreach (ManagementObject mo in queryCollection)
{
//each of services only have one base address in my example
Uri baseAddress = new Uri(((Array)mo.Properties["BaseAddresses"].Value).GetValue(0).ToString());
int pid = Int32.Parse(mo.Properties["ProcessId"].Value.ToString());
portToPID.Add(baseAddress.Port, pid);
}
Also requires add this to each service .config, not WMI Client
<system.serviceModel>
…
<diagnostics wmiProviderEnabled="true" />
…
</system.serviceModel>