是否可以/允许从这样的 C# pinvoke 代码返回结构体的取消引用指针。 该结构是 blittable 的。 Pinvoke 代码和结构是使用 CsWin32 生成的。感谢您提供与此相关的任何帮助:)
internal static unsafe IEnumerable<ENUM_SERVICE_STATUS_PROCESSW> GetAllServices(this CloseServiceHandleSafeHandle serviceManagerHandle, string? group)
{
ArgumentNullException.ThrowIfNull(serviceManagerHandle);
var data = new List<ENUM_SERVICE_STATUS_PROCESSW>();
var serviceManagerHandleAddRef = false;
try
{
serviceManagerHandle.DangerousAddRef(ref serviceManagerHandleAddRef);
bool moreData;
uint bytesNeeded = 0, resumeHandle = 0, servicesReturned = 0;
do
{
moreData = false;
var bufferData = new byte[bytesNeeded];
fixed (byte* ptrBufferData = bufferData)
{
fixed (char* ptrGroup = group)
{
if (!PInvokeCore.EnumServicesStatusEx((SC_HANDLE)serviceManagerHandle.DangerousGetHandle(), SC_ENUM_TYPE.SC_ENUM_PROCESS_INFO, ENUM_SERVICE_TYPE.SERVICE_WIN32_OWN_PROCESS, ENUM_SERVICE_STATE.SERVICE_STATE_ALL, ptrBufferData, (uint)bufferData.Length, &bytesNeeded, &servicesReturned, &resumeHandle, ptrGroup))
{
if (Marshal.GetLastPInvokeError() != (uint)WIN32_ERROR.ERROR_MORE_DATA)
throw new Exception($"Could not enumerate services. {Marshal.GetLastPInvokeErrorMessage()}");
else
moreData = true;
}
}
for (var i = 0; i < servicesReturned; i++)
{
ENUM_SERVICE_STATUS_PROCESSW element = ((ENUM_SERVICE_STATUS_PROCESSW*)ptrBufferData)[i];
data.Add(element);
}
}
} while (moreData);
}
finally
{
if (serviceManagerHandleAddRef)
serviceManagerHandle.DangerousRelease();
}
return data;
}
它可以工作,但我不确定这是否是非法操作。
答案是否定的,它不是保存返回结构体。结构本身是一个副本,因此可以安全返回,但结构中是一个 PWSTR 又名 char* ,并且该指针指向 byte* 中的一个区域(就在结构数组之后),该区域在函数返回后无效.