Я использую ManagementBaseObjects из пакета System.Management.
Если быть точным, я в основном получаю свои данные с помощью этого кода:
searcher = new ManagementObjectSearcher($"Select * From {area}");
ManagementObjectCollection results = searcher.Get();
Дело в следующем: объект/данные, которые мне возвращаются, имеют uint в качестве информации о размере оперативной памяти. Из-за этого он слишком мал, чтобы правильно предоставить мне информацию для любой V-RAM более 4 ГБ.
Теперь, судя по тому, что я смог определить, я могу использовать HKLMRegistry, чтобы немного помочь мне здесь.
До сих пор, когда «обычное» поле memorzSize было слишком маленьким, в объекте HKLM было поле qwMemorySize. ДО СИХ ПОР. (Я добавляю соответствующий код в самом конце)
Дело в том, что в БОЛЬШИНСТВЕ, но не ВСЕХ случаях, когда оперативная память не слишком велика/отсутствует поле qwMemory, другие поля HKLM, кроме PNP-ID, хранятся в формате base64.
Учитывая контекст, мои вопросы заключаются в следующем:
- Всегда ли так, что если VRAM превышает 4 ГБ, будет поле qwMemorySize?
- Когда такое поле НЕ отображается, всегда ли строки будут иметь формат Base64?
- Если нет, то какие еще крайние случаи существуют
- Как я могу упредить такие «различные случаи хранения данных» в Предполагается, что я не могу просто сохранить закодированную строку через API, но мне нужно, чтобы все было декодировано и доступно для чтения, когда я отправляю ее в API?
А теперь еще несколько примеров скриншотов.
Изображение первое — это вывод консоли, показывающий графический процессор, который превышает лимит и имеет поле qw, и графический процессор, который этого не делает. (По запросу я также предоставлю вывод консоли в виде текста. Текст будет под скриншотами и над кодом.)
На рисунках ниже показано, как это выглядит в HKLM, в том же порядке.

Если вы хотите увидеть, что находится в вашем собственном HKLM, просто откройте редактор реестра приложения и перейдите по пути Компьютер\HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}\0000
Если у вас несколько графических процессоров, вы можете просмотреть их, проверив \0001 или 0002 и т. д. и т. д. и т. д.
[
{
"WinInfo": {
"Name": "NVIDIA Quadro P620",
"AdapterRAM": 4293918720,
"AdapterDACType": "Integrated RAMDAC",
"VideoProcessor": "Quadro P620",
"DeviceId": "VideoController1",
"PNPDeviceID": "PCI\\VEN_10DE\u0026DEV_1CBD\u0026SUBSYS_8754103C\u0026REV_A1\\4\u002624674EF9\u00260\u00260008"
},
"HKLMInfo":{
"AdapterString": "Quadro P620",
"BiosString": "Version86.7.8e.0.3",
"ChipType": "Quadro P620",
"DacType": "Integrated RAMDAC",
"MemorySize": -1048576,
"QwMemorySize": 4294967296,
"MatchingDeviceId": "pci\\ven_10de\u0026dev_1cbd\u0026subsys_8754103c"
}
},
{
"WinInfo": {
"Name": "Intel(R) UHD Graphics 630",
"AdapterRAM": 1073741824,
"AdapterDACType": "Internal",
"VideoProcessor": "Intel(R) UHD Graphics Family",
"DeviceId": "VideoController2",
"PNPDeviceID": "PCI\\VEN_8086\u0026DEV_9BC5\u0026SUBSYS_8754103C\u0026REV_05\\3\u002611583659\u00260\u002610"
},
"HKLMInfo": {
"AdapterString": "SQBuAHQAZQBsACgAUgApACAAVQBIAEQAIABHAHIAYQBwAGgAaQBjAHMAIAA2ADMAMAAAAA==",
"BiosString": "SQBuAHQAZQBsACAAVgBpAGQAZQBvACAAQgBJAE8AUwAAAA==",
"ChipType": "SQBuAHQAZQBsACgAUgApACAAVQBIAEQAIABHAHIAYQBwAGgAaQBjAHMAIABGAGEAbQBpAGwAeQAAAA==",
"DacType": "SQBuAHQAZQByAG4AYQBsAAAA",
"MemorySize": "AAAAQA==",
"QwMemorySize": "Could not determine HardwareInformation.qwMemorySize",
"MatchingDeviceId": "PCI\\VEN_8086\u0026DEV_9BC5\u0026SUBSYS_8754103C"
}
}
]


using Microsoft.Win32;
using System.Management;
using System.Text.Json;
namespace StackGPUQuestion
{
internal class Program
{
static void Main(string[] args)
{
GPUsInfo information = InfoExtractor.SimplifiedCondensationOfCode();
JsonSerializerOptions options = new JsonSerializerOptions() { WriteIndented = true };
string gpuInfoString = JsonSerializer.Serialize(information, options);
Console.WriteLine(gpuInfoString);
}
}
//Extensions---------------------------------------------------------------
public static class Extensions
{
//...
public static T GetPropVal(this ManagementBaseObject obj, string name)
{
//todo improve
//this is still a bit in the works, but it will suffice for this
return (T)obj.GetPropertyValue(name);
}
//...
}
//Extensions---------------------------------------------------------------
//System Management---------------------------------------------------------------
public class WinVideoControllerInfo
{
#region Properties
public string Name { get; set; }
public uint AdapterRAM { get; set; }
public string AdapterDACType { get; set; }
public string VideoProcessor { get; set; }
public string PNPDeviceID { get; set; }
#endregion
public WinVideoControllerInfo()
{
//This is empty on purpose. For the function of generics
}
public WinVideoControllerInfo Construct(ManagementBaseObject obj)//This will seem weird, but it has its use
{
return new WinVideoControllerInfo(obj);
}
public WinVideoControllerInfo(ManagementBaseObject obj)
{
Name = obj.GetPropVal(nameof(Name));
AdapterRAM = obj.GetPropVal(nameof(AdapterRAM));
AdapterDACType = obj.GetPropVal(nameof(AdapterDACType));
VideoProcessor = obj.GetPropVal(nameof(VideoProcessor));
PNPDeviceID = obj.GetPropVal(nameof(PNPDeviceID));
}
}
//System Management---------------------------------------------------------------
//HKLM---------------------------------------------------------------
//HKLM Support---------------------------------------------------------------
public interface IRegistry
{
///
/// Retrieves the value associated with the specified name, in the specified registry key.
/// If the name is not found in the specified key, returns a default value that you provide, or null if the specified key does not exist.
///
/// The full registry path of the key, beginning with a valid registry root, such as "HKEY_CURRENT_USER".
/// The name of the name/value pair.
/// The value to return if valueName does not exist.
///
object? GetValue(string keyName, string valueName, object? defaultValue);
}
public class Registry : IRegistry
{
public static Registry RegistryDefault => new();
public object? GetValue(string keyName, string valueName, object? defaultValue)
{
return Microsoft.Win32.Registry.GetValue(keyName, valueName, defaultValue);
}
}
public readonly struct RegistryEntry
{
///
/// The full registry path of the key, beginning with a valid registry root, such as "HKEY_CURRENT_USER".
///
public string FullPathToKey { get; }
///
/// The name of the name/value pair.
///
public string ValueName { get; }
///
/// The value to return if ValueName does not exist.
///
public string? DefaultValueNotFound { get; }
public RegistryEntry(string fullPathToKey, string valueName, string? defaultValue)
{
FullPathToKey = fullPathToKey;
ValueName = valueName;
DefaultValueNotFound = defaultValue;
}
}
//HKLM Support---------------------------------------------------------------
public class HKLMVideoController
{
private const string HKLMRegistryPathBase = @"HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}\";
private readonly RegistryEntry _adapterStringRegistry;
private readonly RegistryEntry _biosStringRegistry;
private readonly RegistryEntry _chipTypeRegistry;
private readonly RegistryEntry _dacTypeRegistry;
private readonly RegistryEntry _memorySizeRegistry;
private readonly RegistryEntry _qwMemorySizeRegistry;
private readonly RegistryEntry _matchingDeviceIdRegistry;
private IRegistry _registryProvider;
#region Properties
#region Backers
private object _adapterString;
private object _biosString;
private object _chipType;
private object _dacType;
private object _memorySize;
private object _qwMemorySize;
private object _matchingDeviceId;
#endregion
public object AdapterString => _adapterString;
public object BiosString => _biosString;
public object ChipType => _chipType;
public object DacType => _dacType;
public object MemorySize => _memorySize;
public object QwMemorySize => _qwMemorySize;
public object MatchingDeviceId => _matchingDeviceId;
#endregion
private string HKLMRegistryPath;
public HKLMVideoController(string id = "0000")
{
_registryProvider = Registry.RegistryDefault;
HKLMRegistryPath = HKLMRegistryPathBase + id;
_adapterStringRegistry = new(HKLMRegistryPath, "HardwareInformation.AdapterString", null);
_biosStringRegistry = new(HKLMRegistryPath, "HardwareInformation.BiosString", null);
_chipTypeRegistry = new(HKLMRegistryPath, "HardwareInformation.ChipType", null);
_dacTypeRegistry = new(HKLMRegistryPath, "HardwareInformation.DacType", null);
_memorySizeRegistry = new(HKLMRegistryPath, "HardwareInformation.MemorySize", null);
_qwMemorySizeRegistry = new(HKLMRegistryPath, "HardwareInformation.qwMemorySize", null);
_matchingDeviceIdRegistry = new(HKLMRegistryPath, "MatchingDeviceId", null);
SetAllProperties();
}
private void SetAllProperties()
{
_adapterString = GetProperty(_adapterStringRegistry);
_biosString = GetProperty(_biosStringRegistry);
_chipType = GetProperty(_chipTypeRegistry);
_dacType = GetProperty(_dacTypeRegistry);
_memorySize = GetProperty(_memorySizeRegistry);
_qwMemorySize = GetProperty(_qwMemorySizeRegistry);
_matchingDeviceId = GetProperty(_matchingDeviceIdRegistry);
}
private object GetProperty(RegistryEntry propertyEntry)
{
object? propertyValue = _registryProvider.GetValue(propertyEntry.FullPathToKey, propertyEntry.ValueName, propertyEntry.DefaultValueNotFound);
propertyValue ??= Def(propertyEntry.ValueName);
return propertyValue;
}
private object Def(string valueName)
{
String str = $"Could not determine {valueName}";
object ing = str;
return ing;
}
}
//HKLM---------------------------------------------------------------
//Pairing---------------------------------------------------------------
public class VideoControllerPair
{
public WinVideoControllerInfo WinInfo { get; set; }
public HKLMVideoController HKLMInfo { get; set; }
public VideoControllerPair(WinVideoControllerInfo winInfo)
{
string driverPathId = SystemInformationRetriever.PNPToPathId(winInfo.PNPDeviceID);
HKLMVideoController hklmInfo = new(driverPathId);
WinInfo = winInfo;
HKLMInfo = hklmInfo;
}
}
//Pairing---------------------------------------------------------------
public static class SystemInformationRetriever
{
public static string PNPToPathId(string pnpId)
{
RegistryKey pnpRegistryEntry =
Microsoft.Win32.Registry.LocalMachine.OpenSubKey($@"SYSTEM\CurrentControlSet\Enum\{pnpId}");
object? driverValue = pnpRegistryEntry.GetValue("Driver");
string driverPath = driverValue.ToString();
string driverPathId = new(driverPath.TakeLast(4).ToArray());
return driverPathId;
}
}
//Very simplified version
public class GPUsInfo
{
/*
//actual properties
public int GPUCards => GPUUnits.Count;
public List GPUUnits { get; set; }
*/
//Simplified Property
public List Pairs { get; set; }
public GPUsInfo() { }
public GPUsInfo Construct(List winInfos)
{
return new GPUsInfo(winInfos);
}
public GPUsInfo(List winInfos)
{
if (!winInfos.Any())
{
throw new Exception();
}
List pairedInfos = new();
foreach (WinVideoControllerInfo winInfo in winInfos)
{
VideoControllerPair pairedInfo = new VideoControllerPair(winInfo);
pairedInfos.Add(pairedInfo);
}
Pairs = pairedInfos;
/*
// This would be the actual code
List infos = new();
foreach (VideoControllerPair pairedInfo in pairedInfos)
{
GPUInfo info = new GPUInfo(pairedInfo);
infos.Add(info);
}
GPUUnits = infos;
*/
}
}
//The following extract has been a bit modified from the way it persists in the project, so you guys can actually work with it
public static class InfoExtractor
{
public static GPUsInfo SimplifiedCondensationOfCode()
{
//simplified exert of Searcher Getter (GetSearcherResults(area))
string area = "Win32_VideoController";
ManagementObjectSearcher searcher = new ManagementObjectSearcher($"Select * From {area}");
ManagementObjectCollection results = searcher.Get();
//simplified exert of Extracting Information (RetrieveGenericInformation(area))
//ManagementObjectCollection rawInformation = GetSearcherResults(area);
ManagementObjectCollection rawInformation = results;
List winInfos = new List();
foreach (ManagementBaseObject information in rawInformation)
{
WinVideoControllerInfo winInfo = new WinVideoControllerInfo().Construct(information);
winInfos.Add(winInfo);
}
GPUsInfo info = new GPUsInfo().Construct(winInfos);
return info;
}
}
}
Подробнее здесь: https://stackoverflow.com/questions/798 ... n-for-gpus
Мобильная версия