diff --git a/trunk/CHANGELOG.txt b/trunk/CHANGELOG.txt
index c3114cf7a..cc26b3124 100644
--- a/trunk/CHANGELOG.txt
+++ b/trunk/CHANGELOG.txt
@@ -9,6 +9,7 @@ Process Hacker
* FIXED:
* #2880368 - "Highlight Option dialog does not show current colors"
* #2881084 - "System.ArgumentOutOfRangeException"
+ * #2881951 - "Invalid cursor handle."
* Fixed some crashes on 64-bit when viewing thread stacks
* Remaining network list bugs
diff --git a/trunk/ProcessHacker.Common/ProcessHacker.Common.csproj b/trunk/ProcessHacker.Common/ProcessHacker.Common.csproj
index 07409739f..66ee1cf98 100644
--- a/trunk/ProcessHacker.Common/ProcessHacker.Common.csproj
+++ b/trunk/ProcessHacker.Common/ProcessHacker.Common.csproj
@@ -83,6 +83,7 @@
+
diff --git a/trunk/ProcessHacker.Common/Settings/VolatileSettingsStore.cs b/trunk/ProcessHacker.Common/Settings/VolatileSettingsStore.cs
new file mode 100644
index 000000000..5ffb44f5e
--- /dev/null
+++ b/trunk/ProcessHacker.Common/Settings/VolatileSettingsStore.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace ProcessHacker.Common.Settings
+{
+ public sealed class VolatileSettingsStore : ISettingsStore
+ {
+ public void Flush()
+ {
+ // Nothing to flush.
+ }
+
+ public string GetValue(string name)
+ {
+ // No settings saved, return null.
+ return null;
+ }
+
+ public void Reset()
+ {
+ // Nothing to reset.
+ }
+
+ public void SetValue(string name, string value)
+ {
+ // Don't save anything.
+ }
+ }
+}
diff --git a/trunk/ProcessHacker/Components/ModuleList.Designer.cs b/trunk/ProcessHacker/Components/ModuleList.Designer.cs
index db9b5a93a..05a595408 100644
--- a/trunk/ProcessHacker/Components/ModuleList.Designer.cs
+++ b/trunk/ProcessHacker/Components/ModuleList.Designer.cs
@@ -19,12 +19,7 @@
}
_highlightingContext.Dispose();
-
- if (this.Provider != null)
- {
- this.Provider.Dispose();
- this.Provider = null;
- }
+ this.Provider = null;
base.Dispose(disposing);
}
diff --git a/trunk/ProcessHacker/Components/ProcessTree/ProcessTreeModel.cs b/trunk/ProcessHacker/Components/ProcessTree/ProcessTreeModel.cs
index 2adc0bccc..9fae0e82c 100644
--- a/trunk/ProcessHacker/Components/ProcessTree/ProcessTreeModel.cs
+++ b/trunk/ProcessHacker/Components/ProcessTree/ProcessTreeModel.cs
@@ -48,53 +48,50 @@ namespace ProcessHacker
public void Add(ProcessItem item)
{
- if (!_processes.ContainsKey(item.Pid))
+ ProcessNode itemNode = new ProcessNode(item);
+
+ // Add the process to the list of all processes.
+ _processes.Add(item.Pid, itemNode);
+
+ // Find the process' parent and add the process to it if we found it.
+ if (item.HasParent && _processes.ContainsKey(item.ParentPid))
{
- ProcessNode itemNode = new ProcessNode(item);
-
- // Add the process to the list of all processes.
- _processes.Add(item.Pid, itemNode);
+ ProcessNode parent = _processes[item.ParentPid];
- // Find the process' parent and add the process to it if we found it.
- if (item.HasParent && _processes.ContainsKey(item.ParentPid))
- {
- ProcessNode parent = _processes[item.ParentPid];
-
- parent.Children.Add(itemNode);
- itemNode.Parent = parent;
- }
- else
- {
- // The process doesn't have a parent, so add it to the root nodes.
- _roots.Add(itemNode);
- }
-
- itemNode.RefreshTreePath();
-
- // Find this process' children and fix them up.
-
- // We need to create a copy of the array because we may need
- // to modify the roots list.
- ProcessNode[] roots = _roots.ToArray();
-
- foreach (ProcessNode node in roots)
- {
- // Notice that we don't replace a node's parent if it
- // already has one. This is to break potential cyclic
- // references.
- if (node.Parent == null && node.ProcessItem.HasParent && node.PPid == item.Pid)
- {
- // Remove the node from the root list and add it to our
- // process' child list.
- _roots.Remove(node);
- itemNode.Children.Add(node);
- node.Parent = itemNode;
- node.RefreshTreePathRecursive();
- }
- }
-
- this.StructureChanged(this, new TreePathEventArgs(new TreePath()));
+ parent.Children.Add(itemNode);
+ itemNode.Parent = parent;
}
+ else
+ {
+ // The process doesn't have a parent, so add it to the root nodes.
+ _roots.Add(itemNode);
+ }
+
+ itemNode.RefreshTreePath();
+
+ // Find this process' children and fix them up.
+
+ // We need to create a copy of the array because we may need
+ // to modify the roots list.
+ ProcessNode[] roots = _roots.ToArray();
+
+ foreach (ProcessNode node in roots)
+ {
+ // Notice that we don't replace a node's parent if it
+ // already has one. This is to break potential cyclic
+ // references.
+ if (node.Parent == null && node.ProcessItem.HasParent && node.PPid == item.Pid)
+ {
+ // Remove the node from the root list and add it to our
+ // process' child list.
+ _roots.Remove(node);
+ itemNode.Children.Add(node);
+ node.Parent = itemNode;
+ node.RefreshTreePathRecursive();
+ }
+ }
+
+ this.StructureChanged(this, new TreePathEventArgs(new TreePath()));
}
public void Modify(ProcessItem oldItem, ProcessItem newItem)
diff --git a/trunk/ProcessHacker/Program/Settings.cs b/trunk/ProcessHacker/Program/Settings.cs
index 78fb6b9b3..c5ad9e4ee 100644
--- a/trunk/ProcessHacker/Program/Settings.cs
+++ b/trunk/ProcessHacker/Program/Settings.cs
@@ -11,8 +11,9 @@ namespace ProcessHacker
{
public class Settings : SettingsBase
{
- private static Settings _instance;
- private static XmlFileSettingsStore _store;
+ // Create instance, before the user creates a new store.
+ private static Settings _instance = new Settings();
+ private static ISettingsStore _store;
public static Settings Instance
{
@@ -20,6 +21,10 @@ namespace ProcessHacker
set { _instance = value; }
}
+ private Settings()
+ : base(_store = new VolatileSettingsStore())
+ { }
+
public Settings(string fileName)
: base(_store = new XmlFileSettingsStore(fileName))
{
@@ -28,7 +33,7 @@ namespace ProcessHacker
public string SettingsFileName
{
- get { return _store.FileName; }
+ get { return (_store as XmlFileSettingsStore).FileName; }
}
public override void Invalidate()
@@ -330,7 +335,7 @@ namespace ProcessHacker
set { this["DeletedServices"] = _deletedServices = value; }
}
- private int _elevationLevel;
+ private int _elevationLevel = 1;
[SettingDefault("1")]
public int ElevationLevel
{
@@ -468,7 +473,7 @@ namespace ProcessHacker
set { this["HideWhenMinimized"] = _hideWhenMinimized = value; }
}
- private int _highlightingDuration;
+ private int _highlightingDuration = 1000;
[SettingDefault("1000")]
public int HighlightingDuration
{
@@ -476,7 +481,7 @@ namespace ProcessHacker
set { this["HighlightingDuration"] = _highlightingDuration = value; }
}
- private int _iconMenuProcessCount;
+ private int _iconMenuProcessCount = 10;
[SettingDefault("10")]
public int IconMenuProcessCount
{
@@ -547,7 +552,7 @@ namespace ProcessHacker
set { this["LogWindowSize"] = value; }
}
- private int _maxSamples;
+ private int _maxSamples = 512;
[SettingDefault("512")]
public int MaxSamples
{
@@ -711,7 +716,7 @@ namespace ProcessHacker
set { this["PlotterMemoryWSColor"] = _plotterMemoryWSColor = value; }
}
- private int _plotterStep;
+ private int _plotterStep = 2;
[SettingDefault("2")]
public int PlotterStep
{
@@ -768,7 +773,7 @@ namespace ProcessHacker
set { this["PromptBoxText"] = value; }
}
- private int _refreshInterval;
+ private int _refreshInterval = 1000;
[SettingDefault("1000")]
public int RefreshInterval
{
@@ -839,7 +844,7 @@ namespace ProcessHacker
set { this["ServiceMiniListColumns"] = value; }
}
- private bool _showAccountDomains;
+ private bool _showAccountDomains = false;
[SettingDefault("False")]
public bool ShowAccountDomains
{
@@ -942,7 +947,7 @@ namespace ProcessHacker
set { this["ToolStripDisplayStyle"] = value; }
}
- private int _unitSpecifier;
+ private int _unitSpecifier = 6;
[SettingDefault("6")]
public int UnitSpecifier
{
@@ -1078,7 +1083,7 @@ namespace ProcessHacker
set { this["VerifySignatures"] = _verifySignatures = value; }
}
- private bool _warnDangerous;
+ private bool _warnDangerous = true;
[SettingDefault("True")]
public bool WarnDangerous
{
diff --git a/trunk/ProcessHacker/Providers/HandleProvider.cs b/trunk/ProcessHacker/Providers/HandleProvider.cs
index 8a013f8ab..f2372dbb2 100644
--- a/trunk/ProcessHacker/Providers/HandleProvider.cs
+++ b/trunk/ProcessHacker/Providers/HandleProvider.cs
@@ -71,6 +71,9 @@ namespace ProcessHacker
private void UpdateOnce()
{
+ if (_processHandle == null)
+ return;
+
var handles = Windows.GetHandles();
var processHandles = new Dictionary();
var newdictionary = new Dictionary(this.Dictionary);
diff --git a/trunk/ProcessHacker/Providers/MemoryProvider.cs b/trunk/ProcessHacker/Providers/MemoryProvider.cs
index f05b32bcf..7dc505a51 100644
--- a/trunk/ProcessHacker/Providers/MemoryProvider.cs
+++ b/trunk/ProcessHacker/Providers/MemoryProvider.cs
@@ -71,6 +71,9 @@ namespace ProcessHacker
private void UpdateOnce()
{
+ if (_processHandle == null)
+ return;
+
var modules = new Dictionary();
try
diff --git a/trunk/ProcessHacker/Providers/ServiceProvider.cs b/trunk/ProcessHacker/Providers/ServiceProvider.cs
index 0da3c5a22..037672ffd 100644
--- a/trunk/ProcessHacker/Providers/ServiceProvider.cs
+++ b/trunk/ProcessHacker/Providers/ServiceProvider.cs
@@ -67,6 +67,8 @@ namespace ProcessHacker
{
var newdictionary = Windows.GetServices();
+ List toRemove = null;
+
// check for removed services
foreach (string s in Dictionary.Keys)
{
@@ -75,10 +77,17 @@ namespace ProcessHacker
ServiceItem service = Dictionary[s];
this.OnDictionaryRemoved(service);
- Dictionary.Remove(s);
+
+ if (toRemove == null)
+ toRemove = new List();
+
+ toRemove.Add(s);
}
}
+ foreach (var serviceName in toRemove)
+ Dictionary.Remove(serviceName);
+
// check for new services
foreach (string s in newdictionary.Keys)
{