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.
///