:: SetDiGetDeviceRegistryProperty()失败与Docker for Windows上的SPDRP_BUSTYPEGUID

我不能在Docker Windows容器上获取​​Hyper-V虚拟以太网适配器的总线typesGUID。 主机是Windows Server 2016版本10.0.14393。

重现步骤

  1. 编译SetupDiGetDeviceRegistryPropertyExperimental.cpp,并生成SetupDiGetDeviceRegistryPropertyExperimental.exe
  2. 将SetupDiGetDeviceRegistryPropertyExperimental.exe复制到c:\ data \
  3. 在下面创build一个Dockerfile。
  4. 执行下面的do.bat。

SetupDiGetDeviceRegistryPropertyExperimental.cpp

// SetupDiGetDeviceRegistryPropertyExperimental.cpp : Defines the entry point // for the console application. // #include "stdafx.h" #include <cstdio> #include <string> #include <SetupAPI.h> #include <Windows.h> #include <devguid.h> std::wstring ConvertLastErrorToString(DWORD last_error) { LPVOID lpMessageBuffer = nullptr; ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, last_error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMessageBuffer, 0, NULL); std::wstring error_message = (LPTSTR)lpMessageBuffer; ::LocalFree(lpMessageBuffer); return error_message; } int main() { std::wprintf(L"SetupDiGetDeviceRegistryPropertyExperimental\n"); struct Resource { ~Resource() { if (devinfo) { ::SetupDiDestroyDeviceInfoList(devinfo); devinfo = NULL; } } HDEVINFO devinfo = NULL; } resource; resource.devinfo = ::SetupDiGetClassDevs(&GUID_DEVCLASS_NET, NULL, NULL, 0); if (!resource.devinfo) { DWORD last_error = ::GetLastError(); std::wprintf( L"Failed to call ::SetupDiGetClassDevs(). last_error=0x%08x " L"error_message=%s\n", last_error, ConvertLastErrorToString(last_error).c_str()); return -1; } for (DWORD member_index = 0;; ++member_index) { SP_DEVINFO_DATA devinfo_data = {0}; devinfo_data.cbSize = sizeof(devinfo_data); if (!::SetupDiEnumDeviceInfo(resource.devinfo, member_index, &devinfo_data)) { DWORD last_error = ::GetLastError(); if (last_error == ERROR_NO_MORE_ITEMS) { std::wprintf(L"ERROR_NO_MORE_ITEMS\n"); break; } std::wprintf( L"Failed to call ::SetupDiGetClassDevs(). last_error=0x%08x " L"error_message=%s\n", last_error, ConvertLastErrorToString(last_error).c_str()); return -1; } std::wprintf(L"----------------------------------------\n"); std::wprintf(L"member_index=%d\n", member_index); GUID guid = GUID_NULL; if (!::SetupDiGetDeviceRegistryProperty( resource.devinfo, &devinfo_data, SPDRP_BUSTYPEGUID, NULL, (PBYTE)&guid, sizeof(guid), NULL)) { DWORD last_error = ::GetLastError(); std::wprintf( L"Failed to call ::SetupDiGetDeviceRegistryProperty() with " L"SPDRP_BUSTYPEGUID. last_error=0x%08x error_message=%s\n", last_error, ConvertLastErrorToString(last_error).c_str()); } RPC_WSTR uuid = nullptr; ::UuidToString(&guid, &uuid); std::wstring guid_string = (wchar_t*)uuid; ::RpcStringFree(&uuid); uuid = nullptr; wchar_t device_desc[1024] = {0}; if (!::SetupDiGetDeviceRegistryProperty( resource.devinfo, &devinfo_data, SPDRP_DEVICEDESC, NULL, (PBYTE)device_desc, sizeof(device_desc) - 1, NULL)) { DWORD last_error = ::GetLastError(); std::wprintf( L"Failed to call ::SetupDiGetDeviceRegistryProperty() with " L"SPDRP_DEVICEDESC. last_error=0x%08x error_message=%s\n", last_error, ConvertLastErrorToString(last_error).c_str()); } std::wprintf(L"guid=%s\n", guid_string.c_str()); std::wprintf(L"device_desc=%s\n", device_desc); std::wprintf(L"\n"); } return 0; } 

Dockerfile

 FROM microsoft/windowsservercore CMD [ "cmd" ] 

do.bat

 docker build -t example . docker stop example docker rm example docker run --detach --name example --mount type=bind,source=C:/data,target=C:/data example ping -t localhost docker exec example C:\data\SetupDiGetDeviceRegistryPropertyExperimental.exe 

预期结果

可以检索Hyper-V虚拟以太网适配器的总线typesGUID。

实际结果

发生错误。 由:: GetLastError()返回的错误代码是0x0000000d。 由:: FormatMessage()翻译的错误消息是“数据无效”。

全部产量在下面。

 SetupDiGetDeviceRegistryPropertyExperimental ---------------------------------------- member_index=0 Failed to call ::SetupDiGetDeviceRegistryProperty() with SPDRP_BUSTYPEGUID. last_error=0x0000000d error_message=The data is invalid. guid=00000000-0000-0000-0000-000000000000 device_desc=Hyper-V Virtual Switch Extension Adapter ---------------------------------------- member_index=1 guid=06d10322-7de0-4cef-8e25-197d0e7442e2 device_desc=Microsoft ISATAP Adapter ---------------------------------------- member_index=2 guid=06d10322-7de0-4cef-8e25-197d0e7442e2 device_desc=Microsoft ISATAP Adapter ---------------------------------------- member_index=3 Failed to call ::SetupDiGetDeviceRegistryProperty() with SPDRP_BUSTYPEGUID. last_error=0x0000000d error_message=The data is invalid. guid=00000000-0000-0000-0000-000000000000 device_desc=Microsoft Kernel Debug Network Adapter ---------------------------------------- member_index=4 guid=c8ebdfb0-b510-11d0-80e5-00a0c92542e3 device_desc=Broadcom NetXtreme Gigabit Ethernet ---------------------------------------- member_index=5 guid=c8ebdfb0-b510-11d0-80e5-00a0c92542e3 device_desc=Broadcom NetXtreme Gigabit Ethernet ---------------------------------------- member_index=6 Failed to call ::SetupDiGetDeviceRegistryProperty() with SPDRP_BUSTYPEGUID. last_error=0x0000000d error_message=The data is invalid. guid=00000000-0000-0000-0000-000000000000 device_desc=Hyper-V Virtual Ethernet Adapter ---------------------------------------- member_index=7 Failed to call ::SetupDiGetDeviceRegistryProperty() with SPDRP_BUSTYPEGUID. last_error=0x0000000d error_message=The data is invalid. guid=00000000-0000-0000-0000-000000000000 device_desc=Hyper-V Virtual Ethernet Adapter ---------------------------------------- member_index=8 Failed to call ::SetupDiGetDeviceRegistryProperty() with SPDRP_BUSTYPEGUID. last_error=0x0000000d error_message=The data is invalid. guid=00000000-0000-0000-0000-000000000000 device_desc=Hyper-V Virtual Ethernet Adapter ERROR_NO_MORE_ITEMS 

当我在Windows 10 Pro版本10.0.16299.15的Windows容器上执行SetupDiGetDeviceRegistryPropertyExperimental.exe时,程序崩溃了:: SetupDiGetDeviceRegistryProperty()。 但这是另一回事。

如何在Windows Server 2016上的Windows容器上获取​​Hyper-V虚拟以太网适配器的总线子typesGUID?