سؤال

لقد حصلت على System.Diagnostics.Process هدف.لي ج# يقوم البرنامج بمراقبته لبعض الحالات.عند الوصول إلى الشرط، أريد إجراء تفريغ كامل للذاكرة للعملية.

ما هي أفضل طريقة لتحقيق ذلك؟

هل هناك طريقة يوفرها CLR?

هل كانت مفيدة؟

المحلول

يمكنك استخدام ProcDump من Sysinternals واجعل برنامج C# الخاص بك يستدعيه عند الحاجة.

Process.Start("procdump " + otherProgramPID.ToString());

نصائح أخرى

يمكنك محاولة استدعاء طريقة C++ من كود C# الخاص بك.فيما يلي مثال لكيفية إعلان ذلك:

    [DllImport("dbghelp.dll",
        EntryPoint = "MiniDumpWriteDump",
        CallingConvention = CallingConvention.StdCall,
        CharSet = CharSet.Unicode,
        ExactSpelling = true,
        SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool MiniDumpWriteDump(
        IntPtr hProcess,
        uint processId,
        SafeHandle hFile,
        MINIDUMP_TYPE dumpType,
        IntPtr expParam,
        IntPtr userStreamParam,
        IntPtr callbackParam);

يمكنك التحقق من رمز هذا المشروع على سبيل المثال:https://github.com/projectkudu/kudu/blob/master/Kudu.Core/Infrastructure/MiniDumpNativeMethods.cs https://github.com/projectkudu/kudu/blob/2db563be679bb60656050ec3f04945086f07b360/Kudu.Core/Infrastructure/ProcessExtensions.cs

يسرد Microsoft MSDN مثالاً للتعليمات البرمجية حول كيفية تحقيق ذلك باستخدام كود C# داخل التطبيق الخاص بك:

using System;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;

// !load \\ddelementary\autowatson\vsdbg\vsdbg.dll

namespace CreateMiniDump
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.Loaded += (ol, el) =>
            {
                IntPtr hFile = IntPtr.Zero;
                try
                {
                    if (IntPtr.Size == 4)
                    {
                        this.Title = "CreateMiniDump Running as 32 bit, creating 32 bit dumps";
                    }
                    else
                    {
                        this.Title = "CreateMiniDump Running as 64 bit, creating 64 bit dumps";
                    }
                    this.Height = 800;
                    this.Width = 800;
                    var sp = new StackPanel() { Orientation = Orientation.Vertical };
                    this.Content = sp;
                    var dumpFileName = System.IO.Path.Combine(
                              System.IO.Path.GetTempPath(),
                              "testdump.dmp");
                    var txtDumpFile = new TextBox()
                    {
                        Text = dumpFileName
                    };
                    sp.Children.Add(txtDumpFile);

                    var txtProcName = new TextBox()
                    {
                        ToolTip = "Process name without extension",
                        Text = "devenv"
                    };
                    sp.Children.Add(txtProcName);
                    var lstDumpType = new ListBox()
                    {
                        // allow multi select
                        SelectionMode = SelectionMode.Extended
                    };
                    lstDumpType.ItemsSource = Enum.GetValues(typeof(NativeMethods._MINIDUMP_TYPE));
                    // set initial value
                    // for a dump with memory info we want these:
                    foreach (var val in new[] {
                  NativeMethods._MINIDUMP_TYPE.MiniDumpWithFullMemory,
                  NativeMethods._MINIDUMP_TYPE.MiniDumpWithFullMemoryInfo,
                  NativeMethods._MINIDUMP_TYPE.MiniDumpWithHandleData,
                  NativeMethods._MINIDUMP_TYPE.MiniDumpWithThreadInfo
            })
                    {
                        var nval = (int)(Math.Log((int)val) / Math.Log(2)) + 1;
                        lstDumpType.SelectedItems.Add(
                                  lstDumpType.Items[nval]
                          );
                    }
                    sp.Children.Add(lstDumpType);

                    var btnGo = new Button()
                    {
                        Content = "_Create Dump",
                        Width = 200
                    };
                    sp.Children.Add(btnGo);
                    var txtStatus = new TextBox()
                    {
                        IsUndoEnabled = false,
                        VerticalScrollBarVisibility = ScrollBarVisibility.Auto,
                        MaxHeight = 400
                    };
                    sp.Children.Add(txtStatus);
                    btnGo.Click += (ob, eb) =>
                      {
                          try
                          {
                              var sw = new Stopwatch();
                              sw.Start();
                              dumpFileName = txtDumpFile.Text.Trim();
                              if (System.IO.File.Exists(dumpFileName))
                              {
                                  System.IO.File.Delete(dumpFileName);
                              }
                              hFile = NativeMethods.CreateFile(
                                dumpFileName,
                                NativeMethods.EFileAccess.GenericWrite,
                                NativeMethods.EFileShare.None,
                                lpSecurityAttributes: IntPtr.Zero,
                                dwCreationDisposition: NativeMethods.ECreationDisposition.CreateAlways,
                                dwFlagsAndAttributes: NativeMethods.EFileAttributes.Normal,
                                hTemplateFile: IntPtr.Zero
                              );
                              if (hFile == NativeMethods.INVALID_HANDLE_VALUE)
                              {
                                  var hr = Marshal.GetHRForLastWin32Error();
                                  var ex = Marshal.GetExceptionForHR(hr);
                                  throw ex;
                              }
                              NativeMethods._MINIDUMP_TYPE dumpType = NativeMethods._MINIDUMP_TYPE.MiniDumpNormal; // 0
                              foreach (var item in lstDumpType.SelectedItems)
                              {
                                  var dt = (NativeMethods._MINIDUMP_TYPE)item;
                                  dumpType |= dt;
                              }

                              var exceptInfo = new NativeMethods.MINIDUMP_EXCEPTION_INFORMATION();
                              var proc = Process.GetProcessesByName(
                                  txtProcName.Text.Trim()
                                  ).FirstOrDefault();

                              if (!proc.Is32BitProcess() && IntPtr.Size == 4)
                              {
                                  throw new InvalidOperationException(
                                    "Can't create 32 bit dump of 64 bit process"
                                    );
                              }

                              var result = NativeMethods.MiniDumpWriteDump(
                                        proc.Handle,
                                        proc.Id,
                                        hFile,
                                        dumpType,
                                        ref exceptInfo,
                                        UserStreamParam: IntPtr.Zero,
                                        CallbackParam: IntPtr.Zero
                                        );
                              if (result == false)
                              {
                                  var hr = Marshal.GetHRForLastWin32Error();
                                  var ex = Marshal.GetExceptionForHR(hr);
                                  throw ex;
                              }

                              txtStatus.Text = string.Format(
                                        "Dump Created. Pid= {0} {1}\r File size = {2:n0}\rElapsed = {3:n3}\r",
                                        proc.Id,
                                        dumpType,
                                        (new System.IO.FileInfo(dumpFileName)).Length,
                                        sw.Elapsed.TotalSeconds
                                        );
                          }
                          catch (Exception ex)
                          {
                              txtStatus.Text = ex.ToString();
                          }
                          finally
                          {
                              NativeMethods.CloseHandle(hFile);
                          }
                      };
                }
                catch (Exception ex)
                {
                    this.Content = ex.ToString();
                }
            };
        }
    }
    public static class ExtensionMethods
    {
        public static bool Is32BitProcess(this Process proc)
        {
            bool fIs32bit = false;
            // if we're runing on 32bit, default to true
            if (IntPtr.Size == 4)
            {
                fIs32bit = true;
            }
            bool fIsRunningUnderWow64 = false;
            // if machine is 32 bit then all procs are 32 bit
            if (NativeMethods.IsWow64Process(NativeMethods.GetCurrentProcess(), out fIsRunningUnderWow64)
                && fIsRunningUnderWow64)
            {
                // current OS is 64 bit
                if (NativeMethods.IsWow64Process(proc.Handle, out fIsRunningUnderWow64)
                      && fIsRunningUnderWow64)
                {
                    fIs32bit = true;
                }
                else
                {
                    fIs32bit = false;
                }
            }
            return fIs32bit;
        }
    }
    public static partial class NativeMethods
    {
        [DllImport("Dbghelp.dll")]
        public static extern bool MiniDumpWriteDump(
            IntPtr hProcess,
            int ProcessId,
            IntPtr hFile,
            _MINIDUMP_TYPE DumpType,
            ref MINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
            IntPtr UserStreamParam,
            IntPtr CallbackParam
            );
        //https://msdn.microsoft.com/en-us/library/windows/desktop/ms680519%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
        [Flags]
        public enum _MINIDUMP_TYPE
        {
            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,
            MiniDumpWithModuleHeaders = 0x00080000,
            MiniDumpFilterTriage = 0x00100000,
            MiniDumpValidTypeFlags = 0x001fffff,
        };
        /*
         * 
    https://msdn.microsoft.com/en-us/library/windows/desktop/bb513622(v=vs.85).aspx
    WER_DUMP_TYPE:
    WerDumpTypeHeapDump
        MiniDumpWithDataSegs
        MiniDumpWithProcessThreadData
        MiniDumpWithHandleData
        MiniDumpWithPrivateReadWriteMemory
        MiniDumpWithUnloadedModules
        MiniDumpWithFullMemoryInfo
        MiniDumpWithThreadInfo (Windows 7 and later)
        MiniDumpWithTokenInformation (Windows 7 and later)
        MiniDumpWithPrivateWriteCopyMemory 
    WerDumpTypeMicroDump
        MiniDumpWithDataSegs
        MiniDumpWithUnloadedModules
        MiniDumpWithProcessThreadData
        MiniDumpWithoutOptionalData

    WerDumpTypeMiniDump
        MiniDumpWithDataSegs
        MiniDumpWithUnloadedModules
        MiniDumpWithProcessThreadData
        MiniDumpWithTokenInformation 
         */

        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        public struct MINIDUMP_EXCEPTION_INFORMATION
        {
            public uint ThreadId;
            public IntPtr ExceptionPointers;
            public int ClientPointers;
        }

        [DllImport("kernel32.dll",
          SetLastError = true,
          CharSet = CharSet.Auto)]
        public static extern IntPtr CreateFile(
                string lpFileName,
                EFileAccess dwDesiredAccess,
                EFileShare dwShareMode,
                IntPtr lpSecurityAttributes,
                ECreationDisposition dwCreationDisposition,
                EFileAttributes dwFlagsAndAttributes,
                IntPtr hTemplateFile
            );

        [DllImport("kernel32.dll",
          SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool CloseHandle(IntPtr hObject);

        public static IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
        [Flags]
        public enum EFileAccess : uint
        {
            //
            // Standart Section
            //

            AccessSystemSecurity = 0x1000000,   // AccessSystemAcl access type
            MaximumAllowed = 0x2000000,     // MaximumAllowed access type

            Delete = 0x10000,
            ReadControl = 0x20000,
            WriteDAC = 0x40000,
            WriteOwner = 0x80000,
            Synchronize = 0x100000,

            StandardRightsRequired = 0xF0000,
            StandardRightsRead = ReadControl,
            StandardRightsWrite = ReadControl,
            StandardRightsExecute = ReadControl,
            StandardRightsAll = 0x1F0000,
            SpecificRightsAll = 0xFFFF,

            FILE_READ_DATA = 0x0001,        // file & pipe
            FILE_LIST_DIRECTORY = 0x0001,       // directory
            FILE_WRITE_DATA = 0x0002,       // file & pipe
            FILE_ADD_FILE = 0x0002,         // directory
            FILE_APPEND_DATA = 0x0004,      // file
            FILE_ADD_SUBDIRECTORY = 0x0004,     // directory
            FILE_CREATE_PIPE_INSTANCE = 0x0004, // named pipe
            FILE_READ_EA = 0x0008,          // file & directory
            FILE_WRITE_EA = 0x0010,         // file & directory
            FILE_EXECUTE = 0x0020,          // file
            FILE_TRAVERSE = 0x0020,         // directory
            FILE_DELETE_CHILD = 0x0040,     // directory
            FILE_READ_ATTRIBUTES = 0x0080,      // all
            FILE_WRITE_ATTRIBUTES = 0x0100,     // all

            //
            // Generic Section
            //

            GenericRead = 0x80000000,
            GenericWrite = 0x40000000,
            GenericExecute = 0x20000000,
            GenericAll = 0x10000000,

            SPECIFIC_RIGHTS_ALL = 0x00FFFF,
            FILE_ALL_ACCESS =
            StandardRightsRequired |
            Synchronize |
            0x1FF,

            FILE_GENERIC_READ =
            StandardRightsRead |
            FILE_READ_DATA |
            FILE_READ_ATTRIBUTES |
            FILE_READ_EA |
            Synchronize,

            FILE_GENERIC_WRITE =
            StandardRightsWrite |
            FILE_WRITE_DATA |
            FILE_WRITE_ATTRIBUTES |
            FILE_WRITE_EA |
            FILE_APPEND_DATA |
            Synchronize,

            FILE_GENERIC_EXECUTE =
            StandardRightsExecute |
              FILE_READ_ATTRIBUTES |
              FILE_EXECUTE |
              Synchronize
        }

        [Flags]
        public enum EFileShare : uint
        {
            /// <summary>
            /// 
            /// </summary>
            None = 0x00000000,
            /// <summary>
            /// Enables subsequent open operations on an object to request read access. 
            /// Otherwise, other processes cannot open the object if they request read access. 
            /// If this flag is not specified, but the object has been opened for read access, the function fails.
            /// </summary>
            Read = 0x00000001,
            /// <summary>
            /// Enables subsequent open operations on an object to request write access. 
            /// Otherwise, other processes cannot open the object if they request write access. 
            /// If this flag is not specified, but the object has been opened for write access, the function fails.
            /// </summary>
            Write = 0x00000002,
            /// <summary>
            /// Enables subsequent open operations on an object to request delete access. 
            /// Otherwise, other processes cannot open the object if they request delete access.
            /// If this flag is not specified, but the object has been opened for delete access, the function fails.
            /// </summary>
            Delete = 0x00000004
        }

        public enum ECreationDisposition : uint
        {
            /// <summary>
            /// Creates a new file. The function fails if a specified file exists.
            /// </summary>
            New = 1,
            /// <summary>
            /// Creates a new file, always. 
            /// If a file exists, the function overwrites the file, clears the existing attributes, combines the specified file attributes, 
            /// and flags with FILE_ATTRIBUTE_ARCHIVE, but does not set the security descriptor that the SECURITY_ATTRIBUTES structure specifies.
            /// </summary>
            CreateAlways = 2,
            /// <summary>
            /// Opens a file. The function fails if the file does not exist. 
            /// </summary>
            OpenExisting = 3,
            /// <summary>
            /// Opens a file, always. 
            /// If a file does not exist, the function creates a file as if dwCreationDisposition is CREATE_NEW.
            /// </summary>
            OpenAlways = 4,
            /// <summary>
            /// Opens a file and truncates it so that its size is 0 (zero) bytes. The function fails if the file does not exist.
            /// The calling process must open the file with the GENERIC_WRITE access right. 
            /// </summary>
            TruncateExisting = 5
        }

        [Flags]
        public enum EFileAttributes : uint
        {
            Readonly = 0x00000001,
            Hidden = 0x00000002,
            System = 0x00000004,
            Directory = 0x00000010,
            Archive = 0x00000020,
            Device = 0x00000040,
            Normal = 0x00000080,
            Temporary = 0x00000100,
            SparseFile = 0x00000200,
            ReparsePoint = 0x00000400,
            Compressed = 0x00000800,
            Offline = 0x00001000,
            NotContentIndexed = 0x00002000,
            Encrypted = 0x00004000,
            Write_Through = 0x80000000,
            Overlapped = 0x40000000,
            NoBuffering = 0x20000000,
            RandomAccess = 0x10000000,
            SequentialScan = 0x08000000,
            DeleteOnClose = 0x04000000,
            BackupSemantics = 0x02000000,
            PosixSemantics = 0x01000000,
            OpenReparsePoint = 0x00200000,
            OpenNoRecall = 0x00100000,
            FirstPipeInstance = 0x00080000
        }


        [DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool IsWow64Process(
              [In] IntPtr hProcess,
              [Out, MarshalAs(UnmanagedType.Bool)] out bool wow64Process
              );
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern IntPtr GetCurrentProcess();
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top