I use .NET 6 to get os version.
I want to get os version like "Windows 2019 Enterprise LTSC" or "Windows 10 Professional".
I use System.Management:
string? info = null;
using (ManagementObjectSearcher searcher = new("SELECT * FROM Win32_OperatingSystem"))
{
ManagementObjectCollection information = searcher.Get();
if (information != null)
{
foreach (ManagementObject obj in information.Cast<ManagementObject>())
{
info = obj["Caption"].ToString() + " - " + obj["OSArchitecture"].ToString();
}
}
info = info.Replace("NT 5.1.2600", "XP");
info = info.Replace("NT 5.2.3790", "Server 2003");
}
return info;
I get os version wonderful,but PublishTrimmed was not allowed:
<PublishTrimmed>true</PublishTrimmed>
System.Management was conflicted with PublishTrimmed.
I tried to use Microsoft.VisualBasic.Device.ComputerInfo,but I need to change .net6.0 to .net6.0-windows and add <UseWindowsForms>true<UseWindowsForms>.When I use this,I can not use <PublishTrimmed>true</PublishTrimmed>.
For some reason,I need reduce my program size less than 20M.
I tried to use registry to get os version:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
But in Windows 11 21H2,the key ProductName of the the value is Windows 10 Pro.It is not correct.
Does anyone have another solution?
This is how I get the total and used RAM:
PerformanceCounter ramAvailableCounter = new PerformanceCounter("Memory", "Available MBytes");
var ramUsedMB = ramAvailableCounter.NextValue();
var ramTotalMB = new Microsoft.VisualBasic.Devices.ComputerInfo().TotalPhysicalMemory / 1024 / 1024;
var ramPercentageLeft = (ramUsedMB * 100) / ramTotalMB;
But how can I get the "Committed" memory shown below?
Unfortunately the application we use throws an exception when there is only about 15GB free and I would like to send a notification when is close enough.
It can be done as following:
PerformanceCounter percCommittedBytesInUseCounter = new PerformanceCounter("Memory", "% Committed Bytes In Use");
I would like to measure how much of system's memory is available in my C# code. I believe it is done something like this:
PerformanceCounter ramCounter = new PerformanceCounter(
"Memory"
, "Available MBytes"
, true
);
float availbleRam = ramCounter.NextValue();
The thing is Mono has no "Memmory" category. I iterated over the list of categories like this:
PerformanceCounterCategory[] cats = PerformanceCounterCategory.GetCategories();
string res = "";
foreach (PerformanceCounterCategory c in cats)
{
res += c.CategoryName + Environment.NewLine;
}
return res;
And closest category I found is "Mono Memory" which has no "Available MBytes" and keeps returning 0 on NextValue calls. Here's the complete list of categories mono returns:
Processor
Process
Mono Memory
ASP.NET
.NET CLR JIT
.NET CLR Exceptions
.NET CLR Memory
.NET CLR Remoting
.NET CLR Loading
.NET CLR LocksAndThreads
.NET CLR Interop
.NET CLR Security
Mono Threadpool
Network Interface
So does anyone know a way to measure the available memory in C# + Mono + Ubuntu?
[UPDATE]
I managed to do this in Ubuntu like this (using the external program free):
long GetFreeMemorySize()
{
Regex ram_regex = new Regex(#"[^\s]+\s+\d+\s+(\d+)$");
ProcessStartInfo ram_psi = new ProcessStartInfo("free");
ram_psi.RedirectStandardOutput = true;
ram_psi.RedirectStandardError = true;
ram_psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
ram_psi.UseShellExecute = false;
System.Diagnostics.Process free = System.Diagnostics.Process.Start(ram_psi);
using (System.IO.StreamReader myOutput = free.StandardOutput)
{
string output = myOutput.ReadToEnd();
string[] lines = output.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
lines[2] = lines[2].Trim();
Match match = ram_regex.Match(lines[2]);
if (match.Success)
{
try
{
return Convert.ToInt64(match.Groups[1].Value);
}
catch (Exception)
{
return 0L;
}
}
else
{
return 0L;
}
}
}
But the problem with this solution is that it works with Mono only if it is run within a Linux system. I would like to know if anyone can come up with a solution for Mono + Windows?
I realize this is an old question, but my answer might help someone.
You need to find out what performance categories and counters are available on your system.
foreach (var cat in PerformanceCounterCategory.GetCategories())
{
Console.WriteLine(cat.CategoryName + ":");
foreach (var co in cat.GetCounters())
{
Console.WriteLine(co.CounterName);
}
}
Then you will need to use the corresponding values for measuring the performance.
For Windows, those should be:
var memory = new PerformanceCounter("Memory", "Available MBytes");
For Linux (tested on Yogurt 0.2.3):
var memory = new PerformanceCounter("Mono Memory", "Available Physical Memory");
The values might be different depending on the operating system, but you will find the correct values by iterating the categories and the counters for each category.
Thread.Sleep(1000);
Place that after your first "NextValue" call (you can toss the very first NextValue return value) and follow it with your line:
float availbleRam = ramCounter.NextValue();
Performance counters need time to measure before they can return results.
Confirmed this works in Windows with .net 4.5, unsure about Linux with Mono.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
C# - How do you get total amount of RAM the computer has?
The following would retrieve how much ram is available:
PerformanceCounter ramCounter;
ramCounter = new PerformanceCounter("Memory", "Available MBytes");
Console.WriteLine("Total RAM: " + ramCounter.NextValue().ToString() + " MB\n\n");
Of course we will have to use the System.Diagnostics; class.
Does performancecounter have any functionality for retrieving the amount of RAM of a particular machine? I'm not talking about the amount of ram used or unused. I'm talking about the amount of ram the machine has.
This information is already available directly in the .NET framework, you might as well use it. Project + Add Reference, select Microsoft.VisualBasic.
using System;
class Program {
static void Main(string[] args) {
Console.WriteLine("You have {0} bytes of RAM",
new Microsoft.VisualBasic.Devices.ComputerInfo().TotalPhysicalMemory);
Console.ReadLine();
}
}
And no, it doesn't turn your C# code into vb.net.
you can try like this
Add a Reference to System.Management.
private static void DisplayTotalRam()
{
string Query = "SELECT MaxCapacity FROM Win32_PhysicalMemoryArray";
ManagementObjectSearcher searcher = new ManagementObjectSearcher(Query);
foreach (ManagementObject WniPART in searcher.Get())
{
UInt32 SizeinKB = Convert.ToUInt32(WniPART.Properties["MaxCapacity"].Value);
UInt32 SizeinMB = SizeinKB / 1024;
UInt32 SizeinGB = SizeinMB / 1024;
Console.WriteLine("Size in KB: {0}, Size in MB: {1}, Size in GB: {2}", SizeinKB, SizeinMB, SizeinGB);
}
}
How can I programmatically tell in C# if an unmanaged DLL file is x86 or x64?
Refer to the specifications. Here's a basic implementation:
public static MachineType GetDllMachineType (string dllPath)
{
// See http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx
// Offset to PE header is always at 0x3C.
// The PE header starts with "PE\0\0" = 0x50 0x45 0x00 0x00,
// followed by a 2-byte machine type field (see the document above for the enum).
//
using (var fs = new FileStream (dllPath, FileMode.Open, FileAccess.Read))
using (var br = new BinaryReader (fs))
{
fs.Seek (0x3c, SeekOrigin.Begin);
Int32 peOffset = br.ReadInt32();
fs.Seek (peOffset, SeekOrigin.Begin);
UInt32 peHead = br.ReadUInt32();
if (peHead != 0x00004550) // "PE\0\0", little-endian
throw new Exception ("Can't find PE header");
return (MachineType)br.ReadUInt16();
}
}
The MachineType enum is defined as:
public enum MachineType : ushort
{
IMAGE_FILE_MACHINE_UNKNOWN = 0x0,
IMAGE_FILE_MACHINE_AM33 = 0x1d3,
IMAGE_FILE_MACHINE_AMD64 = 0x8664,
IMAGE_FILE_MACHINE_ARM = 0x1c0,
IMAGE_FILE_MACHINE_EBC = 0xebc,
IMAGE_FILE_MACHINE_I386 = 0x14c,
IMAGE_FILE_MACHINE_IA64 = 0x200,
IMAGE_FILE_MACHINE_M32R = 0x9041,
IMAGE_FILE_MACHINE_MIPS16 = 0x266,
IMAGE_FILE_MACHINE_MIPSFPU = 0x366,
IMAGE_FILE_MACHINE_MIPSFPU16 = 0x466,
IMAGE_FILE_MACHINE_POWERPC = 0x1f0,
IMAGE_FILE_MACHINE_POWERPCFP = 0x1f1,
IMAGE_FILE_MACHINE_R4000 = 0x166,
IMAGE_FILE_MACHINE_SH3 = 0x1a2,
IMAGE_FILE_MACHINE_SH3DSP = 0x1a3,
IMAGE_FILE_MACHINE_SH4 = 0x1a6,
IMAGE_FILE_MACHINE_SH5 = 0x1a8,
IMAGE_FILE_MACHINE_THUMB = 0x1c2,
IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x169,
IMAGE_FILE_MACHINE_ARM64 = 0xaa64
}
I only needed three of these, but I included them all for completeness. Final 64-bit check:
// Returns true if the dll is 64-bit, false if 32-bit, and null if unknown
public static bool? UnmanagedDllIs64Bit(string dllPath)
{
switch (GetDllMachineType(dllPath))
{
case MachineType.IMAGE_FILE_MACHINE_AMD64:
case MachineType.IMAGE_FILE_MACHINE_IA64:
return true;
case MachineType.IMAGE_FILE_MACHINE_I386:
return false;
default:
return null;
}
}
Using a Visual Studio command prompt, dumpbin /headers dllname.dll works too. On my machine the beginning of the output stated:
FILE HEADER VALUES
8664 machine (x64)
5 number of sections
47591774 time date stamp Fri Dec 07 03:50:44 2007
Even easier: check out the System.Reflection.Module class. It includes the GetPEKind method, which returns 2 enums that describe the type of code and the CPU target. No more hex!
(the rest of this very informative post was copied shamelessly from http://www.developersdex.com/vb/message.asp?p=2924&r=6413567)
Sample code:
Assembly assembly = Assembly.ReflectionOnlyLoadFrom(#"<assembly Path>");
PortableExecutableKinds kinds;
ImageFileMachine imgFileMachine;
assembly.ManifestModule.GetPEKind(out kinds, out imgFileMachine);
PortableExecutableKinds can be used to check what kind of the assembly. It
has 5 values:
ILOnly: The executable contains only Microsoft intermediate language
(MSIL), and is therefore neutral with respect to 32-bit or 64-bit
platforms.
NotAPortableExecutableImage: The file is not in portable executable (PE)
file format.
PE32Plus: The executable requires a 64-bit platform.
Required32Bit: The executable can be run on a 32-bit platform, or in the
32-bit Windows on Windows (WOW) environment on a 64-bit platform.
Unmanaged32Bit: The executable contains pure unmanaged code.
Following are the links:
Module.GetPEKind Method:
http://msdn.microsoft.com/en-us/library/system.reflection.module.getpekind.aspx
PortableExecutableKinds Enumeration:
http://msdn.microsoft.com/en-us/library/system.reflection.portableexecutablekinds(VS.80).aspx
ImageFileMachine Enumeration:
http://msdn.microsoft.com/en-us/library/system.reflection.imagefilemachine.aspx
Instead of Assembly.LoadFile, use Assembly.ReflectionOnlyLoadFrom. This will let you work around the "Bad Image Format" exceptions.
I know it has been a while since this was updated. I was able to get away with the "Bad Image Format" exceptions by loading the file into it's own AppDomain.
private static (string pkName, string imName) FindPEKind(string filename)
{
// some files, especially if loaded into memory
// can cause errors. Thus, load into their own appdomain
AppDomain tempDomain = AppDomain.CreateDomain(Guid.NewGuid().ToString());
PEWorkerClass remoteWorker =
(PEWorkerClass)tempDomain.CreateInstanceAndUnwrap(
typeof(PEWorkerClass).Assembly.FullName,
typeof(PEWorkerClass).FullName);
(string pkName, string imName) = remoteWorker.TryReflectionOnlyLoadFrom_GetManagedType(filename);
AppDomain.Unload(tempDomain);
return (pkName, imName);
}
At this point, I do the following:
public (string pkName, string imName) TryReflectionOnlyLoadFrom_GetManagedType(string fileName)
{
string pkName;
string imName;
try
{
Assembly assembly = Assembly.ReflectionOnlyLoadFrom(assemblyFile: fileName);
assembly.ManifestModule.GetPEKind(
peKind: out PortableExecutableKinds peKind,
machine: out ImageFileMachine imageFileMachine);
// Any CPU builds are reported as 32bit.
// 32bit builds will have more value for PortableExecutableKinds
if (peKind == PortableExecutableKinds.ILOnly && imageFileMachine == ImageFileMachine.I386)
{
pkName = "AnyCPU";
imName = "";
}
else
{
PortableExecutableKindsNames.TryGetValue(
key: peKind,
value: out pkName);
if (string.IsNullOrEmpty(value: pkName))
{
pkName = "*** ERROR ***";
}
ImageFileMachineNames.TryGetValue(
key: imageFileMachine,
value: out imName);
if (string.IsNullOrEmpty(value: pkName))
{
imName = "*** ERROR ***";
}
}
return (pkName, imName);
}
catch (Exception ex)
{
return (ExceptionHelper(ex), "");
}
}
Running this against my Widows\Assembly directory gives me zero errors with over 3600 files processed.
note: I use a dictionary to load the values being returned.
I hope it helps. YMMV