C++ WMI - Fetch local IP address - c++

I'm trying to fetch the local IP via WMI ManagementObject but I get only empty/null strings.
With a call from PowerShell:
Get-WmiObject -Class Win32_NetworkAdapterConfiguration
I get 13 elements 2 of which with a valid IP address.
But with the following code, passing
"Win32_NetworkAdapterConfiguration" as hardwareClass and
"IPAddress" as propertyName:
void propertyValueLocal(String^ hardwareClass, String^ propertyName)
{
ManagementObjectSearcher^ searcher = gcnew ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM " + hardwareClass);
ManagementObjectCollection^ collection = searcher->Get();
for each (ManagementObject^ object in collection)
{
if (object[propertyName] != nullptr)
Console::WriteLine(object[propertyName]);
}
}
I get:
System.String[]
System.String[]
Any help would be appreciated.

Related

What is the correct way to get the client's IP address in Crow (C++ library)?

I am using Crow (C++ server library) and trying to get the client's IP address.
I found this answer, Getting the client IP address: REMOTE_ADDR, HTTP_X_FORWARDED_FOR, what else could be useful?, so I have tried:
CROW_ROUTE(app, "/mine")([](const crow::request& req, crow::response& res)
{
std::string ip_address = req.get_header_value("REMOTE_ADDR");
res.write(req.get_header_value("HTTP_X_FORWARDED_FOR"));
res.write(req.get_header_value("HTTP_CLIENT_IP"));
res.write(req.get_header_value("HTTP_X_FORWARDED"));
res.write(req.get_header_value("HTTP_X_CLUSTER_CLIENT_IP"));
res.write(req.get_header_value("HTTP_FORWARDED_FOR"));
res.write(req.get_header_value("HTTP_FORWARDED"));
for( auto head : req.headers )
{
res.write(head.first);
res.write(" = ");
res.write(head.second);
res.write( "<br/>" );
}
res.end();
});
But all of those header fields are blank. Is there another way to get the IP address or is my browser just not sending the required information?
This worked for me:
std::string str_IP_and_PortNumber("");
auto itr = req.headers.find("Host");
if (itr != req.headers.end())
{
str_IP_and_PortNumber = itr->second;
}
Actually, not sure if this is what you need - this gets the IP and port number of the server, as seen by the client. In case you need something different, just view the req.headers tree in the debug view window and find the string key of your interest.

Invoking a method thtough C#

I am trying to get some data from the UWF_Volume WMI provider. Please see the following link,
https://msdn.microsoft.com/en-us/library/jj979756(v=winembedded.81).aspx
More specifically I am trying to get the exclusion files using the following class,
UInt32 GetExclusions([out, EmbeddedInstance("UWF_ExcludedFile")] string ExcludedFiles[]);
I am not familiar with out parameters but from a research I can understand that acts as a reference argument. So I wrote the following method,
public void getUWFExclusions()
{
{
string computer = ".";
ManagementScope scope = new ManagementScope(#"\\" + computer + #"\root\standardcimv2\embedded");
ManagementClass cls = new ManagementClass(scope.Path.Path, "UWF_Volume", null);
foreach (MethodData m in cls.Methods)
{
richTextBox1.AppendText("The class contains this method:" + m.Name + "\n");
}
ManagementBaseObject outParams;
foreach (ManagementObject mo in cls.GetInstances())
{
outParams = mo.InvokeMethod("GetExclusions", null, null);
richtextbox1.appendtext(string.format("ExcludedFiles" + mo[ExcludedFiles]));
}
}
catch (Exception e)
{
richTextBox1.AppendText(e.ToString());
}
}
The problem is that the line,
richtextbox1.appendtext(string.format("ExcludedFiles" + mo[ExcludedFiles]));
returns "Not Found"
I appreciate any help to debug this problem.
I guess you are missing the Object Query that actually gets data via call to WMI. I am not sure about windows 8 but till 7 we used to get data by WQL and that is not there in above code.

c# NetworkInterface.GetAllNetworkInterfaces vs WMI Win32_NetworkAdapter

I get a InterfaceIndex with GetBestInterface (iphlpapi.dll).
The goal : read other interface properties.
This WMI query is slow :
SELECT MACAddress,Name,GUID,NetConnectionID FROM Win32_NetworkAdapter WHERE InterfaceIndex=
In C# there is, faster,
NetworkInterface.GetAllNetworkInterfaces()
but each NetworkInterface hasn't the property InterfaceIndex ( sic ! ).
I don't know how to optimize this :
EnumerationOptions wmi_options = new EnumerationOptions();
wmi_options.Rewindable = false;
wmi_options.ReturnImmediately = true;
string wql = "SELECT MACAddress,Name,GUID,NetConnectionID FROM Win32_NetworkAdapter WHERE InterfaceIndex=" + iface;
ManagementObjectCollection recordset = new ManagementObjectSearcher(#"root\cimv2", wql, wmi_options).Get();
foreach (ManagementObject mo in recordset)
The options don't seem to help.
Can I split the operations and cache any step ?
Or another path : avoid WMI and lookup the interface ( with InterfaceIndex ) from the registry ?
HKLM\SYSTEM\CurrentControlSet\Services\tcpip\Parameters\Interfaces
HKLM\SYSTEM\CurrentControlSet\Control\Network{4D36E972-E325-11CE-BFC1-08002BE10318}
i dont know if this is actually faster but have you tried powershell?
string IfIndex = "15";
string psscript = "get-netadapter | Where-Object interfaceindex -eq " + IfIndex;
PowerShell powershell = PowerShell.Create();
powershell.Runspace = RunspaceFactory.CreateRunspace();
powershell.Runspace.Open();
powershell.AddScript(psscript);
foreach (PSObject result in powershell.Invoke())
{
Console.WriteLine("Name: {0} " + "Status: {1}",result.Members["Name"].Value, result.Members["status"].Value);
}
Console.Read();
run this from your application, using System.Management.Automation &
System.Management.Automation.Runspaces;
i haven't tested the code yet, this is the top of my head.

How can I enumerate/list all installed applications in Windows XP?

When I say "installed application", I basically mean any application visible in [Control Panel]->[Add/Remove Programs].
I would prefer to do it in Python, but C or C++ is also fine.
If you mean the list of installed applications that is shown in Add\Remove Programs in the control panel, you can find it in the registry key:
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall
more info about how the registry tree is structured can be found here.
You need to use the winreg API in python to read the values from the registry.
Check out the Win32_Product WMI (Windows Management Instrumentation) class. Here's a tutorial on using WMI in Python.
Control Panel uses Win32 COM api, which is the official method (see Google Groups, Win32)
Never rely on registry.
The Microsoft Script Repository has a script for listing all installed software.
import win32com.client
strComputer = "."
objWMIService = win32com.client.Dispatch("WbemScripting.SWbemLocator")
objSWbemServices = objWMIService.ConnectServer(strComputer,"root\cimv2")
colItems = objSWbemServices.ExecQuery("Select * from Win32_Product")
for objItem in colItems:
print "Caption: ", objItem.Caption
print "Description: ", objItem.Description
print "Identifying Number: ", objItem.IdentifyingNumber
print "Install Date: ", objItem.InstallDate
print "Install Date 2: ", objItem.InstallDate2
print "Install Location: ", objItem.InstallLocation
print "Install State: ", objItem.InstallState
print "Name: ", objItem.Name
print "Package Cache: ", objItem.PackageCache
print "SKU Number: ", objItem.SKUNumber
print "Vendor: ", objItem.Vendor
print "Version: ", objItem.Version
The best registry-based implementation that I have seen is the one written by Chris Wright (chris128) posted at http://www.vbforums.com/showthread.php?t=598355. It uses multiple registry keys and is a lot more complex than any of the answers currently posted here. It seems to produce identical results to the Add/Remove Programs app, and like the ARP app it also provides an option to include updates.
Although it's implemented in VB.NET, it should be easy to convert to other .NET languages like C# or IronPython. I imagine that converting to IronPython first should make it fairly easy to port to regular Python if that's what you want, but I only converted it to C# myself and then cleaned up the code a bit.
Only one small bug to point out: GetUserInstallerKeyPrograms() doesn't add the version for user programs to the list, even though it extracts it. This is easy to fix though.
C#.net code for getting the list of installed software using WMI in xp and win7(wmi is the only way in win7)
WqlObjectQuery wqlQuery =
new WqlObjectQuery("SELECT * FROM Win32_Product");
ManagementObjectSearcher searcher =
new ManagementObjectSearcher(wqlQuery);
foreach (ManagementObject software in searcher.Get()) {
Console.WriteLine(software["Caption"]);
}
The OP mentioned XP and also mentioned Python, C or C++ but I found that a lot of information on the net about this topic is either incomplete or incorrect. An example of the latter is the suggestion to use WMI--specifically, the Win32_Product class; however, as is noted elsewhere, that method is slow, partly because, believe it or not, each MSI found actually runs its repair. I call that solution incorrect because of how painfully slow it is and because of its nasty side-effect. For instance, you have already opted to disable a program's Windows service but calling select * from Win32_Product, as part of ensuring that the MSI repair runs, will apparently re-enable the service.
For what it's worth, below is what I would consider to be the most complete example to date, albeit in C# (I compiled it against Framework 4.6.1 but lower versions may work too.) It lists 32-bit and 64-bit installed programs; it disposes registry keys that it uses and it runs in under a second, at least after caching kicks in. Improvements are welcome.
One thing it is still missing is some updates. For example, when I run it on my Windows 10 system and compare it with Control Panel | Programs and Features | Installed Updates, I notice that it does not show Security Update for Adobe Flash Player for some reason.
I don't have any good reason for the anonymous method, it's just how I was thinking at the time--a sort of method-within-a-method solution.
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.Win32;
class Program
{
static void Main(string[] args)
{
var result = InstalledProgram.GetAllInstalledPrograms();
result.Sort((a, b) => a.DisplayName.CompareTo(b.DisplayName));
foreach(var program in result)
{
if(!program.IsSystemComponent && !program.IsKB) Console.WriteLine(program.Dump());
}
}
}
public enum PlatformTypes
{
x86,
amd64
}
public class InstalledProgram
{
[DllImport("advapi32.dll")]
extern public static int RegQueryInfoKey(
Microsoft.Win32.SafeHandles.SafeRegistryHandle hkey,
StringBuilder lpClass,
ref uint lpcbClass,
IntPtr lpReserved,
IntPtr lpcSubKeys,
IntPtr lpcbMaxSubKeyLen,
IntPtr lpcbMaxClassLen,
IntPtr lpcValues,
IntPtr lpcbMaxValueNameLen,
IntPtr lpcbMaxValueLen,
IntPtr lpcbSecurityDescriptor,
out long lpftLastWriteTime
);
public string DisplayName { get; private set; }
public string UninstallString { get; private set; }
public string KBNumber { get; private set; }
public string DisplayIcon { get; private set; }
public string Version { get; private set; }
public DateTime InstallDate { get; private set; }
public PlatformTypes Platform { get; private set; }
public bool IsSystemComponent { get; private set; }
public bool IsKB { get { return !string.IsNullOrWhiteSpace(KBNumber); } }
public static List<InstalledProgram> GetAllInstalledPrograms()
{
var result = new List<InstalledProgram>();
Action<PlatformTypes, RegistryKey, string> getRegKeysForRegPath = (platform, regBase, path) =>
{
using(var baseKey = regBase.OpenSubKey(path))
{
if(baseKey != null)
{
string[] subKeyNames = baseKey.GetSubKeyNames();
foreach(string subkeyName in subKeyNames)
{
using(var subKey = baseKey.OpenSubKey(subkeyName))
{
object o;
o = subKey.GetValue("DisplayName");
string displayName = o != null ? o.ToString() : "";
o = subKey.GetValue("UninstallString");
string uninstallString = o != null ? o.ToString() : "";
o = subKey.GetValue("KBNumber");
string kbNumber = o != null ? o.ToString() : "";
o = subKey.GetValue("DisplayIcon");
string displayIcon = o != null ? o.ToString() : "";
o = subKey.GetValue("DisplayVersion");
string version = o != null ? o.ToString() : "";
o = subKey.GetValue("InstallDate");
DateTime installDate = o != null ? parseInstallDate(o.ToString()) : default(DateTime);
o = subKey.GetValue("SystemComponent");
bool isSystemComponent = o != null ? o.ToString() == "1" : false;
// Sometimes, you need to get the KB number another way.
if(kbNumber == "")
{
var match = Regex.Match(displayName, #".*?\((KB\d+?)\).*");
if(match.Success) kbNumber = match.Groups[1].ToString();
}
// Sometimes, the only way you can get install date is from the last write
// time on the registry key.
if(installDate == default(DateTime))
{
string keyFull = baseKey + "\\" + subkeyName + "\\DisplayVersion";
var sb = new StringBuilder(64);
uint sbLen = 65;
RegQueryInfoKey(
subKey.Handle
, sb
, ref sbLen
, IntPtr.Zero
, IntPtr.Zero
, IntPtr.Zero
, IntPtr.Zero
, IntPtr.Zero
, IntPtr.Zero
, IntPtr.Zero
, IntPtr.Zero
, out long lastWriteTime);
installDate = DateTime.FromFileTime(lastWriteTime);
}
if(displayName != "" && uninstallString != "")
{
result.Add(new InstalledProgram
{
DisplayName = displayName,
UninstallString = uninstallString,
KBNumber = kbNumber,
DisplayIcon = displayIcon,
Version = version,
InstallDate = installDate,
Platform = platform,
IsSystemComponent = isSystemComponent
});
}
}
}
}
}
};
getRegKeysForRegPath(PlatformTypes.amd64, Registry.LocalMachine, #"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall");
getRegKeysForRegPath(PlatformTypes.amd64, Registry.CurrentUser, #"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall");
if(Environment.Is64BitOperatingSystem)
{
getRegKeysForRegPath(PlatformTypes.x86, Registry.LocalMachine, #"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall");
getRegKeysForRegPath(PlatformTypes.x86, Registry.CurrentUser, #"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall");
}
return result;
}
public string Dump()
{
return Platform + "\t" + DisplayName + "\t" + InstallDate + "\t" + DisplayIcon + "\t" + Version + "\t" + KBNumber + "\t" + UninstallString;
}
private static DateTime parseInstallDate(string installDateStr)
{
DateTime.TryParseExact(
installDateStr
, format: "yyyyMMdd"
, provider: new System.Globalization.CultureInfo("en-US")
, style: System.Globalization.DateTimeStyles.None
, result: out DateTime result);
return result;
}
public override string ToString()
{
return DisplayName;
}
}
[Sigh] and then I saw #PolyTekPatrick's answer. How did I miss that?

WMI Remote connection

I have an issue regarding WMI connection through asp.net from Computer A (windows 2003 server) to Computer B (Windows XP)..
The error is as follows:
RPC server is unavailable..
There are a few steps that you must take in order to successfully leverage WMI connectivity. The basics are you must allow remote management on the target box of course. If you can’t RDP into it, chances are, you can’t remote manage anything else. This can also include Windows firewall issues too. Make sure your request can even get in at all.
Next, start simple. Can you even poll for the running processes on that box? Try to output all the running processes on the target box with System.Diagnostics.Process currentProcess = System.Diagnostics.Process.GetProcesses("machine-name"). If you can at least get some information on the box then the RPC message you are getting has to do with incorrect arguments being passed in, perhaps?
Anyways, I recently wrote a web application that allowed the users to find a server on the LAN and kill a target process there or start a new one. I did it in C# so the code snippet below is just what I used. It's not the best but its working in production right now:
public static class RemoteProcessAccess
{
public static void KillProcessByProcessID(string NameOfServer, string DomainName, string LogIn, string Password, int processID)
{
//#1 The vars for this static method
#region /// <variables> ...
string userName;
string password;
string machineName;
string myDomain;
Hashtable hs = new Hashtable();
ManagementScope mScope;
ConnectionOptions cnOptions;
ManagementObjectSearcher objSearcher;
ManagementOperationObserver opsObserver;
ManagementClass manageClass;
DirectoryEntry entry;
DirectorySearcher searcher;
DirectorySearcher userSearcher;
#endregion
//#2 Set the basics sent into the method
machineName = NameOfServer;
myDomain = DomainName;
userName = LogIn;
password = Password;
cnOptions = new ConnectionOptions();
cnOptions.Impersonation = ImpersonationLevel.Impersonate;
cnOptions.EnablePrivileges = true;
cnOptions.Username = myDomain + "\\" + userName;
cnOptions.Password = password;
mScope = new ManagementScope(#"\\" + machineName + #"\ROOT\CIMV2", cnOptions);
//#3 Begin Connection to Remote Box
mScope.Connect();
objSearcher = new ManagementObjectSearcher(String.Format("Select * from Win32_Process Where ProcessID = {0}", processID));
opsObserver = new ManagementOperationObserver();
objSearcher.Scope = mScope;
string[] sep = { "\n", "\t" };
//#4 Loop through
foreach (ManagementObject obj in objSearcher.Get())
{
string caption = obj.GetText(TextFormat.Mof);
string[] split = caption.Split(sep, StringSplitOptions.RemoveEmptyEntries);
// Iterate through the splitter
for (int i = 0; i < split.Length; i++)
{
if (split[i].Split('=').Length > 1)
{
string[] procDetails = split[i].Split('=');
procDetails[1] = procDetails[1].Replace(#"""", "");
procDetails[1] = procDetails[1].Replace(';', ' ');
switch (procDetails[0].Trim().ToLower())
{
//You could look for any of the properties here and do something else,
case "processid":
int tmpProc = Convert.ToInt32(procDetails[1].ToString());
//if the process id equals the one passed in....
//(this is redundant since we should have limited the return
//by the query where above, but we're paranoid here
if (tmpProc.Equals(processID))
{
obj.InvokeMethod(opsObserver, "Terminate", null);
}
break;
}//end process ID switch...
}//end our if statement...
}//end our for loop...
}//end our for each loop...
}//end static method
}
Look at KB875605 ("How to troubleshoot WMI-related issues in Windows XP SP2")
You could enable the RPC server on any target machine by running this on the target's command prompt:
[/code]
netsh firewall set service RemoteAdmin
[/code]
Worked for me at least. :)
Try to use wmic command line to get information from the remote computer, also you can install the code of Services+ and try to connect and debug your connection to the server, most likely it is firewall problem or RPC services is down or disabled.