此代码导致以下异常,有时:
“尝试读取或写入受保护的 记忆。这通常是一个迹象 其他记忆是腐败的“
private static TOKEN_GROUPS GetTokenGroups(IntPtr tokenHandle)
{
var groups = new TOKEN_GROUPS();
uint tokenInfoLength = 0;
uint returnLength;
var res = GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenGroups, IntPtr.Zero,
tokenInfoLength, out returnLength);
if (!res && returnLength > 0)
{
tokenInfoLength = returnLength;
var tokenInfo = Marshal.AllocHGlobal((int) tokenInfoLength);
res = GetTokenInformation(tokenHandle,
TOKEN_INFORMATION_CLASS.TokenGroups,
tokenInfo,
tokenInfoLength,
out returnLength);
if(res)
{
groups = (TOKEN_GROUPS)Marshal.PtrToStructure(tokenInfo, typeof (TOKEN_GROUPS));
}
Marshal.FreeHGlobal(tokenInfo);
CloseHandle(tokenHandle);
}
else
{
var error = new Win32Exception(Marshal.GetLastWin32Error());
_log.WarnFormat("Failed evaluate the call to get process token information. {0}", error.Message);
}
return groups;
}
失败的行是groups = (TOKEN_GROUPS)Marshal.PtrToStructure(tokenInfo, typeof (TOKEN_GROUPS));
我会说异常发生在1和每20次调用此方法。一旦它开始发生,之后的每个调用都会抛出异常。重新启动该过程会导致错误消失。
IntPtr tokenHandle
的结果是:
var processId = GetCurrentProcess();
_log.InfoFormat("Process ID [{0}]", processId.ToString());
if (processId != IntPtr.Zero)
{
IntPtr tokenHandle;
if (OpenProcessToken(processId, TOKEN_READ, out tokenHandle))
{
groups = GetTokenGroups(tokenHandle);
}
编辑希望这不是信息过载,但这是pinvoke声明:
struct TOKEN_GROUPS
{
public uint GroupCount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4000)]
public SID_AND_ATTRIBUTES[] Groups;
}
[StructLayout(LayoutKind.Sequential)]
struct SID_AND_ATTRIBUTES
{
public IntPtr SID;
public uint Attributes;
}
[DllImport("advapi32.dll", SetLastError = true)]
static extern bool GetTokenInformation(
IntPtr TokenHandle,
TOKEN_INFORMATION_CLASS TokenInformationClass,
IntPtr TokenInformation,
uint TokenInformationLength,
out uint ReturnLength);
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool OpenProcessToken(IntPtr ProcessHandle,
UInt32 DesiredAccess, out IntPtr TokenHandle);
[DllImport("kernel32.dll")]
static extern IntPtr GetCurrentProcess();
enum TOKEN_INFORMATION_CLASS
{
TokenUser = 1,
TokenGroups,
TokenPrivileges,
TokenOwner,
TokenPrimaryGroup,
TokenDefaultDacl,
TokenSource,
TokenType,
TokenImpersonationLevel,
TokenStatistics,
TokenRestrictedSids,
TokenSessionId,
TokenGroupsAndPrivileges,
TokenSessionReference,
TokenSandBoxInert,
TokenAuditPolicy,
TokenOrigin
}
答案 0 :(得分:3)
我的猜测是,错误是由于未正确释放资源造成的,就像您的情况一样。我可能错了,但是包裹FreeHGlobal
和CloseHandle
in a finally
block可能是个好主意,以确保正确清理。
如果错误仍然存在,则可能是其他内容(错误的结构或wrong data layout in the declaration或错误LayoutKind for TOKEN_GROUPS?)或错误使用此特定API(我不太熟悉)。
问题可能在于必要的SizeConst
属性参数。请考虑以下事项:GetTokenInformation已经给出了tokeInfoLength中返回的大小。你分配这个。此大小不太可能等于SizeConst
值。如果SizeConst
大于所需大小,则Marshal.PtrToStructure
将进一步访问您分配的长度,因为它只知道SizeConst
,并且此内存可能是可访问的,并且可能不是
要解决此问题,请确保AllocHGlobal
调用至少是整个结构的大小