第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何枚舉 NVMe (M2) 驅動器并在 c# 中獲取它們的溫度?

如何枚舉 NVMe (M2) 驅動器并在 c# 中獲取它們的溫度?

C#
寶慕林4294392 2022-10-23 14:02:19
如何枚舉 NVMe (M2) 驅動器并在 c# 中獲取它們的溫度?它不能通過 WMI 常規(guī)查詢訪問。有這個 MSFT 參考在 c 中執(zhí)行此操作,但它相當模糊,代碼不完整: https ://learn.microsoft.com/en-us/windows/desktop/fileio/working-with-nvme-devices#temperature-查詢
查看完整描述

1 回答

?
慕姐8265434

TA貢獻1813條經驗 獲得超2個贊

一個快速的實現(但不是最簡單的)是使用 nvme.h winioctl.h ntddstor.h API 并在 c# 中與它互操作。這是一個完整的實現。


申報方:


#include <nvme.h>

#include <winioctl.h>

#include <ntddstor.h>


#ifndef Pinvoke

#define Pinvoke extern "C" __declspec(dllexport)

#endif


typedef void(__stdcall *MessageChangedCallback)(const wchar_t* string);


class __declspec(dllexport) NVmeQuery final

{

public:

    NVmeQuery(MessageChangedCallback managedDelegate);

    ~NVmeQuery();

    template <class ... T>

    auto LogMessage(T&& ... args) -> void;

    auto GetTemp(const wchar_t* nvmePath) -> unsigned long;


    MessageChangedCallback LogMessageChangedCallback{};


    PNVME_HEALTH_INFO_LOG SmartHealthInfo{};

    PSTORAGE_PROPERTY_QUERY query{};

    PSTORAGE_PROTOCOL_SPECIFIC_DATA protocolSpecificData{};

    PSTORAGE_PROTOCOL_DATA_DESCRIPTOR protocolDataDescriptor{};

};

定義端:我用來向托管端追溯互操作錯誤消息的功能;這對于理解哪里出了問題、如何/哪里出了問題至關重要:


template<class ...T>

auto NVmeQuery::LogMessage(T&&... args) -> void

{

    wchar_t updatedMessage[256];

    swprintf_s(updatedMessage, forward<T>(args)...);

    if (LogMessageChangedCallback != nullptr)

        LogMessageChangedCallback(updatedMessage);

}

核心功能,設計起來并不簡單。它有 4 個部分: 1. 獲取 NVMe 驅動器的句柄 2. 準備查詢 3. 執(zhí)行查詢 4. 檢查并傳輸結果


auto NVmeQuery::GetTemp(const wchar_t* nvmePath) -> unsigned long

{

    auto nvmeHandle = CreateFile(nvmePath, 0, 0,

        0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

    {

        auto lastErrorID = GetLastError();

        if (lastErrorID != 0)

        {

            LPVOID errorBuffer{};

            FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,

                nullptr, lastErrorID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errorBuffer, 0, nullptr);

            LogMessage(L"Query: ERROR creating handle to NVMe [%s]: %d, %s", nvmePath, lastErrorID, errorBuffer);

        }

    }


    unsigned long bufferLength = FIELD_OFFSET(STORAGE_PROPERTY_QUERY, AdditionalParameters)

        + sizeof(STORAGE_PROTOCOL_SPECIFIC_DATA) + NVME_MAX_LOG_SIZE;

    void *buffer = malloc(bufferLength);

    ZeroMemory(buffer, bufferLength);


    query = (PSTORAGE_PROPERTY_QUERY)buffer;

    protocolDataDescriptor = (PSTORAGE_PROTOCOL_DATA_DESCRIPTOR)buffer;

    protocolSpecificData = (PSTORAGE_PROTOCOL_SPECIFIC_DATA)query->AdditionalParameters;


    query->PropertyId = StorageDeviceProtocolSpecificProperty;

    query->QueryType = PropertyStandardQuery;


    protocolSpecificData->ProtocolType = ProtocolTypeNvme;

    protocolSpecificData->DataType = NVMeDataTypeLogPage;

    protocolSpecificData->ProtocolDataRequestValue = NVME_LOG_PAGE_HEALTH_INFO;

    protocolSpecificData->ProtocolDataRequestSubValue = 0;

    protocolSpecificData->ProtocolDataOffset = sizeof(STORAGE_PROTOCOL_SPECIFIC_DATA);

    protocolSpecificData->ProtocolDataLength = sizeof(NVME_HEALTH_INFO_LOG);


    unsigned long returnedLength{};

繼續(xù),實際查詢,然后是雜項檢查:


    auto result = DeviceIoControl(nvmeHandle, IOCTL_STORAGE_QUERY_PROPERTY,

        buffer, bufferLength,

        buffer, bufferLength,

        &returnedLength, nullptr);


    if (!result || returnedLength == 0)

    {

        auto lastErrorID = GetLastError();

        LPVOID errorBuffer{};

        FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,

            nullptr, lastErrorID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errorBuffer, 0, nullptr);

        LogMessage(L"Query: drive path: %s, nvmeHandle %lu", nvmePath, nvmeHandle);

        LogMessage(L"Query: ERROR DeviceIoControl 0x%x %s", lastErrorID, errorBuffer);

    }


    if (protocolDataDescriptor->Version != sizeof(STORAGE_PROTOCOL_DATA_DESCRIPTOR) ||

        protocolDataDescriptor->Size != sizeof(STORAGE_PROTOCOL_DATA_DESCRIPTOR))

    {

        LogMessage(L"Query: Data descriptor header not valid (size of descriptor: %llu)", sizeof(STORAGE_PROTOCOL_DATA_DESCRIPTOR));

        LogMessage(L"Query: DataDesc: version %lu, size %lu", protocolDataDescriptor->Version, protocolDataDescriptor->Size);

    }


    protocolSpecificData = &protocolDataDescriptor->ProtocolSpecificData;

    if (protocolSpecificData->ProtocolDataOffset < sizeof(STORAGE_PROTOCOL_SPECIFIC_DATA) ||

        protocolSpecificData->ProtocolDataLength < sizeof(NVME_HEALTH_INFO_LOG))

        LogMessage(L"Query: ProtocolData Offset/Length not valid");


    SmartHealthInfo = (PNVME_HEALTH_INFO_LOG)((PCHAR)protocolSpecificData + protocolSpecificData->ProtocolDataOffset);

    CloseHandle(nvmeHandle);

    auto temp = ((ULONG)SmartHealthInfo->Temperature[1] << 8 | SmartHealthInfo->Temperature[0]) - 273;

    return temp;

} // end of GetTemp

對于互操作:


Pinvoke auto __stdcall New(MessageChangedCallback managedDelegate) -> NVmeQuery*

{

    return new NVmeQuery(managedDelegate);

}


Pinvoke auto GetTemp(NVmeQuery* p, const wchar_t* nvmePath) -> unsigned long

{

    return p->GetTemp(nvmePath);

}

和 c# 方面:


public static class NVMeQuery

{

    [DllImport("NVMeQuery.dll", CallingConvention = CallingConvention.StdCall)]

    internal static extern IntPtr New(InteropBase.AssetCallback callback);

    [DllImport("NVMeQuery.dll", CallingConvention = CallingConvention.Cdecl)]

    internal static extern ulong GetTemp(IntPtr p, IntPtr drivePath);

}


public class NVMeQueries : InteropBase

{

    public NVMeQueries()

    {

        _ptr = NVMeQuery.New(_onAssetErrorMessageChanged);

    }


    public ulong GetTemp() => GetTemp(@"\\.\PhysicalDrive4");


    public ulong GetTemp(string drivePath)

    {

        var strPtr = Marshal.StringToHGlobalAuto(drivePath);

        var result = NVMeQuery.GetTemp(_ptr, strPtr);

        Marshal.FreeHGlobal(strPtr);

        return result;

    }

}

我用于互操作的通用基類:


public class InteropBase : INotifyPropertyChanged

{

    protected IntPtr _ptr;

    protected readonly AssetCallback _onAssetErrorMessageChanged;


    public delegate void AssetCallback(IntPtr strPtr);


    public List<string> LogMessages { get; private set; } = new List<string>();


    public InteropBase()

    {

        _onAssetErrorMessageChanged = LogUpdater;

    }


    private unsafe void LogUpdater(IntPtr strPtr)

    {

        var LastLogMessage = new string((char*)strPtr);

        LogMessages.Add(LastLogMessage);

        OnPropertyChanged(nameof(LogMessages));

    }


    public event PropertyChangedEventHandler PropertyChanged;


    [NotifyPropertyChangedInvocator]

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)

    {

        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

    }

}

就我而言,我想查詢的 NVMe 驅動器是第四個物理驅動器。我們得到所有這些:


Get-WmiObject Win32_DiskDrive

在我的情況下,這將給出:


Partitions : 4

DeviceID   : \\.\PHYSICALDRIVE4

Model      : Samsung SSD 970 EVO Plus 1TB

Size       : 1000202273280

Caption    : Samsung SSD 970 EVO Plus 1TB

評論

這個實現非??欤]有 LogMessage 調用時不到 1ms);您可以定義和填寫自己的結構,以獲取其他相關信息;在這種情況下,該結構必須保存在本機類的字段中(例如,SmartHealthInfo在本例中),并且查詢將只傳輸指向該結構的指針。


查看完整回答
反對 回復 2022-10-23
  • 1 回答
  • 0 關注
  • 247 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號