1

我目前正在开发一个用于监视其他几个进程的 C# 应用程序。我想偶尔转储这些进程。为此,目前我正在使用 PInvokingMiniDumpWriteDump()功能。我有一个命令行实用程序和一个图形实用程序,它们 PInvokeMiniDumpWriteDump()函数。我目前面临的问题是,我在使用命令行实用程序时得到了完美的内存转储,但是从调用相同函数的图形实用程序中,它每次都会创建一个空文件(即使以管理员身份运行)。GetLastWin32Error()给出0x80000057- ,但在这Parameter is invalid两种情况下我都将完全相同的值传递给我的 PInvoked 函数。所以我怀疑无效值错误来自一些调用MiniDumpWriteDump()正在内部进行,我最好的猜测是这是一个进程特权问题。我想在这里知道一些事情:

  1. 默认情况下,命令行实用程序和图形实用程序在启动时的权限有什么区别吗?
  2. 如果它不是特权问题,那么我面临的问题的可能原因是什么?
  3. 如果是权限问题,是否有任何方法可以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);
}
4

0 回答 0