Enumerating Network Sessions - c#

I wanted to pull data about the connected network users from the Computer Management -> Shared Folders -> Sessions tab into my c# application. Can anybody guide me on what namespaces have to be used along with some sample code to import username and ip address from Computer Management -> Shared Folders -> Sessions tab?
Regards

You want NetSessionEnum, which:
Provides information about sessions established on a server.
When passed a level of 502, it'll return an array of:
...the name of the computer; name of the user; open files, pipes, and devices on the computer; and the name of the transport the client is using.
Luckily for you, pinvoke.net has the necessary signatures and even some sample code. Here's a full featured sample:
public class Program {
public void Main(string[] args) {
IntPtr pSessionInfo;
IntPtr pResumeHandle = IntPtr.Zero;
UInt32 entriesRead, totalEntries;
var netStatus = NativeMethods.NetSessionEnum(
null, // local computer
null, // client name
null, // username
502, // include all info
out pSessionInfo, // pointer to SESSION_INFO_502[]
NativeMethods.MAX_PREFERRED_LENGTH,
out entriesRead,
out totalEntries,
ref pResumeHandle
);
try {
if (netStatus != NativeMethods.NET_API_STATUS.NERR_Success) {
throw new InvalidOperationException(netStatus.ToString());
}
Console.WriteLine("Read {0} of {1} entries", entriesRead, totalEntries);
for (int i = 0; i < entriesRead; i++) {
var pCurrentSessionInfo = new IntPtr(pSessionInfo.ToInt32() + (NativeMethods.SESSION_INFO_502.SIZE_OF * i));
var s = (NativeMethods.SESSION_INFO_502)Marshal.PtrToStructure(pCurrentSessionInfo, typeof(NativeMethods.SESSION_INFO_502));
Console.WriteLine(
"User: {0}, Computer: {1}, Type: {2}, # Open Files: {3}, Connected Time: {4}s, Idle Time: {5}s, Guest: {6}",
s.sesi502_username,
s.sesi502_cname,
s.sesi502_cltype_name,
s.sesi502_num_opens,
s.sesi502_time,
s.sesi502_idle_time,
s.sesi502_user_flags == NativeMethods.SESSION_INFO_502_USER_FLAGS.SESS_GUEST
);
}
} finally {
NativeMethods.NetApiBufferFree(pSessionInfo);
}
}
}
public sealed class NativeMethods {
[DllImport("netapi32.dll", SetLastError=true)]
public static extern NET_API_STATUS NetSessionEnum(
string serverName,
string uncClientName,
string userName,
UInt32 level,
out IntPtr bufPtr,
int prefMaxLen,
out UInt32 entriesRead,
out UInt32 totalEntries,
ref IntPtr resume_handle
);
[DllImport("netapi32.dll")]
public static extern uint NetApiBufferFree(IntPtr Buffer);
public const int MAX_PREFERRED_LENGTH = -1;
public enum NET_API_STATUS : uint {
NERR_Success = 0,
NERR_InvalidComputer = 2351,
NERR_NotPrimary = 2226,
NERR_SpeGroupOp = 2234,
NERR_LastAdmin = 2452,
NERR_BadPassword = 2203,
NERR_PasswordTooShort = 2245,
NERR_UserNotFound = 2221,
ERROR_ACCESS_DENIED = 5,
ERROR_NOT_ENOUGH_MEMORY = 8,
ERROR_INVALID_PARAMETER = 87,
ERROR_INVALID_NAME = 123,
ERROR_INVALID_LEVEL = 124,
ERROR_MORE_DATA = 234 ,
ERROR_SESSION_CREDENTIAL_CONFLICT = 1219
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct SESSION_INFO_502 {
public static readonly int SIZE_OF = Marshal.SizeOf(typeof(SESSION_INFO_502));
public string sesi502_cname;
public string sesi502_username;
public uint sesi502_num_opens;
public uint sesi502_time;
public uint sesi502_idle_time;
public SESSION_INFO_502_USER_FLAGS sesi502_user_flags;
public string sesi502_cltype_name;
public string sesi502_transport;
}
public enum SESSION_INFO_502_USER_FLAGS : uint {
SESS_GUEST = 1,
SESS_NOENCRYPTION = 2
}
}

You don't want to interact with Computer Management, you want to call the same functions it does and cut the middle man out of the loop.
For finding out about current network connection, you might be looking for WNetOpenEnum or NetConnectionEnum
I don't think there's a .NET function for this in the BCL, you'd have to use p/invoke or look for a third-party library (or my personal favorite, use C++/CLI to write a wrapper)

Related

Passing uint array to Dll to be populated (Nvidia NVML library)

I'm attempting to pass a uint array into the NVML function nvmlDeviceGetAccountingPids(Doc here) from C#, here's a minimum working sample of what I have so far:
{
public const string NVMLDLL = "nvml.dll";
public static class Constants
{
public const int NVML_DEVICE_INFOROM_VERSION_BUFFER_SIZE = 16;
public const int NVML_DEVICE_NAME_BUFFER_SIZE = 64;
public const int NVML_DEVICE_NAME_V2_BUFFER_SIZE = 96;
public const int NVML_DEVICE_PART_NUMBER_BUFFER_SIZE = 80;
public const int NVML_DEVICE_SERIAL_BUFFER_SIZE = 30;
public const int NVML_DEVICE_UUID_BUFFER_SIZE = 80;
public const int NVML_DEVICE_UUID_V2_BUFFER_SIZE = 96;
public const int NVML_DEVICE_VBIOS_VERSION_BUFFER_SIZE = 32;
public const int NVML_SYSTEM_DRIVER_VERSION_BUFFER_SIZE = 80;
public const int NVML_SYSTEM_NVML_VERSION_BUFFER_SIZE = 80;
public const int NVML_INIT_FLAG_NO_ATTACH = 2;
public const int NVML_INIT_FLAG_NO_GPUS = 1;
}
public enum nvmlReturn_t
{
NVML_SUCCESS = 0, // The operation was successful.
NVML_ERROR_UNINITIALIZED = 1, // NVML was not first initialized with nvmlInit().
NVML_ERROR_INVALID_ARGUMENT = 2, // A supplied argument is invalid.
NVML_ERROR_NOT_SUPPORTED = 3, // The requested operation is not available on target device.
NVML_ERROR_NO_PERMISSION = 4, // The current user does not have permission for operation.
NVML_ERROR_ALREADY_INITIALIZED = 5, // Deprecated: Multiple initializations are now allowed through ref counting.
NVML_ERROR_NOT_FOUND = 6, // A query to find an object was unsuccessful.
NVML_ERROR_INSUFFICIENT_SIZE = 7, // An input argument is not large enough.
NVML_ERROR_INSUFFICIENT_POWER = 8, // A device's external power cables are not properly attached.
NVML_ERROR_DRIVER_NOT_LOADED = 9, // NVIDIA driver is not loaded.
NVML_ERROR_TIMEOUT = 10, // User provided timeout passed.
NVML_ERROR_IRQ_ISSUE = 11, // NVIDIA Kernel detected an interrupt issue with a GPU.
NVML_ERROR_LIBRARY_NOT_FOUND = 12, // NVML Shared Library couldn't be found or loaded.
NVML_ERROR_FUNCTION_NOT_FOUND = 13, // Local version of NVML doesn't implement this function.
NVML_ERROR_CORRUPTED_INFOROM = 14, // infoROM is corrupted
NVML_ERROR_GPU_IS_LOST = 15, // The GPU has fallen off the bus or has otherwise become inaccessible.
NVML_ERROR_RESET_REQUIRED = 16, // The GPU requires a reset before it can be used again.
NVML_ERROR_OPERATING_SYSTEM = 17, // The GPU control device has been blocked by the operating system/cgroups.
NVML_ERROR_LIB_RM_VERSION_MISMATCH = 18, // RM detects a driver/library version mismatch.
NVML_ERROR_IN_USE = 19, // An operation cannot be performed because the GPU is currently in use.
NVML_ERROR_MEMORY = 20, // Insufficient memory.
NVML_ERROR_NO_DATA = 21, // No data.
NVML_ERROR_VGPU_ECC_NOT_SUPPORTED = 22, // The requested vgpu operation is not available on target device, becasue ECC is enabled.
NVML_ERROR_INSUFFICIENT_RESOURCES = 23, // Ran out of critical resources, other than memory.
NVML_ERROR_FREQ_NOT_SUPPORTED = 24, // Ran out of critical resources, other than memory.
NVML_ERROR_UNKNOWN = 999 // An internal driver error occurred.
}
[DllImport(NVMLDLL)]
private static extern nvmlReturn_t nvmlInit_v2();
[DllImport(NVMLDLL)]
private static extern nvmlReturn_t nvmlShutdown();
[DllImport(NVMLDLL)]
private static extern nvmlReturn_t nvmlDeviceGetCount_v2(out uint deviceCount);
[DllImport(NVMLDLL)]
private static extern nvmlReturn_t nvmlDeviceGetHandleByIndex_v2(int index, out IntPtr handle);
[DllImport(NVMLDLL)]
private static extern nvmlReturn_t nvmlDeviceGetName(IntPtr device, [MarshalAs(UnmanagedType.LPStr)] StringBuilder deviceName, uint length);
[DllImport(NVMLDLL)]
private static extern nvmlReturn_t nvmlDeviceGetAccountingPids(IntPtr device, ref uint count, [In, Out] uint[] pids);
static void Main(string[] args)
{
if (nvmlInit_v2() == nvmlReturn_t.NVML_SUCCESS)
{
nvmlDeviceGetCount_v2(out uint deviceCount);
for (int i = 0; i < deviceCount; i++)
{
StringBuilder name = new();
nvmlDeviceGetHandleByIndex_v2(i, out IntPtr _device);
nvmlDeviceGetName(_device, name, Constants.NVML_DEVICE_NAME_V2_BUFFER_SIZE);
// arbitrary number for now
uint count = 5;
uint[] pids = new uint[count];
nvmlDeviceGetAccountingPids(_device, ref count, pids);
foreach(uint ui in pids) Console.WriteLine(ui);
}
nvmlShutdown();
}
}
}
and so far it's returning the correct # of processes that are utilizing the gpu, but the PID array keeps returning all 0's. I'm not particularly experienced with C# so if someone could show me the proper syntax for this(or lemme know if I have to resort to IntPtr's), the original function has this signature:
nvmlReturn_t nvmlDeviceGetAccountingPids ( nvmlDevice_t device, unsigned int* count, unsigned int* pids )
Parameters
device
The identifier of the target device
count
Reference in which to provide the pids array size, and to return the number of elements ready to be queried
pids
Reference in which to return list of process ids
If anyone knows that magic combo I'd sure appreciate it, thank you for your time =)
Sometimes I think I only type things to work them out ^_^
static void Main(string[] args)
{
if (nvmlInit_v2() == nvmlReturn_t.NVML_SUCCESS)
{
nvmlDeviceGetCount_v2(out uint deviceCount);
for (int i = 0; i < deviceCount; i++)
{
StringBuilder name = new();
nvmlDeviceGetHandleByIndex_v2(i, out IntPtr _device);
nvmlDeviceGetName(_device, name, Constants.NVML_DEVICE_NAME_V2_BUFFER_SIZE);
// arbitrary number for now
uint count = 0;
nvmlDeviceGetAccountingPids(_device, ref count, null);
uint[] pids = new uint[count];
if (nvmlDeviceGetAccountingPids(_device, ref count, pids) == nvmlReturn_t.NVML_SUCCESS)
{
foreach (uint ui in pids) Console.WriteLine(ui);
}
}
nvmlShutdown();
}
so it turns out that when passing the count to the function it wants the same number as the size of the array in order to populate the pids list(which makes sense I suppose). This is retrieved by just setting count to "0" and passing a null array to the function and it will set count to the size of the array. Create a new uint array with that size, pass the array/count and BAM, it returns the pids as desired.
Thanks for reading SO!
If anyone has some constructive criticism in terms of syntax/practices please do comment so I can improve this code as I go. Have a wonderful day 👍

[GnuTLS Library in a C# project]

I am trying to import the GnuTLS library to my C# project and use its APIs. Unfortunately, I cannot find any way on how to do this with the C-based GnuTLS library.
Does anyone know a way on how to use the GnuTLS library in a C# project or even on how to use the Windows build of the GnuTLS library available on their website https://www.gnutls.org/download.html so that I can run it using a C compiler and use the P/Invoke in C# to access the necessary APIs.
(In C#, I tried to import the libraries as reference using MSVS2010 but it says that it is not a valid .NET assembly nor a COM component)
(Also tried the Windows build of this library using a simple C code that calls a function but fails on compilation due to an error "... undefined reference to ...". I put the header files in MinGW directory as well as the DLL and EXE files).
You can use gnutls via P\Invoke. So it's worked on unix platforms.
Example on linux:
namespace GnuTlsExample
{
internal static class NativeMethodsLinux {
internal enum GNUTLS_X509_FMT
{
GNUTLS_X509_FMT_DER = 0,
GNUTLS_X509_FMT_PEM = 1
}
[DllImport("libgnutls.so.30")]
internal static extern int gnutls_x509_crt_list_import(IntPtr certs, ref int cert_max, IntPtr data, GNUTLS_X509_FMT format, uint flags);
[DllImport("libgnutls.so.30")]
internal static extern int gnutls_x509_privkey_init(ref IntPtr key);
[DllImport("libgnutls.so.30")]
internal static extern int gnutls_x509_privkey_import(IntPtr key, IntPtr data, GNUTLS_X509_FMT format);
[DllImport("libgnutls.so.30")]
internal static extern int gnutls_certificate_set_x509_key(IntPtr cred, IntPtr certs, int max, IntPtr key);
[StructLayout(LayoutKind.Sequential)]
internal class gnutls_datum_t
{
public IntPtr data = IntPtr.Zero;
public int size = 0;
}
}
class Program
{
static void Main(string[] args)
{
var buf = ByteArrayToGnuTlsDatum(File.ReadAllBytes(certificateFilePath));
var certs = Marshal.AllocHGlobal(IntPtr.Size);
var max = 6;
var tlsCtx = IntPtr.Zero;
var isServer = 0;
var key = IntPtr.Zero;
var bufKey = MarshalUtils.ByteArrayToGnuTlsDatum(File.ReadAllBytes(keyFilePath));
var res = NativeMethodsLinux.gnutls_x509_privkey_init(ref key);
res = NativeMethodsLinux.gnutls_x509_privkey_import(key, bufKey,
NativeMethodsLinux.GNUTLS_X509_FMT.GNUTLS_X509_FMT_PEM);
res = NativeMethodsLinux.gnutls_x509_crt_list_import(certs, ref max, buf,
NativeMethodsLinux.GNUTLS_X509_FMT.GNUTLS_X509_FMT_PEM, 0);
var cred = Marshal.AllocHGlobal(IntPtr.Size);
res = NativeMethodsLinux.gnutls_certificate_set_x509_key(cred, certs, max, key);
}
internal static IntPtr ByteArrayToGnuTlsDatum(byte[] bytes)
{
var berPtr = Marshal.AllocHGlobal(Marshal.SizeOf<NativeMethodsLinux.gnutls_datum_t>());
var valPtr = Marshal.AllocHGlobal(bytes.Length);
Marshal.Copy(bytes,0,valPtr,bytes.Length);
Marshal.StructureToPtr(new NativeMethodsLinux.gnutls_datum_t
{
data = valPtr,
size = bytes.Length
}, berPtr, true);
return berPtr;
}
}
}

Issues gathering local network information in C# for Windows CE 6.0

I'm doing some cross platform development and am having issues trying to gather local network information using C# on Windows CE 6.0. I'm gathering information such as local IP address and gateway IP address. My method to get the local IP address works fine on all platforms but the method to get the gateway IP address doesn't work on CE 6.0, below is what I have
private IPAddress GetGatewayInfo()
{
//Console.WriteLine("Gateways");
NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces();
foreach (NetworkInterface adapter in adapters)
{
IPInterfaceProperties adapterProperties = adapter.GetIPProperties();
GatewayIPAddressInformationCollection addresses = adapterProperties.GatewayAddresses;
if (addresses.Count > 0)
{
foreach (GatewayIPAddressInformation address in addresses)
{
Console.WriteLine("Gateway IP is : {0}", address.Address);
return address.Address;
}
}
}
return null;
}
So after some research I found methods like GetAllNetworkInterfaces() aren't supported on CE and I found another way to get this information which is listed below
class libGetAdaptersInfo
{
[DllImport("iphlpapi.dll")]
private static extern int GetAdaptersInfo(IntPtr pAdapterInfo, ref Int64 pBufOutLen);
private const int MAX_ADAPTER_DESCRIPTION_LENGTH = 128;
private const int ERROR_BUFFER_OVERFLOW = 111;
private const int MAX_ADAPTER_NAME_LENGTH = 256;
private const int MAX_ADAPTER_ADDRESS_LENGTH = 8;
private const int MIB_IF_TYPE_OTHER = 1;
private const int MIB_IF_TYPE_ETHERNET = 6;
private const int MIB_IF_TYPE_TOKENRING = 9;
private const int MIB_IF_TYPE_FDDI = 15;
private const int MIB_IF_TYPE_PPP = 23;
private const int MIB_IF_TYPE_LOOPBACK = 24;
private const int MIB_IF_TYPE_SLIP = 28;
[StructLayout(LayoutKind.Sequential)]
private struct IP_ADDRESS_STRING
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string Address;
}
[StructLayout(LayoutKind.Sequential)]
private struct IP_ADDR_STRING
{
public IntPtr Next;
public IP_ADDRESS_STRING IpAddress;
public IP_ADDRESS_STRING IpMask;
public Int32 Context;
}
[StructLayout(LayoutKind.Sequential)]
private struct IP_ADAPTER_INFO
{
public IntPtr Next;
public Int32 ComboIndex;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_ADAPTER_NAME_LENGTH + 4)]
public string AdapterName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_ADAPTER_DESCRIPTION_LENGTH + 4)]
public string AdapterDescription;
public UInt32 AddressLength;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_ADAPTER_ADDRESS_LENGTH)]
public byte[] Address;
public Int32 Index;
public UInt32 Type;
public UInt32 DhcpEnabled;
public IntPtr CurrentIpAddress;
public IP_ADDR_STRING IpAddressList;
public IP_ADDR_STRING GatewayList;
public IP_ADDR_STRING DhcpServer;
public bool HaveWins;
public IP_ADDR_STRING PrimaryWinsServer;
public IP_ADDR_STRING SecondaryWinsServer;
public Int32 LeaseObtained;
public Int32 LeaseExpires;
}
public static void GetAdapters()
{
long structSize = Marshal.SizeOf(typeof(IP_ADAPTER_INFO));
IntPtr pArray = Marshal.AllocHGlobal((int)new IntPtr(structSize));
int ret = GetAdaptersInfo(pArray, ref structSize);
if (ret == ERROR_BUFFER_OVERFLOW) // ERROR_BUFFER_OVERFLOW == 111
{
// Buffer was too small, reallocate the correct size for the buffer.
pArray = Marshal.ReAllocHGlobal(pArray, new IntPtr(structSize));
ret = GetAdaptersInfo(pArray, ref structSize);
} // if
if (ret == 0)
{
// Call Succeeded
IntPtr pEntry = pArray;
do
{
// Retrieve the adapter info from the memory address
IP_ADAPTER_INFO entry = (IP_ADAPTER_INFO)Marshal.PtrToStructure(pEntry, typeof(IP_ADAPTER_INFO));
Console.WriteLine("\n");
Console.WriteLine("Index: {0}", entry.Index.ToString());
// Adapter Type
string tmpString = string.Empty;
switch (entry.Type)
{
case MIB_IF_TYPE_ETHERNET: tmpString = "Ethernet"; break;
case MIB_IF_TYPE_TOKENRING: tmpString = "Token Ring"; break;
case MIB_IF_TYPE_FDDI: tmpString = "FDDI"; break;
case MIB_IF_TYPE_PPP: tmpString = "PPP"; break;
case MIB_IF_TYPE_LOOPBACK: tmpString = "Loopback"; break;
case MIB_IF_TYPE_SLIP: tmpString = "Slip"; break;
default: tmpString = "Other/Unknown"; break;
} // switch
Console.WriteLine("Adapter Type: {0}", tmpString);
Console.WriteLine("Name: {0}", entry.AdapterName);
Console.WriteLine("Desc: {0}\n", entry.AdapterDescription);
Console.WriteLine("DHCP Enabled: {0}", (entry.DhcpEnabled == 1) ? "Yes" : "No");
if (entry.DhcpEnabled == 1)
{
Console.WriteLine("DHCP Server : {0}", entry.DhcpServer.IpAddress.Address);
// Lease Obtained (convert from "time_t" to C# DateTime)
DateTime pdatDate = new DateTime(1970, 1, 1).AddSeconds(entry.LeaseObtained).ToLocalTime();
Console.WriteLine("Lease Obtained: {0}", pdatDate.ToString());
// Lease Expires (convert from "time_t" to C# DateTime)
pdatDate = new DateTime(1970, 1, 1).AddSeconds(entry.LeaseExpires).ToLocalTime();
Console.WriteLine("Lease Expires : {0}\n", pdatDate.ToString());
} // if DhcpEnabled
Console.WriteLine("IP Address : {0}", entry.IpAddressList.IpAddress.Address);
Console.WriteLine("Subnet Mask : {0}", entry.IpAddressList.IpMask.Address);
Console.WriteLine("Default Gateway: {0}", entry.GatewayList.IpAddress.Address);
// MAC Address (data is in a byte[])
tmpString = string.Empty;
for (int i = 0; i < entry.AddressLength - 1; i++)
{
tmpString += string.Format("{0:X2}-", entry.Address[i]);
}
Console.WriteLine("MAC Address : {0}{1:X2}\n", tmpString, entry.Address[entry.AddressLength - 1]);
Console.WriteLine("Has WINS: {0}", entry.HaveWins ? "Yes" : "No");
if (entry.HaveWins)
{
Console.WriteLine("Primary WINS Server : {0}", entry.PrimaryWinsServer.IpAddress.Address);
Console.WriteLine("Secondary WINS Server: {0}", entry.SecondaryWinsServer.IpAddress.Address);
} // HaveWins
// Get next adapter (if any)
pEntry = entry.Next;
}
while (pEntry != IntPtr.Zero);
Marshal.FreeHGlobal(pArray);
} // if
else
{
Marshal.FreeHGlobal(pArray);
throw new InvalidOperationException("GetAdaptersInfo failed: " + ret);
}
} // GetAdapters
The above method worked fine on Windows 7 and printed all correct values but when I tested it on CE I still had issues, such as all values saying they are unknown/empty, an index out of range exception when trying to get the MAC address information, and crashing at the end of the program with an "Not supported exception". I'm pretty stumped now as it works perfectly fine on win 7 so I'm not sure what to try next as this was the only method I could find that was supposed to work on CE, does anyone know how I could fix these issues or know of another method to get the gateway IP address? thanks
GetAdaptersInfo should work, but I see a few issues with the P/Invoke definitions:
On Windows CE, the second parameter to GetAdaptersInfo is a pointer to a 32-bit integer, not 64-bit
Strings in iphlpapi context are C-style char arrays, so the CE default of 2-byte Unicode selected with UnmanagedType.ByValTStr won't work. Specify CharSet = CharSet.Ansi in the StructLayout attribute on all structs that contain strings
HaveWins is specified as a .NET bool, but if I remember correctly this is marshalled as a single byte. Stick a [MarshalAs(UnmanagedType.Bool)] in front, or change to int to map correctly to the underlying type.
I may have missed something, so do check your code thoroughly against the CE definitions. A good place to start might be https://msdn.microsoft.com/en-us/library/ms891170.aspx (CE 5.0 documentation, but same as 6.0).

In C# GetEnvironmentVariable("NUMBER_OF_PROCESSORS") returns the wrong number [duplicate]

Is there a way via .NET/C# to find out the number of CPU cores?
PS This is a straight code question, not a "Should I use multi-threading?" question! :-)
There are several different pieces of information relating to processors that you could get:
Number of physical processors
Number of cores
Number of logical processors.
These can all be different; in the case of a machine with 2 dual-core hyper-threading-enabled processors, there are 2 physical processors, 4 cores, and 8 logical processors.
The number of logical processors is available through the Environment class, but the other information is only available through WMI (and you may have to install some hotfixes or service packs to get it on some systems):
Make sure to add a reference in your project to System.Management.dll
In .NET Core, this is available (for Windows only) as a NuGet package.
Physical Processors:
foreach (var item in new System.Management.ManagementObjectSearcher("Select * from Win32_ComputerSystem").Get())
{
Console.WriteLine("Number Of Physical Processors: {0} ", item["NumberOfProcessors"]);
}
Cores:
int coreCount = 0;
foreach (var item in new System.Management.ManagementObjectSearcher("Select * from Win32_Processor").Get())
{
coreCount += int.Parse(item["NumberOfCores"].ToString());
}
Console.WriteLine("Number Of Cores: {0}", coreCount);
Logical Processors:
Console.WriteLine("Number Of Logical Processors: {0}", Environment.ProcessorCount);
OR
foreach (var item in new System.Management.ManagementObjectSearcher("Select * from Win32_ComputerSystem").Get())
{
Console.WriteLine("Number Of Logical Processors: {0}", item["NumberOfLogicalProcessors"]);
}
Processors excluded from Windows:
You can also use Windows API calls in setupapi.dll to discover processors that have been excluded from Windows (e.g. through boot settings) and aren't detectable using the above means. The code below gives the total number of logical processors (I haven't been able to figure out how to differentiate physical from logical processors) that exist, including those that have been excluded from Windows:
static void Main(string[] args)
{
int deviceCount = 0;
IntPtr deviceList = IntPtr.Zero;
// GUID for processor classid
Guid processorGuid = new Guid("{50127dc3-0f36-415e-a6cc-4cb3be910b65}");
try
{
// get a list of all processor devices
deviceList = SetupDiGetClassDevs(ref processorGuid, "ACPI", IntPtr.Zero, (int)DIGCF.PRESENT);
// attempt to process each item in the list
for (int deviceNumber = 0; ; deviceNumber++)
{
SP_DEVINFO_DATA deviceInfo = new SP_DEVINFO_DATA();
deviceInfo.cbSize = Marshal.SizeOf(deviceInfo);
// attempt to read the device info from the list, if this fails, we're at the end of the list
if (!SetupDiEnumDeviceInfo(deviceList, deviceNumber, ref deviceInfo))
{
deviceCount = deviceNumber;
break;
}
}
}
finally
{
if (deviceList != IntPtr.Zero) { SetupDiDestroyDeviceInfoList(deviceList); }
}
Console.WriteLine("Number of cores: {0}", deviceCount);
}
[DllImport("setupapi.dll", SetLastError = true)]
private static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid,
[MarshalAs(UnmanagedType.LPStr)]String enumerator,
IntPtr hwndParent,
Int32 Flags);
[DllImport("setupapi.dll", SetLastError = true)]
private static extern Int32 SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet);
[DllImport("setupapi.dll", SetLastError = true)]
private static extern bool SetupDiEnumDeviceInfo(IntPtr DeviceInfoSet,
Int32 MemberIndex,
ref SP_DEVINFO_DATA DeviceInterfaceData);
[StructLayout(LayoutKind.Sequential)]
private struct SP_DEVINFO_DATA
{
public int cbSize;
public Guid ClassGuid;
public uint DevInst;
public IntPtr Reserved;
}
private enum DIGCF
{
DEFAULT = 0x1,
PRESENT = 0x2,
ALLCLASSES = 0x4,
PROFILE = 0x8,
DEVICEINTERFACE = 0x10,
}
Environment.ProcessorCount
[Documentation]
WMI queries are slow, so try to Select only the desired members instead of using Select *.
The following query takes 3.4s:
foreach (var item in new System.Management.ManagementObjectSearcher("Select * from Win32_Processor").Get())
While this one takes 0.122s:
foreach (var item in new System.Management.ManagementObjectSearcher("Select NumberOfCores from Win32_Processor").Get())
Environment.ProcessorCount should give you the number of cores on the local machine.
The the easyest way = Environment.ProcessorCount
Exemple from Environment.ProcessorCount Property
using System;
class Sample
{
public static void Main()
{
Console.WriteLine("The number of processors " +
"on this computer is {0}.",
Environment.ProcessorCount);
}
}
It's rather interesting to see how .NET get this internally to say the least... It's as "simple" as below:
namespace System.Threading
{
using System;
using System.Runtime.CompilerServices;
internal static class PlatformHelper
{
private const int PROCESSOR_COUNT_REFRESH_INTERVAL_MS = 0x7530;
private static volatile int s_lastProcessorCountRefreshTicks;
private static volatile int s_processorCount;
internal static bool IsSingleProcessor
{
get
{
return (ProcessorCount == 1);
}
}
internal static int ProcessorCount
{
get
{
int tickCount = Environment.TickCount;
int num2 = s_processorCount;
if ((num2 == 0) || ((tickCount - s_lastProcessorCountRefreshTicks) >= 0x7530))
{
s_processorCount = num2 = Environment.ProcessorCount;
s_lastProcessorCountRefreshTicks = tickCount;
}
return num2;
}
}
}
}
From .NET Framework source
You can also get it with PInvoke on Kernel32.dll
The following code is coming more or less from SystemInfo.cs from System.Web source located here:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct SYSTEM_INFO
{
public ushort wProcessorArchitecture;
public ushort wReserved;
public uint dwPageSize;
public IntPtr lpMinimumApplicationAddress;
public IntPtr lpMaximumApplicationAddress;
public IntPtr dwActiveProcessorMask;
public uint dwNumberOfProcessors;
public uint dwProcessorType;
public uint dwAllocationGranularity;
public ushort wProcessorLevel;
public ushort wProcessorRevision;
}
internal static class SystemInfo
{
static int _trueNumberOfProcessors;
internal static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
internal static extern void GetSystemInfo(out SYSTEM_INFO si);
[DllImport("kernel32.dll")]
internal static extern int GetProcessAffinityMask(IntPtr handle, out IntPtr processAffinityMask, out IntPtr systemAffinityMask);
internal static int GetNumProcessCPUs()
{
if (SystemInfo._trueNumberOfProcessors == 0)
{
SYSTEM_INFO si;
GetSystemInfo(out si);
if ((int) si.dwNumberOfProcessors == 1)
{
SystemInfo._trueNumberOfProcessors = 1;
}
else
{
IntPtr processAffinityMask;
IntPtr systemAffinityMask;
if (GetProcessAffinityMask(INVALID_HANDLE_VALUE, out processAffinityMask, out systemAffinityMask) == 0)
{
SystemInfo._trueNumberOfProcessors = 1;
}
else
{
int num1 = 0;
if (IntPtr.Size == 4)
{
uint num2 = (uint) (int) processAffinityMask;
while ((int) num2 != 0)
{
if (((int) num2 & 1) == 1)
++num1;
num2 >>= 1;
}
}
else
{
ulong num2 = (ulong) (long) processAffinityMask;
while ((long) num2 != 0L)
{
if (((long) num2 & 1L) == 1L)
++num1;
num2 >>= 1;
}
}
SystemInfo._trueNumberOfProcessors = num1;
}
}
}
return SystemInfo._trueNumberOfProcessors;
}
}
There are many answers here already, but some have heavy upvotes and are incorrect.
The .NET Environment.ProcessorCount WILL return incorrect values and can fail critically if your system WMI is configured incorrectly.
If you want a RELIABLE way to count the cores, the only way is Win32 API.
Here is a C++ snippet:
#include <Windows.h>
#include <vector>
int num_physical_cores()
{
static int num_cores = []
{
DWORD bytes = 0;
GetLogicalProcessorInformation(nullptr, &bytes);
std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> coreInfo(bytes / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION));
GetLogicalProcessorInformation(coreInfo.data(), &bytes);
int cores = 0;
for (auto& info : coreInfo)
{
if (info.Relationship == RelationProcessorCore)
++cores;
}
return cores > 0 ? cores : 1;
}();
return num_cores;
}
And since this is a .NET C# Question, here's the ported version:
[StructLayout(LayoutKind.Sequential)]
struct CACHE_DESCRIPTOR
{
public byte Level;
public byte Associativity;
public ushort LineSize;
public uint Size;
public uint Type;
}
[StructLayout(LayoutKind.Explicit)]
struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION_UNION
{
[FieldOffset(0)] public byte ProcessorCore;
[FieldOffset(0)] public uint NumaNode;
[FieldOffset(0)] public CACHE_DESCRIPTOR Cache;
[FieldOffset(0)] private UInt64 Reserved1;
[FieldOffset(8)] private UInt64 Reserved2;
}
public enum LOGICAL_PROCESSOR_RELATIONSHIP
{
RelationProcessorCore,
RelationNumaNode,
RelationCache,
RelationProcessorPackage,
RelationGroup,
RelationAll = 0xffff
}
struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION
{
public UIntPtr ProcessorMask;
public LOGICAL_PROCESSOR_RELATIONSHIP Relationship;
public SYSTEM_LOGICAL_PROCESSOR_INFORMATION_UNION ProcessorInformation;
}
[DllImport("kernel32.dll")]
static extern unsafe bool GetLogicalProcessorInformation(SYSTEM_LOGICAL_PROCESSOR_INFORMATION* buffer, out int bufferSize);
static unsafe int GetProcessorCoreCount()
{
GetLogicalProcessorInformation(null, out int bufferSize);
int numEntries = bufferSize / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
var coreInfo = new SYSTEM_LOGICAL_PROCESSOR_INFORMATION[numEntries];
fixed (SYSTEM_LOGICAL_PROCESSOR_INFORMATION* pCoreInfo = coreInfo)
{
GetLogicalProcessorInformation(pCoreInfo, out bufferSize);
int cores = 0;
for (int i = 0; i < numEntries; ++i)
{
ref SYSTEM_LOGICAL_PROCESSOR_INFORMATION info = ref pCoreInfo[i];
if (info.Relationship == LOGICAL_PROCESSOR_RELATIONSHIP.RelationProcessorCore)
++cores;
}
return cores > 0 ? cores : 1;
}
}
public static readonly int NumPhysicalCores = GetProcessorCoreCount();
One option would be to read the data from the registry.
MSDN Article On The Topic: http://msdn.microsoft.com/en-us/library/microsoft.win32.registry.localmachine(v=vs.71).aspx)
The processors, I believe can be located here, HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor
private void determineNumberOfProcessCores()
{
RegistryKey rk = Registry.LocalMachine;
String[] subKeys = rk.OpenSubKey("HARDWARE").OpenSubKey("DESCRIPTION").OpenSubKey("System").OpenSubKey("CentralProcessor").GetSubKeyNames();
textBox1.Text = "Total number of cores:" + subKeys.Length.ToString();
}
I am reasonably sure the registry entry will be there on most systems.
Thought I would throw my $0.02 in.
You can use this class:
public static class CpuCores
{
private static int cores = 0;
public static int Number
{
get
{
if (cores > 0) return cores;
RegistryKey key = Registry.LocalMachine.OpenSubKey(#"SYSTEM\CurrentControlSet\Control\Class\" +
"{50127dc3-0f36-415e-a6cc-4cb3be910b65}");
if (key == null)
{
cores = Environment.ProcessorCount;
return cores;
}
string[] subkeys = key.GetSubKeyNames();
key.Close();
cores = 0;
if (subkeys != null && subkeys.Length > 0) foreach (string s in subkeys)
{
if (s.Length != 4) continue;
int n;
if (int.TryParse(s, out n) && ++n > cores) cores = n;
}
if (cores <= 0) cores = Environment.ProcessorCount;
return cores;
}
}
}
I was looking for the same thing but I don't want to install any nuget or servicepack, so I found this solution, it is pretty simple and straight forward,
using this discussion, I thought it would be so easy to run that WMIC command and get that value, here is the C# code. You only need to use System.Management namespace (and couple more standard namespaces for process and so on).
string fileName = Path.Combine(Environment.SystemDirectory, "wbem", "wmic.exe");
string arguments = #"cpu get NumberOfCores";
Process process = new Process
{
StartInfo =
{
FileName = fileName,
Arguments = arguments,
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardOutput = true,
RedirectStandardError = true
}
};
process.Start();
StreamReader output = process.StandardOutput;
Console.WriteLine(output.ReadToEnd());
process.WaitForExit();
int exitCode = process.ExitCode;
process.Close();

Which PID listens on a given port in c#

What is the easiest way to get a PID that listens on a given port in C#?
Basically, I want to make sure that my service is running and listens on a port I have provided it.
If there is an easier way than parsing netstat output it will be great.
from win XP SP2 onwards you can P/Invoke to GetExtendedTcpTable
Using This person's kind work to flesh out the signature (the PInvoke.net spec is incomplete) here is a (rough and poor at error checking) example
using System;
using System.Runtime.InteropServices;
public enum TCP_TABLE_CLASS : int
{
TCP_TABLE_BASIC_LISTENER,
TCP_TABLE_BASIC_CONNECTIONS,
TCP_TABLE_BASIC_ALL,
TCP_TABLE_OWNER_PID_LISTENER,
TCP_TABLE_OWNER_PID_CONNECTIONS,
TCP_TABLE_OWNER_PID_ALL,
TCP_TABLE_OWNER_MODULE_LISTENER,
TCP_TABLE_OWNER_MODULE_CONNECTIONS,
TCP_TABLE_OWNER_MODULE_ALL
}
[StructLayout(LayoutKind.Sequential)]
public struct MIB_TCPROW_OWNER_PID
{
public uint state;
public uint localAddr;
public byte localPort1;
public byte localPort2;
public byte localPort3;
public byte localPort4;
public uint remoteAddr;
public byte remotePort1;
public byte remotePort2;
public byte remotePort3;
public byte remotePort4;
public int owningPid;
public ushort LocalPort
{
get
{
return BitConverter.ToUInt16(
new byte[2] { localPort2, localPort1}, 0);
}
}
public ushort RemotePort
{
get
{
return BitConverter.ToUInt16(
new byte[2] { remotePort2, remotePort1}, 0);
}
}
}
[StructLayout(LayoutKind.Sequential)]
public struct MIB_TCPTABLE_OWNER_PID
{
public uint dwNumEntries;
MIB_TCPROW_OWNER_PID table;
}
[DllImport("iphlpapi.dll", SetLastError=true)]
static extern uint GetExtendedTcpTable(IntPtr pTcpTable,
ref int dwOutBufLen,
bool sort,
int ipVersion,
TCP_TABLE_CLASS tblClass,
int reserved);
public static MIB_TCPROW_OWNER_PID[] GetAllTcpConnections()
{
MIB_TCPROW_OWNER_PID[] tTable;
int AF_INET = 2; // IP_v4
int buffSize = 0;
// how much memory do we need?
uint ret = GetExtendedTcpTable(IntPtr.Zero,
ref buffSize,
true,
AF_INET,
TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_ALL,
0);
if (ret != 0 && ret != 122) // 122 insufficient buffer size
throw new Exception("bad ret on check " + ret);
IntPtr buffTable = Marshal.AllocHGlobal(buffSize);
try
{
ret = GetExtendedTcpTable(buffTable,
ref buffSize,
true,
AF_INET,
TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_ALL,
0);
if (ret != 0)
throw new Exception("bad ret "+ ret);
// get the number of entries in the table
MIB_TCPTABLE_OWNER_PID tab =
(MIB_TCPTABLE_OWNER_PID)Marshal.PtrToStructure(
buffTable,
typeof(MIB_TCPTABLE_OWNER_PID));
IntPtr rowPtr = (IntPtr)((long)buffTable +
Marshal.SizeOf(tab.dwNumEntries));
tTable = new MIB_TCPROW_OWNER_PID[tab.dwNumEntries];
for (int i = 0; i < tab.dwNumEntries; i++)
{
MIB_TCPROW_OWNER_PID tcpRow = (MIB_TCPROW_OWNER_PID)Marshal
.PtrToStructure(rowPtr, typeof(MIB_TCPROW_OWNER_PID));
tTable[i] = tcpRow;
// next entry
rowPtr = (IntPtr)((long)rowPtr + Marshal.SizeOf(tcpRow));
}
}
finally
{
// Free the Memory
Marshal.FreeHGlobal(buffTable);
}
return tTable;
}
check out this project:
http://www.codeproject.com/KB/IP/iphlpapi.aspx
It uses Interop in C# to get to the underlying GetTcpTable Win API function. And therefore can give you the process id you are looking for.
hope that helps,
Alex

Categories