我目前正在开发一个用于监视其他几个进程的 C# 应用程序。我想偶尔转储这些进程。为此,目前我正在使用 PInvokingMiniDumpWriteDump()
功能。我有一个命令行实用程序和一个图形实用程序,它们 PInvokeMiniDumpWriteDump()
函数。我目前面临的问题是,我在使用命令行实用程序时得到了完美的内存转储,但是从调用相同函数的图形实用程序中,它每次都会创建一个空文件(即使以管理员身份运行)。GetLastWin32Error()
给出0x80000057
- ,但在这Parameter is invalid
两种情况下我都将完全相同的值传递给我的 PInvoked 函数。所以我怀疑无效值错误来自一些调用MiniDumpWriteDump()
正在内部进行,我最好的猜测是这是一个进程特权问题。我想在这里知道一些事情:
- 默认情况下,命令行实用程序和图形实用程序在启动时的权限有什么区别吗?
- 如果它不是特权问题,那么我面临的问题的可能原因是什么?
- 如果是权限问题,是否有任何方法可以
SE_DEBUG_NAME
使用 C#(没有 PInvokingAdjustTokenPrivileges()
和相关功能)从我的实用程序启用权限?
这是我的 PInvoke 声明:
public enum Typ : uint
{
// From dbghelp.h:
MiniDumpNormal = 0x00000000,
MiniDumpWithDataSegs = 0x00000001,
MiniDumpWithFullMemory = 0x00000002,
MiniDumpWithHandleData = 0x00000004,
MiniDumpFilterMemory = 0x00000008,
MiniDumpScanMemory = 0x00000010,
MiniDumpWithUnloadedModules = 0x00000020,
MiniDumpWithIndirectlyReferencedMemory = 0x00000040,
MiniDumpFilterModulePaths = 0x00000080,
MiniDumpWithProcessThreadData = 0x00000100,
MiniDumpWithPrivateReadWriteMemory = 0x00000200,
MiniDumpWithoutOptionalData = 0x00000400,
MiniDumpWithFullMemoryInfo = 0x00000800,
MiniDumpWithThreadInfo = 0x00001000,
MiniDumpWithCodeSegs = 0x00002000,
MiniDumpWithoutAuxiliaryState = 0x00004000,
MiniDumpWithFullAuxiliaryState = 0x00008000,
MiniDumpWithPrivateWriteCopyMemory = 0x00010000,
MiniDumpIgnoreInaccessibleMemory = 0x00020000,
MiniDumpWithTokenInformation = 0x00040000,
MiniDumpValidTypeFlags = 0x0003ffff,
};
[DllImport("dbghelp.dll",
EntryPoint = "MiniDumpWriteDump",
CallingConvention = CallingConvention.StdCall,
CharSet = CharSet.Unicode,
ExactSpelling = true, SetLastError = true)]
static extern bool MiniDumpWriteDump(
IntPtr hProcess,
uint processId,
IntPtr hFile,
uint dumpType,
IntPtr expParam,
IntPtr userStreamParam,
IntPtr callbackParam);
public static bool Write(string fileName, IntPtr prochandle, uint procid)
{
return Write(fileName, (Typ.MiniDumpWithFullMemory|Typ.MiniDumpWithDataSegs|Typ.MiniDumpWithHandleData|Typ.MiniDumpWithThreadInfo|Typ.MiniDumpWithTokenInformation), prochandle, procid);
}
public static bool Write(string fileName, Typ dumpTyp, IntPtr prochandle, uint procid)
{
using (var fs = new System.IO.FileStream(fileName, System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.None))
{
bool bRet = MiniDumpWriteDump(
prochandle,
procid,
fs.SafeFileHandle.DangerousGetHandle(),
(uint)dumpTyp,
IntPtr.Zero,
IntPtr.Zero,
IntPtr.Zero);
if (!bRet)
{
throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
}
return bRet;
}
}
}
这是我的调用方式(使用来自控制台和 GUI 应用程序的相同函数 dump()):
void dump(procId, filePath)
{
Process p = Process.GetProcessById(procId);
MiniDumper.Write(filePath, p.Handle, (uint)p.Id);
}