diff --git a/trunk/CHANGELOG.txt b/trunk/CHANGELOG.txt index 9e8a6db16..18579ed97 100644 --- a/trunk/CHANGELOG.txt +++ b/trunk/CHANGELOG.txt @@ -3,6 +3,7 @@ Process Hacker 1.3.5.5 * NEW: * Modules tab shows mapped files + * "Reduce Working Set" function * FIXED: 1.3.5.0 diff --git a/trunk/ProcessHacker/Forms/HackerWindow.Designer.cs b/trunk/ProcessHacker/Forms/HackerWindow.Designer.cs index d6382f25f..2f32cb19f 100644 --- a/trunk/ProcessHacker/Forms/HackerWindow.Designer.cs +++ b/trunk/ProcessHacker/Forms/HackerWindow.Designer.cs @@ -37,6 +37,7 @@ this.suspendMenuItem = new System.Windows.Forms.MenuItem(); this.resumeMenuItem = new System.Windows.Forms.MenuItem(); this.restartProcessMenuItem = new System.Windows.Forms.MenuItem(); + this.reduceWorkingSetProcessMenuItem = new System.Windows.Forms.MenuItem(); this.menuItem5 = new System.Windows.Forms.MenuItem(); this.affinityProcessMenuItem = new System.Windows.Forms.MenuItem(); this.setTokenProcessMenuItem = new System.Windows.Forms.MenuItem(); @@ -168,6 +169,7 @@ this.suspendMenuItem, this.resumeMenuItem, this.restartProcessMenuItem, + this.reduceWorkingSetProcessMenuItem, this.menuItem5, this.affinityProcessMenuItem, this.setTokenProcessMenuItem, @@ -210,33 +212,39 @@ this.restartProcessMenuItem.Text = "Restart"; this.restartProcessMenuItem.Click += new System.EventHandler(this.restartProcessMenuItem_Click); // + // reduceWorkingSetProcessMenuItem + // + this.reduceWorkingSetProcessMenuItem.Index = 4; + this.reduceWorkingSetProcessMenuItem.Text = "Reduce Working Set"; + this.reduceWorkingSetProcessMenuItem.Click += new System.EventHandler(this.reduceWorkingSetProcessMenuItem_Click); + // // menuItem5 // - this.menuItem5.Index = 4; + this.menuItem5.Index = 5; this.menuItem5.Text = "-"; // // affinityProcessMenuItem // - this.affinityProcessMenuItem.Index = 5; + this.affinityProcessMenuItem.Index = 6; this.affinityProcessMenuItem.Text = "Affinity..."; this.affinityProcessMenuItem.Click += new System.EventHandler(this.affinityProcessMenuItem_Click); // // setTokenProcessMenuItem // - this.setTokenProcessMenuItem.Index = 6; + this.setTokenProcessMenuItem.Index = 7; this.setTokenProcessMenuItem.Text = "Set Token..."; this.setTokenProcessMenuItem.Click += new System.EventHandler(this.setTokenProcessMenuItem_Click); // // terminatorProcessMenuItem // - this.terminatorProcessMenuItem.Index = 7; + this.terminatorProcessMenuItem.Index = 8; this.terminatorProcessMenuItem.Text = "Terminator..."; this.terminatorProcessMenuItem.Click += new System.EventHandler(this.terminatorProcessMenuItem_Click); // // priorityMenuItem // this.vistaMenu.SetImage(this.priorityMenuItem, global::ProcessHacker.Properties.Resources.control_equalizer_blue); - this.priorityMenuItem.Index = 8; + this.priorityMenuItem.Index = 9; this.priorityMenuItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { this.realTimeMenuItem, this.highMenuItem, @@ -290,7 +298,7 @@ // // runAsProcessMenuItem // - this.runAsProcessMenuItem.Index = 9; + this.runAsProcessMenuItem.Index = 10; this.runAsProcessMenuItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { this.launchAsUserProcessMenuItem, this.launchAsThisUserProcessMenuItem}); @@ -312,36 +320,36 @@ // this.propertiesProcessMenuItem.DefaultItem = true; this.vistaMenu.SetImage(this.propertiesProcessMenuItem, global::ProcessHacker.Properties.Resources.application_form_magnify); - this.propertiesProcessMenuItem.Index = 10; + this.propertiesProcessMenuItem.Index = 11; this.propertiesProcessMenuItem.Text = "&Properties..."; this.propertiesProcessMenuItem.Click += new System.EventHandler(this.inspectProcessMenuItem_Click); // // menuItem7 // - this.menuItem7.Index = 11; + this.menuItem7.Index = 12; this.menuItem7.Text = "-"; // // searchProcessMenuItem // - this.searchProcessMenuItem.Index = 12; + this.searchProcessMenuItem.Index = 13; this.searchProcessMenuItem.Text = "&Search Online..."; this.searchProcessMenuItem.Click += new System.EventHandler(this.searchProcessMenuItem_Click); // // reanalyzeProcessMenuItem // - this.reanalyzeProcessMenuItem.Index = 13; + this.reanalyzeProcessMenuItem.Index = 14; this.reanalyzeProcessMenuItem.Text = "Re-analyze"; this.reanalyzeProcessMenuItem.Click += new System.EventHandler(this.reanalyzeProcessMenuItem_Click); // // copyProcessMenuItem // this.vistaMenu.SetImage(this.copyProcessMenuItem, global::ProcessHacker.Properties.Resources.page_copy); - this.copyProcessMenuItem.Index = 14; + this.copyProcessMenuItem.Index = 15; this.copyProcessMenuItem.Text = "&Copy"; // // selectAllProcessMenuItem // - this.selectAllProcessMenuItem.Index = 15; + this.selectAllProcessMenuItem.Index = 16; this.selectAllProcessMenuItem.Text = "Select &All"; this.selectAllProcessMenuItem.Click += new System.EventHandler(this.selectAllProcessMenuItem_Click); // @@ -1077,6 +1085,7 @@ private System.Windows.Forms.MenuItem freeMemoryMenuItem; private System.Windows.Forms.MenuItem menuItem1; private System.Windows.Forms.MenuItem reanalyzeProcessMenuItem; + private System.Windows.Forms.MenuItem reduceWorkingSetProcessMenuItem; } } diff --git a/trunk/ProcessHacker/Forms/HackerWindow.cs b/trunk/ProcessHacker/Forms/HackerWindow.cs index 0fd0e0ad2..057cb3319 100644 --- a/trunk/ProcessHacker/Forms/HackerWindow.cs +++ b/trunk/ProcessHacker/Forms/HackerWindow.cs @@ -915,6 +915,20 @@ namespace ProcessHacker } } + private void reduceWorkingSetProcessMenuItem_Click(object sender, EventArgs e) + { + try + { + using (var phandle = new Win32.ProcessHandle(processSelectedPID, + Win32.PROCESS_RIGHTS.PROCESS_ALL_ACCESS)) + phandle.EmptyWorkingSet(); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "Process Hacker", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + private void inspectProcessMenuItem_Click(object sender, EventArgs e) { // user hasn't got any processes selected diff --git a/trunk/ProcessHacker/Win32/API/Functions.cs b/trunk/ProcessHacker/Win32/API/Functions.cs index 0a21b4e82..cda43385b 100644 --- a/trunk/ProcessHacker/Win32/API/Functions.cs +++ b/trunk/ProcessHacker/Win32/API/Functions.cs @@ -302,6 +302,9 @@ namespace ProcessHacker #region Processes + [DllImport("psapi.dll", SetLastError = true)] + public static extern bool EmptyWorkingSet(int ProcessHandle); + [DllImport("psapi.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern int GetMappedFileName( int ProcessHandle, diff --git a/trunk/ProcessHacker/Win32/Handles/ProcessHandle.cs b/trunk/ProcessHacker/Win32/Handles/ProcessHandle.cs index 0f0fd272f..bfd955f12 100644 --- a/trunk/ProcessHacker/Win32/Handles/ProcessHandle.cs +++ b/trunk/ProcessHacker/Win32/Handles/ProcessHandle.cs @@ -218,6 +218,16 @@ namespace ProcessHacker return new ThreadHandle(this.CreateThread(startAddress, parameter)); } + /// + /// Removes as many pages as possible from the process' working set. This requires the + /// PROCESS_QUERY_INFORMATION and PROCESS_SET_INFORMATION permissions. + /// + public void EmptyWorkingSet() + { + if (!Win32.EmptyWorkingSet(this)) + ThrowLastWin32Error(); + } + /// /// Frees a memory region in the process' virtual memory. ///