PowerReadFriendlyName 报告错误的缓冲区长度

问题描述 投票:0回答:1

我正在制作一个 C# 程序,通过 PInvoking Win32 函数 PowerReadFriendlyName 从电源管理方案的 GUID 中检索其名称。然而,该函数似乎报告错误的缓冲区长度。

Guid id = new Guid("381b4222-f694-41f0-9685-ff5bb260df2e"); // "Balanced" scheme GUID
uint length = 0;

IntPtr ptr = GCHandle.ToIntPtr(GCHandle.Alloc(id));
Marshal.StructureToPtr(id, ptr, true);

PowerReadFriendlyName(IntPtr.Zero, ptr, IntPtr.Zero, IntPtr.Zero, null, ref length);
byte[] buffer = new byte[length];
PowerReadFriendlyName(IntPtr.Zero, ptr, IntPtr.Zero, IntPtr.Zero, buffer, ref length);

PowerReadFriendlyName
被调用两次。一次使用空指针作为缓冲区,用于检索所需的缓冲区长度。再次使用具有正确长度的缓冲区,用于实际读取名称。

第一次调用后,

length
是一个大得离谱的数字,但对于
Balanced
方案来说它始终是126

第二次调用后,

buffer
已填充了正确的字符,
length
突然变成了
20
,听起来更正确。

两个调用都会返回

ERROR_SUCCESS

TL;DR: 根据 MSDN 上的文档,作为缓冲区的空引用使函数报告所需的缓冲区长度。但是,当存在空引用时,会报告错误的最小长度。传递数组(空或非空)使函数报告正确的最小长度。

是什么原因导致这种行为以及如何预防?

PowerReadFriendlyName
声明如下:

[DllImport("powrprof.dll")]
public static extern UInt32 PowerReadFriendlyName
(
    IntPtr RootPowerKey, 
    IntPtr SchemeGuid, 
    IntPtr SubGroupOfPowerSettingsGuid, 
    IntPtr PowerSettingGuid, 
    Byte[] Buffer, 
    ref UInt32 BufferSize
);

测试不同的方案:高性能方案使第一个调用报告

114
,而第二个调用报告
22

编辑:可能值得注意的是,Balanced已本地化Balansert,而高性能在调试环境中是Høy ytelse

c# winapi pinvoke power-management ref
1个回答
0
投票

至于为什么返回的大小大于(/不匹配)所需的确切数量,“返回所需缓冲区大小的函数通常返回上限,而不是严格的界限” - https://devblogs.microsoft。 com/oldnewthing/20240214-00/?p=109400

© www.soinside.com 2019 - 2024. All rights reserved.