diff --git a/DatabaseFile.cs b/DatabaseFile.cs index 89d0c48..dacce5d 100644 --- a/DatabaseFile.cs +++ b/DatabaseFile.cs @@ -180,7 +180,7 @@ public DatabaseFile (TaskScheduler scheduler, string filename) Tangles.Add(theTangle); } - yield return SymbolCache.CreateIndex( + yield return SymbolCache.CreateIndex( "ByFunction", IndexSymbolByFunction ).Bind(() => SymbolsByFunction); diff --git a/HeapRecording.cs b/HeapRecording.cs index 128fddd..73899da 100644 --- a/HeapRecording.cs +++ b/HeapRecording.cs @@ -31,6 +31,9 @@ namespace HeapProfiler { public class HeapRecording : IDisposable { + public const string DefaultSymbolPath = @"%windir%\symbols"; + public const string DefaultSymbolServers = @"http://msdl.microsoft.com/download/symbols"; + public const int SymbolResolveBatchSize = 1024; public static class SnapshotLoadState { @@ -262,6 +265,9 @@ string filename } }); + IDictionary environment = null; + yield return GetEnvironment().Bind(() => environment); + var psi = new ProcessStartInfo( Settings.UmdhPath, String.Format( "\"{0}\" -f:\"{1}\"", infile, outfile @@ -269,7 +275,9 @@ string filename ); using (var rp = Scheduler.Start( - Program.RunProcess(psi, ProcessPriorityClass.Idle), + Program.RunProcess( + psi, ProcessPriorityClass.Idle, environment + ), TaskExecutionPolicy.RunAsBackgroundTask )) yield return rp; @@ -947,6 +955,33 @@ where sgn.Key.Equals(item.key) return f; } + protected IEnumerator GetEnvironment () { + object[] prefs = null; + yield return Program.Preferences.Select( + new[] { "SymbolPath", "SymbolServers" } + ).Bind(() => prefs); + + var symbolPath = (prefs[0] as string) ?? ""; + var symbolServers = (prefs[1] as string) ?? ""; + + if (String.IsNullOrWhiteSpace(symbolPath)) + symbolPath = DefaultSymbolPath; + if (String.IsNullOrWhiteSpace(symbolServers)) + symbolServers = DefaultSymbolServers; + + var symbolSrv = String.Format( + "SRV*{0}*{1}", + Environment.ExpandEnvironmentVariables(symbolPath), + Environment.ExpandEnvironmentVariables(symbolServers) + ); + + var environment = new Dictionary { + { "_NT_SYMBOL_PATH", symbolSrv } + }; + + yield return new Result(environment); + } + protected IEnumerator CaptureSnapshotTask (string targetFilename) { var now = DateTime.Now; @@ -958,10 +993,13 @@ where sgn.Key.Equals(item.key) ) ); + IDictionary environment = null; + yield return GetEnvironment().Bind(() => environment); + TemporaryFiles.Add(targetFilename); using (Activities.AddItem("Capturing heap snapshot")) - yield return Program.RunProcess(psi); + yield return Program.RunProcess(psi, customEnvironment: environment); yield return Future.RunInThread( () => File.AppendAllText(targetFilename, mem.GetFileText()) @@ -987,13 +1025,18 @@ where sgn.Key.Equals(item.key) } else { filename = Path.GetTempFileName(); + IDictionary environment = null; + yield return GetEnvironment().Bind(() => environment); + var psi = new ProcessStartInfo( Settings.UmdhPath, String.Format( "\"{0}\" \"{1}\" -f:\"{2}\"", file1, file2, filename ) ); - var rp = Scheduler.Start(Program.RunProcess(psi), TaskExecutionPolicy.RunAsBackgroundTask); + var rp = Scheduler.Start(Program.RunProcess( + psi, customEnvironment: environment + ), TaskExecutionPolicy.RunAsBackgroundTask); using (Activities.AddItem("Generating heap diff")) using (rp) diff --git a/Program.cs b/Program.cs index 46ddf19..941e7ce 100644 --- a/Program.cs +++ b/Program.cs @@ -232,8 +232,13 @@ static class Program { ); } - public static IEnumerator RunProcess (ProcessStartInfo psi, ProcessPriorityClass? priority = null) { - var rtc = new RunToCompletion(RunProcessWithResult(psi, priority)); + public static IEnumerator RunProcess ( + ProcessStartInfo psi, ProcessPriorityClass? priority = null, + IEnumerable> customEnvironment = null + ) { + var rtc = new RunToCompletion(RunProcessWithResult( + psi, priority, customEnvironment + )); yield return rtc; if ((rtc.Result.StdOut ?? "").Trim().Length > 0) @@ -245,13 +250,20 @@ static class Program { throw new Exception(String.Format("Process exited with code {0}", rtc.Result.ExitCode)); } - public static IEnumerator RunProcessWithResult (ProcessStartInfo psi, ProcessPriorityClass? priority = null) { + public static IEnumerator RunProcessWithResult ( + ProcessStartInfo psi, ProcessPriorityClass? priority = null, + IEnumerable> customEnvironment = null + ) { psi.UseShellExecute = false; psi.CreateNoWindow = true; psi.RedirectStandardOutput = true; psi.RedirectStandardError = true; psi.WindowStyle = ProcessWindowStyle.Hidden; + if (customEnvironment != null) + foreach (var kvp in customEnvironment) + psi.EnvironmentVariables.Add(kvp.Key, kvp.Value); + var fProcess = StartProcess(psi); yield return fProcess;