Consider domain of all windows based computers. from these computers i want to detect only windows server 2003 computers.
I have all machine names of all machines in domain. then how to determine OS version from machine name. I have used Environment.OSVersion to get os version of local computer. How can i obtain OS version of remote computer if i know remote computer name ?
You can use WMI (Windows Management Instrumentation) to access the remote computer's
Win32_OperatingSystem class instance.
using (var mc = new ManagementClass(#"\\" + computerName + #"\root\cimv2:Win32_OperatingSystem"))
{
foreach (var obj in mc.GetInstances())
{
if (((bool)obj.Properties["Primary"].Value))
{
int productType = (int)obj.Properties["ProductType"].Value;
string version = obj.Properties["Version"].Value.ToString();
bool isServer = (productType == 2 || productType == 3); // "Domain Controller" or "Server
if (version == "5.2.3790" && isServer)
{
// "Caption" should contain something like "Microsoft(R) Windows(R) Server 2003..."
// Please resist parsing that, however.
Console.WriteLine(obj.Properties["Caption"].Value);
}
}
}
}
For details on the properties and what values are available, see the MSDN pages for the Win32_OperatingSystem class.
Related
So far I have struggled to get MbnInterfaceManager working (see hresult from IMbnInterfaceManager::GetInterfaces when no MBN device exists), so instead I built and debugged an application with no problems from within Visual Studio 2015 that executed this WMI query in C# (see also the Win32_PerfFormattedData_Tcpip_NetworkInterface documentation):
string query = "SELECT * FROM Win32_PerfRawData_Tcpip_NetworkInterface";
ManagementObjectSearcher moSearch = new ManagementObjectSearcher(query);
ManagementObjectCollection moCollection = moSearch.Get();
But then when I deployed the application to Windows 8.1, I receive this error every time the query is executed:
System.Management.ManagementException: Invalid query
at System.Management.ManagementException.ThrowWithExtendedInfo(ManagementStatus errorCode)
at System.Management.ManagementObjectCollection.ManagementObjectEnumerator.MoveNext()
Does anyone have any suggestions on how to resolve this issue? How can I deploy an application so that it is able to use queries like this?
UPDATE:
Please note that I can build and run the above code (as part of a larger WPF application) from within Visual Studio 2015 on either Windows 7 or Windows 8.1, and I can deploy the same application using ClickOnce onto Windows 7 where it runs successfully. For some reason when I deploy this application using ClickOnce onto Windows 8.1, I get that Invalid query message.
I think what I have to do is make sure that the System.Management reference is set to "Copy Local" but I'm not able to test that right now. If anyone has any better ideas please feel free to let me know.
UPDATE:
It is not possible to use System.Management.dll on Windows 8.1 in the same way it is used on Windows 7 or Windows 10.
I've found that to perform operations similar to the ones I mentioned in my question on Windows 8.1 and Windows 8 phone you need to either get a Windows 8.1 developer license or on Windows 10 set your computer to "Developer Mode" so you can use the Windows.Networking.Connectivity namespace:
string connectionProfileInfo = string.Empty;
ConnectionProfile InternetConnectionProfile = NetworkInformation.GetInternetConnectionProfile();
if (InternetConnectionProfile == null)
{
rootPage.NotifyUser("Not connected to Internet\n", NotifyType.StatusMessage);
}
else
{
connectionProfileInfo = GetConnectionProfile(InternetConnectionProfile);
OutputText.Text = connectionProfileInfo;
rootPage.NotifyUser("Success", NotifyType.StatusMessage);
}
// Which calls this function, that allows you to determine how strong the signal is and the associated bandwidth
string GetConnectionProfile(ConnectionProfile connectionProfile)
{
// ...
if (connectionProfile.GetSignalBars().HasValue)
{
connectionProfileInfo += "====================\n";
connectionProfileInfo += "Signal Bars: " + connectionProfile.GetSignalBars() + "\n";
}
// ...
}
Please note that you have to make sure your project is either a Window 8.1 PCL or a Windows 8.1 app to be able to reference the namespace.
For details please see https://code.msdn.microsoft.com/windowsapps/network-information-sample-63aaa201
UPDATE 2:
To be able to get bandwidth on Windows 7, 8.1 and 10, I ended up using this code:
private int GetMaxBandwidth()
{
int maxBandwidth = 0;
NetworkInterface[] networkIntrInterfaces = NetworkInterface.GetAllNetworkInterfaces();
foreach (var networkInterface in networkIntrInterfaces)
{
IPv4InterfaceStatistics interfaceStats = networkInterface.GetIPv4Statistics();
int bytesSentSpeed = (int)(interfaceStats.BytesSent);
int bytesReceivedSpeed = (int)(interfaceStats.BytesReceived);
if (bytesSentSpeed + bytesReceivedSpeed > maxBandwidth)
{
maxBandwidth = bytesSentSpeed + bytesReceivedSpeed;
}
}
}
I'm trying to get number of physical USB ports of PC for different Windows operating systems. To start with it seemed like an easy task but now I'm getting desperate.
Maybe this question is not even valid since I don't know how USB ports are treated on hardware level.
I thought using WMI(C) and ManagementObjectSearcher would be the right path to take and it returned right values... on certain operating systems. Or that's what I thought.
For example, I tried the following:
// >wmic path win32_usbhub get name
private const string UsbProperty = "Name";
private const string UsbPath = "Win32_USBHub";
private const string UsbPortName = "USB ROOT HUB";
...
// Get USB Ports
public IEnumerable<string> GetUsbPorts()
{
// All from Win32_USBHub where name contains USB ROOT HUB
return GetManagementObjectValues(UsbProperty, UsbPath).Where(name =>
CultureInfo.CurrentCulture.CompareInfo.IndexOf(
name, UsbPortName, CompareOptions.IgnoreCase) >= 0);
}
.
// Query
private static IEnumerable<string> GetManagementObjectValues(
string properties, string path, Func<object, string> formatter = null)
{
var values = new List<string>();
string query = string.Format("SELECT {0} FROM {1}", properties, path);
var search = new ManagementObjectSearcher(query);
try
{
foreach (ManagementObject item in search.Get())
{
string value = string.Empty;
foreach (string property in properties.Split(',')
.Select(prop => prop.Trim()))
{
if (item[property] == null)
continue;
if (value.Length > 0)
value += " ";
if (formatter != null)
value += formatter(item[properties]);
value += item[property].ToString();
}
values.Add(value.TrimEnd());
}
}
catch (Exception e)
{
if (e is ManagementException)
Logger.Warn(string.Format(
"Can't extract {0} properties of {1}", properties, path), e);
else
Logger.Error(e);
}
return values.Count >= 1 ? values : new List<string> { DefaultValue };
}
This seemed to get me the right amount on Windows8 but on WindowsXP it was totally off.
Next, I tried (for example) the following. I noticed that on Win8 I have USB<number> as ExternalReferenceDesignator but on WinXP, there's plain USB as InternalReferenceDesignator and external is empty.
For XP this seemed to work just fine but then again on Win8 amount of ports was six (6). Actual port count is 3 and with docking station station seven (7).
// >wmic path Win32_PortConnector get ExternalReferenceDesignator,InternalReferenceDesignator
private const string UsbPortName = "USB";
private const string PortProperties =
"ExternalReferenceDesignator, InternalReferenceDesignator";
private const string PortPath = #"Win32_PortConnector";
...
public IEnumerable<string> GetEthernetPorts()
{
// All where external includes USB or internal equals USB
return GetManagementObjectValues(PortProperties, PortPath).Where(name =>
CultureInfo.CurrentCulture.CompareInfo.IndexOf(
name, UsbPortName, CompareOptions.IgnoreCase) >= 0 ||
string.Compare(name, UsbPortName, StringComparison.OrdinalIgnoreCase) == 0);
}
So is it even possible or am I just looking from the wrong place?
And to answer my own question: No, it's not possible.
WMIC query results for Win32_USBController (or some related path) might seem right but you can't draw any conclusions from them. Information about connectors aren't stored on the baseboard or any other location either.
For example an old Dell Latitude D830 with Windows XP SP3 has three (3) physical connectors but WMIC and USBView.exe shows results below:
C:\>wmic path win32_usbcontroller get caption
Caption
Intel(R) ICH8 Family USB Universal Host Controller - 2834
Intel(R) ICH8 Family USB Universal Host Controller - 2835
Intel(R) ICH8 Family USB2 Enhanced Host Controller - 283A
Intel(R) ICH8 Family USB Universal Host Controller - 2830
Intel(R) ICH8 Family USB Universal Host Controller - 2831
Intel(R) ICH8 Family USB Universal Host Controller - 2832
Intel(R) ICH8 Family USB2 Enhanced Host Controller - 2836
I know it has been a while since the question was asked, but I just happened to be working on a USB port tree for a support app of some sort.
Initially, I tried to use Win32..., as much as it is not intended to be used as a source of information for the rebuilding of the device tree, the answer of this post explains some possibilities (Get List of connected USB Devices).
I played with it but I did not like it. UsbView by itself was also not an option (lack of skill in C ). Luckily I found NativeUsbLib. It provides you with a USB device tree, you just need to understand how to read it. Not a physical USB port This image shows a port that clearly states it is not possible to use it. In addition to that parameter, there is "Companion Hub Symbolic Link Name", in my experience, it has to be present on a valid USB port.
As for multiple controllers, and even multiple ports in one controller that satisfy my previous statement, there is an explanation. Multiple ports for same physical port, in my case, ports 1 and 13 are the same. If a device is 1.1 or 2.0 it will show under port 1, and if it supports 3.0 it will show up under port 13. And same goes for two controllers, they don't have 100% the same structure, but once you strip unnecessary data, and merge data (not necessarily all of it) that is left, the result will be a USB port tree. I can't guarantee all of the statements are true, but that is my current experience, and I might update this post. If not, feel free to message me if you have some questions. Btw. NativeUsbLib by default does not provide data for ports that don't have a device present (plugged in). To fix that, comment out lines in DeviceFactory that check if the device is present (line 35).
Hope this helps someone and sorry for my spelling, I am sure I messed up somewhere...
This has been an issue I have been looking to for two days. I will share my findings.
I am currently working on an in-house license management system for our software. It's nothing too fancy - as long as it can uniquely identify a user, it's good enough. Our mechanism currently relies on user sign-in + password + MAC address.
99% of the users so far have had no issues, but there is a small subset, the 1%, that has been returning an issue. This 1% is so important to us, because one failure means one hole in our system, something we would like to weed out. Okay - onto the main topic.
Method 1:
public static string returnMAC1()
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("Select MACAddress, PNPDeviceID FROM Win32_NetworkAdapter WHERE MACAddress IS NOT NULL AND PNPDEVICEID IS NOT NULL");
ManagementObjectCollection mObject = searcher.Get();
foreach (ManagementObject obj in mObject)
{
string pnp = obj["PNPDeviceID"].ToString();
if (pnp.Contains("PCI\\"))
{
string mac = obj["MACAddress"].ToString();
mac = mac.Replace(":", string.Empty);
return mac;
}
}
return "Nothing happened...";
}
Method 1 retrieves the MAC address based on the fact that the physical card is connected to the PCI interface.
Method 2:
public static string returnMAC2()
{
string mac = string.Empty;
foreach (System.Net.NetworkInformation.NetworkInterface nic in System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces())
{
if (nic.OperationalStatus == System.Net.NetworkInformation.OperationalStatus.Up)
{
macAddresses += nic.GetPhysicalAddress().ToString();
break;
}
}
return mac;
}
The second method is a standard method retrieved from MSDN documentation in-regards to MAC addresses.
Based on some tests, it seems the second method is a tad unreliable to retrieve MAC addresses, since it retrieves the wireless card's address. We've had some users returning null addresses as a result of using that method, and while I don't know why that would happen, it could be because there's a lack of a wireless card in their computers. With that said, that's only conjecture. Method #1 relies on using SQL queries to retrieve the PCI MAC. This one has been reliable.
Tests:
Using a Windows 8.1 Enterprise Evaluation edition (free 90-day trial, yay!) installed onto the VirtualBox VM, the tests confirmed that there are major differences in the MAC addresses returned via the guest VM and the host VM.
According to my research, in most cases, the virtual machine is assigned the same MAC address every time it is powered on, so long as the virtual machine is not moved and no changes are made to the certain settings in the configuration file. With that said, and here's the bad news... The guest VM MAC could be anything. So it seems, this is one of the reasons the MAC addresses are inconsistent when used as unique identifiers, which is an issue I found out when some users were on their company VMs. I never knew that's the way people worked, but here we are, so no gloating about it at this point.
My question is - is there any way, without making the user change any settings on their end, to retrieve the host VM's MAC as opposed to the guest VM?
At this point I don't see any reason why someone won't assign the same MAC to every single guest machine to get around our floating license mechanism. Retrieving the host VM MAC would get around this issue, as it would show as one MAC.
We decided this is both impossible and unnecessary. We also decided to use the motherboard UUID as the primary unique identifier, and falling back to the MAC address using the MAC address method below, in case the UUID returns a FFFF-FFFF....... on the rare occasion the vendor does not supply a UUID to that motherboard.
public static string returnMAC1()
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("Select MACAddress, PNPDeviceID FROM Win32_NetworkAdapter WHERE MACAddress IS NOT NULL AND PNPDEVICEID IS NOT NULL");
ManagementObjectCollection mObject = searcher.Get();
foreach (ManagementObject obj in mObject)
{
string pnp = obj["PNPDeviceID"].ToString();
if (pnp.Contains("PCI\\"))
{
string mac = obj["MACAddress"].ToString();
mac = mac.Replace(":", string.Empty);
return mac;
}
}
return "Nothing happened...";
}
I have an application that requires to control mobile broadband API.
I am struggling on correctly installing the api on my devices.
I've been follow the instructions in this document:
http://www.google.be/url?sa=t&rct=j&q=&esrc=s&frm=1&source=web&cd=1&cad=rja&ved=0CC0QFjAA&url=http%3A%2F%2Fdownload.microsoft.com%2Fdownload%2F7%2FE%2F7%2F7E7662CF-CBEA-470B-A97E-CE7CE0D98DC2%2FMB_ManagedCode.docx&ei=kyvmUs7jE4e60QWbooHYDg&usg=AFQjCNG6yaGf4sRhdbWI99fE7tmQX8cmnA&sig2=2Fg-_DRYBIselKR19wTq2Q
and trying to combine the steps with this stackoverflow explanation
C# Read Windows Mobile Broadband connection properties
I have been able to lay a reference from visual studio to mbnapi.tlb in V7.0/lib. and I automatically now have a interop.mbnapi.tlb in my obj/debug folder.
When trying to "check the SIM is inserted and working / activated". => my code crashes on the following line
IMbnInterface[] mobileInterfaces = mbnInfMgrInterface.GetInterfaces() as IMbnInterface[];
When I run it on windows 8, mbnInfMgrInterface == null
I have already tried to install the same SDK on windows 8 as stated in the requirements of the document but the SDK is only meant for windows 7...
I have tried to register the mbnapi in windows 8 by performing
Regtlibv12 Mbnapi.tlb
no luck whatsoever...
what do I need to do to get this to work please?
anyone has some experience in this?
EDIT. on windows 7 (my development machine), I get the message "Device not ready", I think this is normal because I don't have mobile broadband on it, on windows 8 I do, but there the mobile interface manager is null => mbnInfMgrInterface == null.
thank you,
Not sure exactly what you are after, but after struggling with IMbnInterface and GetSignalStrength() (see https://msdn.microsoft.com/en-us/library/windows/desktop/dd323166(v=vs.85).aspx) and being unsuccessful, I found that you can obtain a lot of info using WMI:
int maxBandwidth = 0;
string query = "SELECT * FROM Win32_PerfRawData_Tcpip_NetworkInterface";
ManagementObjectSearcher moSearch = new ManagementObjectSearcher(query);
ManagementObjectCollection moCollection = moSearch.Get();
foreach (ManagementObject mo in moCollection)
{
if (Convert.ToInt32(mo["CurrentBandwidth"]) > maxBandwidth)
{
// Instead of CurrentBandwidth you may want to use BytesReceivedPerSec
maxBandwidth = Convert.ToInt32(mo["CurrentBandwidth"]);
}
}
Please see answer here: Determining the network connection link speed and here is the list of properties you can obtain: https://msdn.microsoft.com/en-us/library/aa394293(VS.85).aspx
UPDATE:
Please note that I can build and debug the above code (as part of a larger WPF application) from within Visual Studio 2015 on either Windows 7 or Windows 8.1, and I can deploy the same application onto Windows 7 where it runs successfully. For some reason when I deploy this application on Windows 8.1, I get an Invalid query message.
UPDATE 2:
Please note that I found you cannot get the network info in Windows 8.1 in the same way as you do in Windows 7, in that the System.Management namespace is not available on Windows 8.1. See https://code.msdn.microsoft.com/windowsapps/network-information-sample-63aaa201
string connectionProfileInfo = string.Empty;
ConnectionProfile InternetConnectionProfile = NetworkInformation.GetInternetConnectionProfile();
if (InternetConnectionProfile == null)
{
rootPage.NotifyUser("Not connected to Internet\n", NotifyType.StatusMessage);
}
else
{
connectionProfileInfo = GetConnectionProfile(InternetConnectionProfile);
OutputText.Text = connectionProfileInfo;
rootPage.NotifyUser("Success", NotifyType.StatusMessage);
}
// Which calls this function, that allows you to determine how strong the signal is and the associated bandwidth
string GetConnectionProfile(ConnectionProfile connectionProfile)
{
// ...
if (connectionProfile.GetSignalBars().HasValue)
{
connectionProfileInfo += "====================\n";
connectionProfileInfo += "Signal Bars: " + connectionProfile.GetSignalBars() + "\n";
}
// ...
}
Is there any API for writing a C# program that could interface with Windows update, and use it to selectively install certain updates?
I'm thinking somewhere along the lines of storing a list in a central repository of approved updates. Then the client side applications (which would have to be installed once) would interface with Windows Update to determine what updates are available, then install the ones that are on the approved list. That way the updates are still applied automatically from a client-side perspective, but I can select which updates are being applied.
This is not my role in the company by the way, I was really just wondering if there is an API for windows update and how to use it.
Add a Reference to WUApiLib to your C# project.
using WUApiLib;
protected override void OnLoad(EventArgs e){
base.OnLoad(e);
UpdateSession uSession = new UpdateSession();
IUpdateSearcher uSearcher = uSession.CreateUpdateSearcher();
uSearcher.Online = false;
try {
ISearchResult sResult = uSearcher.Search("IsInstalled=1 And IsHidden=0");
textBox1.Text = "Found " + sResult.Updates.Count + " updates" + Environment.NewLine;
foreach (IUpdate update in sResult.Updates) {
textBox1.AppendText(update.Title + Environment.NewLine);
}
}
catch (Exception ex) {
Console.WriteLine("Something went wrong: " + ex.Message);
}
}
Given you have a form with a TextBox this will give you a list of the currently installed updates. See http://msdn.microsoft.com/en-us/library/aa387102(VS.85).aspx for more documentation.
This will, however, not allow you to find KB hotfixes which are not distributed via Windows Update.
The easiest way to do what you want is using WSUS. It's free and basically lets you setup your own local windows update server where you decide which updates are "approved" for your computers. Neither the WSUS server nor the clients need to be in a domain, though it makes it easier to configure the clients if they are. If you have different sets of machines that need different sets of updates approved, that's also supported.
Not only does this accomplish your stated goal, it saves your overall network bandwidth as well by only downloading the updates once from the WSUS server.
If in your context you're allowed to use Windows Server Update Service (WSUS), it will give you access to the Microsoft.UpdateServices.Administration Namespace.
From there, you should be able to do some nice things :)
P-L right. I tried first the Christoph Grimmer-Die method, and in some case, it was not working. I guess it was due to different version of .net or OS architecture (32 or 64 bits).
Then, to be sure that my program get always the Windows Update waiting list of each of my computer domain, I did the following :
Install a serveur with WSUS (may save some internet bandwith) : http://www.microsoft.com/en-us/download/details.aspx?displaylang=en&id=5216
Add all your workstations & servers to your WSUS server
Get SimpleImpersonation Lib to run this program with different admin right (optional)
Install only the administration console component on your dev workstation and run the following program :
It will print in the console all Windows updates with UpdateInstallationStates.Downloaded
using System;
using Microsoft.UpdateServices.Administration;
using SimpleImpersonation;
namespace MAJSRS_CalendarChecker
{
class WSUS
{
public WSUS()
{
// I use impersonation to use other logon than mine. Remove the following "using" if not needed
using (Impersonation.LogonUser("mydomain.local", "admin_account_wsus", "Password", LogonType.Batch))
{
ComputerTargetScope scope = new ComputerTargetScope();
IUpdateServer server = AdminProxy.GetUpdateServer("wsus_server.mydomain.local", false, 80);
ComputerTargetCollection targets = server.GetComputerTargets(scope);
// Search
targets = server.SearchComputerTargets("any_server_name_or_ip");
// To get only on server FindTarget method
IComputerTarget target = FindTarget(targets, "any_server_name_or_ip");
Console.WriteLine(target.FullDomainName);
IUpdateSummary summary = target.GetUpdateInstallationSummary();
UpdateScope _updateScope = new UpdateScope();
// See in UpdateInstallationStates all other properties criteria
_updateScope.IncludedInstallationStates = UpdateInstallationStates.Downloaded;
UpdateInstallationInfoCollection updatesInfo = target.GetUpdateInstallationInfoPerUpdate(_updateScope);
int updateCount = updatesInfo.Count;
foreach (IUpdateInstallationInfo updateInfo in updatesInfo)
{
Console.WriteLine(updateInfo.GetUpdate().Title);
}
}
}
public IComputerTarget FindTarget(ComputerTargetCollection coll, string computername)
{
foreach (IComputerTarget target in coll)
{
if (target.FullDomainName.Contains(computername.ToLower()))
return target;
}
return null;
}
}
}