[
  {
    "path": ".gitattributes",
    "content": "###############################################################################\n# Set default behavior to automatically normalize line endings.\n###############################################################################\n* text=auto\n\n###############################################################################\n# Set default behavior for command prompt diff.\n#\n# This is need for earlier builds of msysgit that does not have it on by\n# default for csharp files.\n# Note: This is only used by command line\n###############################################################################\n#*.cs     diff=csharp\n\n###############################################################################\n# Set the merge driver for project and solution files\n#\n# Merging from the command prompt will add diff markers to the files if there\n# are conflicts (Merging from VS is not affected by the settings below, in VS\n# the diff markers are never inserted). Diff markers may cause the following \n# file extensions to fail to load in VS. An alternative would be to treat\n# these files as binary and thus will always conflict and require user\n# intervention with every merge. To do so, just uncomment the entries below\n###############################################################################\n#*.sln       merge=binary\n#*.csproj    merge=binary\n#*.vbproj    merge=binary\n#*.vcxproj   merge=binary\n#*.vcproj    merge=binary\n#*.dbproj    merge=binary\n#*.fsproj    merge=binary\n#*.lsproj    merge=binary\n#*.wixproj   merge=binary\n#*.modelproj merge=binary\n#*.sqlproj   merge=binary\n#*.wwaproj   merge=binary\n\n###############################################################################\n# behavior for image files\n#\n# image files are treated as binary by default.\n###############################################################################\n#*.jpg   binary\n#*.png   binary\n#*.gif   binary\n\n###############################################################################\n# diff behavior for common document formats\n# \n# Convert binary document formats to text before diffing them. This feature\n# is only available from the command line. Turn it on by uncommenting the \n# entries below.\n###############################################################################\n#*.doc   diff=astextplain\n#*.DOC   diff=astextplain\n#*.docx  diff=astextplain\n#*.DOCX  diff=astextplain\n#*.dot   diff=astextplain\n#*.DOT   diff=astextplain\n#*.pdf   diff=astextplain\n#*.PDF   diff=astextplain\n#*.rtf   diff=astextplain\n#*.RTF   diff=astextplain\n"
  },
  {
    "path": ".gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n## TODO: Comment the next line if you want to checkin your\n## web deploy settings but do note that will include unencrypted\n## passwords\n#*.pubxml\n\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Windows Azure Build Output\ncsx/\n*.build.csdef\n\n# Windows Store app package directory\nAppPackages/\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n[Ss]tyle[Cc]op.*\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# LightSwitch generated files\nGeneratedArtifacts/\n_Pvt_Extensions/\nModelManifest.xml\n"
  },
  {
    "path": ".nuget/NuGet.Config",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n  <solution>\n    <add key=\"disableSourceControlIntegration\" value=\"true\" />\n  </solution>\n</configuration>"
  },
  {
    "path": ".nuget/NuGet.targets",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n    <PropertyGroup>\n        <SolutionDir Condition=\"$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'\">$(MSBuildProjectDirectory)\\..\\</SolutionDir>\n\n        <!-- Enable the restore command to run before builds -->\n        <RestorePackages Condition=\"  '$(RestorePackages)' == '' \">false</RestorePackages>\n\n        <!-- Property that enables building a package from a project -->\n        <BuildPackage Condition=\" '$(BuildPackage)' == '' \">false</BuildPackage>\n\n        <!-- Determines if package restore consent is required to restore packages -->\n        <RequireRestoreConsent Condition=\" '$(RequireRestoreConsent)' != 'false' \">true</RequireRestoreConsent>\n\n        <!-- Download NuGet.exe if it does not already exist -->\n        <DownloadNuGetExe Condition=\" '$(DownloadNuGetExe)' == '' \">false</DownloadNuGetExe>\n    </PropertyGroup>\n\n    <ItemGroup Condition=\" '$(PackageSources)' == '' \">\n        <!-- Package sources used to restore packages. By default, registered sources under %APPDATA%\\NuGet\\NuGet.Config will be used -->\n        <!-- The official NuGet package source (https://www.nuget.org/api/v2/) will be excluded if package sources are specified and it does not appear in the list -->\n        <!--\n            <PackageSource Include=\"https://www.nuget.org/api/v2/\" />\n            <PackageSource Include=\"https://my-nuget-source/nuget/\" />\n        -->\n    </ItemGroup>\n\n    <PropertyGroup Condition=\" '$(OS)' == 'Windows_NT'\">\n        <!-- Windows specific commands -->\n        <NuGetToolsPath>$([System.IO.Path]::Combine($(SolutionDir), \".nuget\"))</NuGetToolsPath>\n    </PropertyGroup>\n\n    <PropertyGroup Condition=\" '$(OS)' != 'Windows_NT'\">\n        <!-- We need to launch nuget.exe with the mono command if we're not on windows -->\n        <NuGetToolsPath>$(SolutionDir).nuget</NuGetToolsPath>\n    </PropertyGroup>\n\n    <PropertyGroup>\n        <PackagesProjectConfig Condition=\" '$(OS)' == 'Windows_NT'\">$(MSBuildProjectDirectory)\\packages.$(MSBuildProjectName.Replace(' ', '_')).config</PackagesProjectConfig>\n        <PackagesProjectConfig Condition=\" '$(OS)' != 'Windows_NT'\">$(MSBuildProjectDirectory)\\packages.$(MSBuildProjectName).config</PackagesProjectConfig>\n    </PropertyGroup>\n\n    <PropertyGroup>\n      <PackagesConfig Condition=\"Exists('$(MSBuildProjectDirectory)\\packages.config')\">$(MSBuildProjectDirectory)\\packages.config</PackagesConfig>\n      <PackagesConfig Condition=\"Exists('$(PackagesProjectConfig)')\">$(PackagesProjectConfig)</PackagesConfig>\n    </PropertyGroup>\n    \n    <PropertyGroup>\n        <!-- NuGet command -->\n        <NuGetExePath Condition=\" '$(NuGetExePath)' == '' \">$(NuGetToolsPath)\\NuGet.exe</NuGetExePath>\n        <PackageSources Condition=\" $(PackageSources) == '' \">@(PackageSource)</PackageSources>\n\n        <NuGetCommand Condition=\" '$(OS)' == 'Windows_NT'\">\"$(NuGetExePath)\"</NuGetCommand>\n        <NuGetCommand Condition=\" '$(OS)' != 'Windows_NT' \">mono --runtime=v4.0.30319 \"$(NuGetExePath)\"</NuGetCommand>\n\n        <PackageOutputDir Condition=\"$(PackageOutputDir) == ''\">$(TargetDir.Trim('\\\\'))</PackageOutputDir>\n\n        <RequireConsentSwitch Condition=\" $(RequireRestoreConsent) == 'true' \">-RequireConsent</RequireConsentSwitch>\n        <NonInteractiveSwitch Condition=\" '$(VisualStudioVersion)' != '' AND '$(OS)' == 'Windows_NT' \">-NonInteractive</NonInteractiveSwitch>\n\n        <PaddedSolutionDir Condition=\" '$(OS)' == 'Windows_NT'\">\"$(SolutionDir) \"</PaddedSolutionDir>\n        <PaddedSolutionDir Condition=\" '$(OS)' != 'Windows_NT' \">\"$(SolutionDir)\"</PaddedSolutionDir>\n\n        <!-- Commands -->\n        <RestoreCommand>$(NuGetCommand) install \"$(PackagesConfig)\" -source \"$(PackageSources)\"  $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir)</RestoreCommand>\n        <BuildCommand>$(NuGetCommand) pack \"$(ProjectPath)\" -Properties \"Configuration=$(Configuration);Platform=$(Platform)\" $(NonInteractiveSwitch) -OutputDirectory \"$(PackageOutputDir)\" -symbols</BuildCommand>\n\n        <!-- We need to ensure packages are restored prior to assembly resolve -->\n        <BuildDependsOn Condition=\"$(RestorePackages) == 'true'\">\n            RestorePackages;\n            $(BuildDependsOn);\n        </BuildDependsOn>\n\n        <!-- Make the build depend on restore packages -->\n        <BuildDependsOn Condition=\"$(BuildPackage) == 'true'\">\n            $(BuildDependsOn);\n            BuildPackage;\n        </BuildDependsOn>\n    </PropertyGroup>\n\n    <Target Name=\"CheckPrerequisites\">\n        <!-- Raise an error if we're unable to locate nuget.exe  -->\n        <Error Condition=\"'$(DownloadNuGetExe)' != 'true' AND !Exists('$(NuGetExePath)')\" Text=\"Unable to locate '$(NuGetExePath)'\" />\n        <!--\n        Take advantage of MsBuild's build dependency tracking to make sure that we only ever download nuget.exe once.\n        This effectively acts as a lock that makes sure that the download operation will only happen once and all\n        parallel builds will have to wait for it to complete.\n        -->\n        <MsBuild Targets=\"_DownloadNuGet\" Projects=\"$(MSBuildThisFileFullPath)\" Properties=\"Configuration=NOT_IMPORTANT;DownloadNuGetExe=$(DownloadNuGetExe)\" />\n    </Target>\n\n    <Target Name=\"_DownloadNuGet\">\n        <DownloadNuGet OutputFilename=\"$(NuGetExePath)\" Condition=\" '$(DownloadNuGetExe)' == 'true' AND !Exists('$(NuGetExePath)')\" />\n    </Target>\n\n    <Target Name=\"RestorePackages\" DependsOnTargets=\"CheckPrerequisites\">        \n        <Exec Command=\"$(RestoreCommand)\"\n              Condition=\"'$(OS)' != 'Windows_NT' And Exists('$(PackagesConfig)')\" />\n\n        <Exec Command=\"$(RestoreCommand)\"\n              LogStandardErrorAsError=\"true\"\n              Condition=\"'$(OS)' == 'Windows_NT' And Exists('$(PackagesConfig)')\" />\n    </Target>\n\n    <Target Name=\"BuildPackage\" DependsOnTargets=\"CheckPrerequisites\">\n        <Exec Command=\"$(BuildCommand)\"\n              Condition=\" '$(OS)' != 'Windows_NT' \" />\n\n        <Exec Command=\"$(BuildCommand)\"\n              LogStandardErrorAsError=\"true\"\n              Condition=\" '$(OS)' == 'Windows_NT' \" />\n    </Target>\n\n    <UsingTask TaskName=\"DownloadNuGet\" TaskFactory=\"CodeTaskFactory\" AssemblyFile=\"$(MSBuildToolsPath)\\Microsoft.Build.Tasks.v4.0.dll\">\n        <ParameterGroup>\n            <OutputFilename ParameterType=\"System.String\" Required=\"true\" />\n        </ParameterGroup>\n        <Task>\n            <Reference Include=\"System.Core\" />\n            <Using Namespace=\"System\" />\n            <Using Namespace=\"System.IO\" />\n            <Using Namespace=\"System.Net\" />\n            <Using Namespace=\"Microsoft.Build.Framework\" />\n            <Using Namespace=\"Microsoft.Build.Utilities\" />\n            <Code Type=\"Fragment\" Language=\"cs\">\n                <![CDATA[\n                try {\n                    OutputFilename = Path.GetFullPath(OutputFilename);\n\n                    Log.LogMessage(\"Downloading latest version of NuGet.exe...\");\n                    WebClient webClient = new WebClient();\n                    webClient.DownloadFile(\"https://www.nuget.org/nuget.exe\", OutputFilename);\n\n                    return true;\n                }\n                catch (Exception ex) {\n                    Log.LogErrorFromException(ex);\n                    return false;\n                }\n            ]]>\n            </Code>\n        </Task>\n    </UsingTask>\n</Project>\n"
  },
  {
    "path": "DumpWriter/DumpReaderLogger.cs",
    "content": "﻿using Microsoft.Diagnostics.Runtime;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace DumpWriter\n{\n    class DumpReaderLogger : IDataReader\n    {\n        const int PAGE_SIZE = 4096;\n        private IDataReader _impl;\n        private Dictionary<ulong, ulong> _ranges = new Dictionary<ulong, ulong>();\n\n        public DumpReaderLogger(IDataReader impl)\n        {\n            _impl = impl;\n\n            // TODO Think about whether it's worth the time to eliminate overlaps, e.g.\n            // reading from 0x2000 to 0x4000 and then reading from 0x1000 to 0x3000 could\n            // be joined into a single 0x1000-0x3000 range. In practice, not sure there will\n            // be many overlaps like that.\n        }\n\n        public IDictionary<ulong, ulong> Ranges { get { return _ranges; } }\n\n        private void AddRange(ulong start, ulong end)\n        {\n            // Round to start of page\n            start -= start % PAGE_SIZE;\n\n            // Round to end of page\n            if (end % PAGE_SIZE != 0)\n                end += PAGE_SIZE - (end % PAGE_SIZE);\n\n            ulong prevEnd;\n            if (_ranges.TryGetValue(start, out prevEnd))\n                _ranges[start] = Math.Max(end, prevEnd);\n            else\n                _ranges.Add(start, end);\n        }\n\n        public bool ReadMemory(ulong address, IntPtr buffer, int bytesRequested, out int bytesRead)\n        {\n            bool success = _impl.ReadMemory(address, buffer, bytesRequested, out bytesRead);\n            if (success)\n            {\n                AddRange(address, address + (ulong)bytesRead);\n            }\n            return success;\n        }\n\n        public bool ReadMemory(ulong address, byte[] buffer, int bytesRequested, out int bytesRead)\n        {\n            bool success = _impl.ReadMemory(address, buffer, bytesRequested, out bytesRead);\n            if (success)\n            {\n                AddRange(address, address + (ulong)bytesRead);\n            }\n            return success;\n        }\n\n        #region Boring\n\n        public bool IsMinidump\n        {\n            get\n            {\n                return _impl.IsMinidump;\n            }\n        }\n\n        public void Close()\n        {\n            _impl.Close();\n        }\n\n        public IEnumerable<uint> EnumerateAllThreads()\n        {\n            return _impl.EnumerateAllThreads();\n        }\n\n        public IList<ModuleInfo> EnumerateModules()\n        {\n            return _impl.EnumerateModules();\n        }\n\n        public void Flush()\n        {\n            _impl.Flush();\n        }\n\n        public Architecture GetArchitecture()\n        {\n            return _impl.GetArchitecture();\n        }\n\n        public uint GetPointerSize()\n        {\n            return _impl.GetPointerSize();\n        }\n\n        public bool GetThreadContext(uint threadID, uint contextFlags, uint contextSize, byte[] context)\n        {\n            return _impl.GetThreadContext(threadID, contextFlags, contextSize, context);\n        }\n\n        public bool GetThreadContext(uint threadID, uint contextFlags, uint contextSize, IntPtr context)\n        {\n            return _impl.GetThreadContext(threadID, contextFlags, contextSize, context);\n        }\n\n        public ulong GetThreadTeb(uint thread)\n        {\n            return _impl.GetThreadTeb(thread);\n        }\n\n        public void GetVersionInfo(ulong baseAddress, out VersionInfo version)\n        {\n            _impl.GetVersionInfo(baseAddress, out version);\n        }\n\n        public uint ReadDwordUnsafe(ulong addr)\n        {\n            return _impl.ReadDwordUnsafe(addr);\n        }\n\n        public ulong ReadPointerUnsafe(ulong addr)\n        {\n            return _impl.ReadPointerUnsafe(addr);\n        }\n\n        public bool VirtualQuery(ulong addr, out VirtualQueryData vq)\n        {\n            return _impl.VirtualQuery(addr, out vq);\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "DumpWriter/DumpWriter.cs",
    "content": "﻿using Microsoft.Diagnostics.Runtime;\nusing System;\nusing System.Collections.Concurrent;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.IO;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Threading.Tasks;\n\nnamespace DumpWriter\n{\n    public enum DumpType\n    {\n        Minimal,\n        MinimalWithFullCLRHeap,\n        FullMemory,\n        FullMemoryExcludingSafeRegions\n    }\n\n    public class DumpWriter\n    {\n        struct DumpedSegment\n        {\n            public ulong Offset;\n            public byte[] Data;\n        }\n\n        private TextWriter _logger;\n        private C5.TreeDictionary<ulong, ulong> _majorClrRegions = new C5.TreeDictionary<ulong, ulong>();\n        private C5.TreeDictionary<ulong, ulong> _otherClrRegions = new C5.TreeDictionary<ulong, ulong>();\n        private int _pid;\n        private DumpType _dumpType;\n        private IEnumerator<C5.KeyValuePair<ulong, ulong>> _regionEnumerator = null;\n        private BlockingCollection<DumpedSegment> _dumpedSegments = new BlockingCollection<DumpedSegment>();\n        private FileStream _dumpFileStream;\n        private Task _segmentSpillingTask;\n        private bool _spillSegmentsAsynchronously;\n        private bool _needMemoryCallbacks;\n\n        private IEnumerable<C5.KeyValuePair<ulong, ulong>> EnumerateAllNeededRegions()\n        {\n            foreach (var region in _majorClrRegions)\n                yield return region;\n            foreach (var region in _otherClrRegions)\n                yield return region;\n        }\n\n        private void DetermineNeededRegions()\n        {\n            if (_dumpType == DumpType.Minimal)\n                return;\n\n            var readerType = typeof(DataTarget).Assembly.GetType(\"Microsoft.Diagnostics.Runtime.LiveDataReader\");\n            var reader = (IDataReader)Activator.CreateInstance(readerType, _pid, false);\n            var readerLogger = new DumpReaderLogger(reader);\n\n            using (var target = DataTarget.CreateFromDataReader(readerLogger))\n            {\n                foreach (var clrVersion in target.ClrVersions)\n                {\n                    var runtime = clrVersion.CreateRuntime();\n\n                    AddCLRRegions(runtime);\n\n                    TouchOtherRegions(readerLogger, runtime);\n\n                    _logger.WriteLine(\"{0} ranges requested by the DAC, total size {1:N0}\",\n                        _otherClrRegions.Count,\n                        _otherClrRegions.Sum(r => (long)(r.Key - r.Value))\n                        );\n                    _logger.WriteLine(\"{0} CLR regions, total size {1:N0}\",\n                        _majorClrRegions.Count,\n                        _majorClrRegions.Sum(r => (long)(r.Key - r.Value))\n                        );\n                }\n            }\n        }\n\n        private void TouchOtherRegions(DumpReaderLogger readerLogger, ClrRuntime runtime)\n        {\n            // Touch all threads, stacks, frames\n            foreach (var t in runtime.Threads)\n            {\n                foreach (var f in t.StackTrace)\n                {\n                    try { var ip = f.InstructionPointer; }\n                    catch (Exception) { }\n                }\n            }\n\n            // Touch all modules\n            runtime.Modules.Count();\n\n            // Touch all heap regions, roots, types\n            var heap = runtime.Heap;\n            heap.EnumerateRoots(enumerateStatics: false).Count();\n            heap.EnumerateTypes().Count();\n\n            // TODO Check if it's faster to construct sorted inside ReaderWrapper\n            foreach (var kvp in readerLogger.Ranges)\n                _otherClrRegions.Add(kvp.Key, kvp.Value);\n        }\n\n        private void AddCLRRegions(ClrRuntime runtime)\n        {\n            foreach (var region in runtime.EnumerateMemoryRegions())\n            {\n                // We don't need reserved memory in our dump\n                if (region.Type == ClrMemoryRegionType.ReservedGCSegment)\n                    continue;\n\n                ulong address = region.Address;\n                ulong endAddress = region.Address + region.Size;\n                ulong existingEndAddress;\n                if (_majorClrRegions.Find(ref address, out existingEndAddress))\n                {\n                    _majorClrRegions.Update(region.Address, Math.Max(existingEndAddress, endAddress));\n                }\n                else\n                {\n                    _majorClrRegions.Add(region.Address, endAddress);\n                }\n            }\n        }\n\n        private static bool HasIntervalThatIsSubsetOfInterval(\n            C5.TreeDictionary<ulong, ulong> regions,\n            ulong regionStart,\n            ulong regionEnd)\n        {\n            // Is there any region in whose [start, end] interval is a sub-interval of\n            // [regionStart, regionEnd]?\n            // TryWeakSuccessor gives us the first region whose start is >= regionStart,\n            // but there could be more regions with start >= regionStart and end <= regionEnd.\n            // Need to traverse successors until start > regionEnd, making containment impossible.\n            C5.KeyValuePair<ulong, ulong> range;\n            if (regions.TryWeakSuccessor(regionStart, out range))\n            {\n                if (range.Key >= regionStart && range.Value <= regionEnd)\n                    return true;\n            }\n            while (regions.TrySuccessor(range.Key, out range))\n            {\n                if (range.Key > regionEnd)\n                    break;\n\n                if (range.Key >= regionStart && range.Value <= regionEnd)\n                    return true;\n            }\n            return false;\n        }\n\n        private bool IsNeededRegion(ulong regionStart, ulong regionEnd)\n        {\n            return\n                HasIntervalThatIsSubsetOfInterval(_majorClrRegions, regionStart, regionEnd) ||\n                HasIntervalThatIsSubsetOfInterval(_otherClrRegions, regionStart, regionEnd);\n        }\n\n        private bool CallbackRoutine(\n            IntPtr CallbackParam,\n            ref MINIDUMP_CALLBACK_INPUT CallbackInput,\n            ref MINIDUMP_CALLBACK_OUTPUT CallbackOutput\n            )\n        {\n            _logger.WriteLine(\"Callback type: \" + CallbackInput.CallbackType);\n\n            if ((int)CallbackInput.CallbackType < 0 ||\n                (int)CallbackInput.CallbackType > (int)MINIDUMP_CALLBACK_TYPE.SecondaryFlagsCallback)\n            {\n                // We don't know what these numbers mean. They aren't in the SDK headers,\n                // but we are getting them when the dump generation begins (16, 17).\n                _logger.WriteLine(\"\\tThis callback type is not recognized\");\n                return false;\n            }\n\n            switch (CallbackInput.CallbackType)\n            {\n                // I/O callbacks\n                case MINIDUMP_CALLBACK_TYPE.IoWriteAllCallback:\n                    _logger.WriteLine(\"\\tIOWriteAll: offset = {0:x8} buffer = {1:x16} size = {2:x8}\",\n                        CallbackInput.Io.Offset, CallbackInput.Io.Buffer, CallbackInput.Io.BufferBytes);\n                    var segment = new DumpedSegment {\n                        Offset = CallbackInput.Io.Offset,\n                        Data = new byte[CallbackInput.Io.BufferBytes]\n                    };\n                    Marshal.Copy(CallbackInput.Io.Buffer, segment.Data, 0, segment.Data.Length);\n                    _dumpedSegments.Add(segment);\n                    CallbackOutput.Status = 0;\n                    break;\n                case MINIDUMP_CALLBACK_TYPE.IoFinishCallback:\n                    _logger.WriteLine(\"\\tIOFinish\");\n                    _dumpedSegments.CompleteAdding();\n                    CallbackOutput.Status = 0;\n                    break;\n                case MINIDUMP_CALLBACK_TYPE.IoStartCallback:\n                    _logger.WriteLine(\"\\tIOStart: handle = {0}\", CallbackInput.Io.Handle);\n                    if (_spillSegmentsAsynchronously)\n                    {\n                        // Providing S_FALSE (1) as the status here instructs dbghelp to send all\n                        // I/O through the callback (IoWriteAllCallback).\n                        CallbackOutput.Status = 1;\n                        _segmentSpillingTask = Task.Factory.StartNew(SpillDumpSegmentsToDisk, TaskCreationOptions.LongRunning);\n                    }\n                    else\n                    {\n                        CallbackOutput.Status = 0;\n                    }\n                    if (_needMemoryCallbacks)\n                    {\n                        DetermineNeededRegions();\n                    }\n                    break;\n\n                // Cancel callback\n                case MINIDUMP_CALLBACK_TYPE.CancelCallback:\n                    _logger.WriteLine(\"\\tCancel callback invoked, asking for no further cancel checks\");\n                    CallbackOutput.Cancel.CheckCancel = false;\n                    CallbackOutput.Cancel.Cancel = false;\n                    break;\n\n                // Thread callbacks\n                case MINIDUMP_CALLBACK_TYPE.IncludeThreadCallback:\n                    _logger.WriteLine(\"\\tDefault include thread flags for thread {0} = {1}\",\n                        CallbackInput.IncludeThread.ThreadId,\n                        CallbackOutput.ThreadWriteFlags);\n                    break;\n                case MINIDUMP_CALLBACK_TYPE.ThreadCallback:\n                case MINIDUMP_CALLBACK_TYPE.ThreadExCallback:\n                    _logger.WriteLine(\"\\tWriting thread {0} handle {1:x} stack {2:x16} - {3:x16}\",\n                        CallbackInput.Thread.ThreadId, CallbackInput.Thread.ThreadHandle,\n                        CallbackInput.Thread.StackBase, CallbackInput.Thread.StackEnd);\n                    break;\n                default:\n                    break;\n\n                // Module callbacks\n                case MINIDUMP_CALLBACK_TYPE.IncludeModuleCallback:\n                    _logger.WriteLine(\"\\tDefault include module flags for module @ {0:x16} = {1}\",\n                        CallbackInput.IncludeModule.BaseOfImage,\n                        CallbackOutput.ModuleWriteFlags);\n                    break;\n                case MINIDUMP_CALLBACK_TYPE.ModuleCallback:\n                    string moduleName = Marshal.PtrToStringUni(CallbackInput.Module.FullPath);\n                    _logger.WriteLine(\"\\tWriting module @ {0:x16} {1}\",\n                        CallbackInput.Module.BaseOfImage,\n                        moduleName);\n                    break;\n\n                // Memory callbacks\n                case MINIDUMP_CALLBACK_TYPE.MemoryCallback:\n                    if (!_needMemoryCallbacks)\n                        break;\n                    if (_regionEnumerator == null)\n                    {\n                        _regionEnumerator = EnumerateAllNeededRegions().GetEnumerator();\n                    }\n                    if (_regionEnumerator.MoveNext())\n                    {\n                        var region = _regionEnumerator.Current;\n                        CallbackOutput.Memory.MemoryBase = region.Key;\n                        CallbackOutput.Memory.MemorySize = (uint)(region.Value - region.Key);\n                    }\n                    _logger.WriteLine(\"\\tRequesting memory region @ {0:x16} size {1}\",\n                        CallbackOutput.Memory.MemoryBase,\n                        CallbackOutput.Memory.MemorySize);\n                    // If this callback produces a non-zero value, it will be included in the \n                    // dump and the callback will be invoked again. This is only relevant when\n                    // not capturing a full memory dump.\n                    break;\n                case MINIDUMP_CALLBACK_TYPE.IncludeVmRegionCallback:\n                    if (!_needMemoryCallbacks)\n                        break;\n                    FilterVMRegion(ref CallbackOutput);\n                    break;\n\n                // Other callbacks\n                case MINIDUMP_CALLBACK_TYPE.KernelMinidumpStatusCallback:\n                case MINIDUMP_CALLBACK_TYPE.WriteKernelMinidumpCallback:\n                case MINIDUMP_CALLBACK_TYPE.SecondaryFlagsCallback:\n                case MINIDUMP_CALLBACK_TYPE.RemoveMemoryCallback:\n                    break;\n\n                // Memory error callback\n                case MINIDUMP_CALLBACK_TYPE.ReadMemoryFailureCallback:\n                    _logger.WriteLine(\"\\tFailed to read memory @ {0} size {1} error {2:x8}\",\n                        CallbackInput.ReadMemoryFailure.Offset,\n                        CallbackInput.ReadMemoryFailure.Bytes,\n                        CallbackInput.ReadMemoryFailure.FailureStatus);\n                    break;\n            }\n\n            return true;\n        }\n\n        private void FilterVMRegion(ref MINIDUMP_CALLBACK_OUTPUT CallbackOutput)\n        {\n            if (_dumpType != DumpType.FullMemoryExcludingSafeRegions)\n            {\n                // No further callbacks of this type are required.\n                CallbackOutput.MemoryInfo.Continue = false;\n                return;\n            }\n            _logger.WriteLine(\"\\tWrite VM region @ {0:x16} size {1} {2} {3} {4}\",\n                CallbackOutput.MemoryInfo.VmRegion.BaseAddress,\n                CallbackOutput.MemoryInfo.VmRegion.RegionSize,\n                CallbackOutput.MemoryInfo.VmRegion.State,\n                CallbackOutput.MemoryInfo.VmRegion.Type,\n                CallbackOutput.MemoryInfo.VmRegion.Protect);\n\n            // NOTE We can further filter because we don't necessarily need the whole\n            // region. We can find the maximum overlapping needed region that is contained\n            // within this region, and change the BaseAddress and RegionSize fields to\n            // capture only that sub-region.\n            if (!IsNeededRegion(\n                CallbackOutput.MemoryInfo.VmRegion.BaseAddress,\n                CallbackOutput.MemoryInfo.VmRegion.BaseAddress + CallbackOutput.MemoryInfo.VmRegion.RegionSize)\n                )\n            {\n                // We do not need this region.\n                _logger.WriteLine(\"\\tRegion EXCLUDED from dump\");\n                CallbackOutput.MemoryInfo.VmRegion.RegionSize = 0;\n            }\n\n            // If the region size or base address are modified (as long as they remain a \n            // subset of the original region), that's what the dump will contain.\n            CallbackOutput.MemoryInfo.Continue = true;\n        }\n\n        public DumpWriter(TextWriter logger = null)\n        {\n            _logger = logger ?? TextWriter.Null;\n        }\n\n        public void Dump(int pid, DumpType dumpType, IntPtr exceptionParam,\n            string fileName, bool writeAsync = false, string dumpComment = null)\n        {\n            _pid = pid;\n            _dumpType = dumpType;\n            _spillSegmentsAsynchronously = writeAsync;\n            dumpComment = dumpComment ?? (\"DumpWriter: \" + _dumpType.ToString());\n\n            IntPtr hProcess = DumpNativeMethods.OpenProcess(\n                ProcessAccessFlags.QueryInformation | ProcessAccessFlags.VirtualMemoryRead | ProcessAccessFlags.DuplicateHandle,\n                false,\n                (uint)_pid\n                );\n            if (hProcess == IntPtr.Zero)\n            {\n                throw new ArgumentException(String.Format(\"Unable to open process {0}, error {1:x8}\", _pid, Marshal.GetLastWin32Error()));\n            }\n\n            _dumpFileStream = new FileStream(fileName, FileMode.Create);\n\n            var userStreamParam = PrepareUserStream(dumpComment);\n            var callbackParam = new MINIDUMP_CALLBACK_INFORMATION();\n            _needMemoryCallbacks = (\n                _dumpType == DumpType.FullMemoryExcludingSafeRegions ||\n                _dumpType == DumpType.MinimalWithFullCLRHeap\n                );\n            if (_needMemoryCallbacks || _spillSegmentsAsynchronously)\n            {\n                callbackParam.CallbackRoutine = CallbackRoutine;\n            }\n\n            MINIDUMP_TYPE nativeDumpType =\n                (_dumpType == DumpType.FullMemory || _dumpType == DumpType.FullMemoryExcludingSafeRegions) ?\n                MINIDUMP_TYPE.MiniDumpWithFullMemory | MINIDUMP_TYPE.MiniDumpWithHandleData | MINIDUMP_TYPE.MiniDumpWithFullMemoryInfo :\n                MINIDUMP_TYPE.MiniDumpWithHandleData | MINIDUMP_TYPE.MiniDumpWithFullMemoryInfo;\n            Stopwatch sw = Stopwatch.StartNew();\n            bool success = DumpNativeMethods.MiniDumpWriteDump(\n                hProcess,\n                (uint)_pid,\n                _dumpFileStream.SafeFileHandle.DangerousGetHandle(),\n                nativeDumpType,\n                exceptionParam,\n                ref userStreamParam,\n                ref callbackParam);\n            if (!success)\n                throw new ApplicationException(string.Format(\"Error writing dump, error: {0}\", Marshal.GetExceptionForHR(\n                    Marshal.GetHRForLastWin32Error())));\n\n            _logger.WriteLine(\"Process was suspended for {0:N2}ms\", sw.Elapsed.TotalMilliseconds);\n\n            if (_spillSegmentsAsynchronously)\n            {\n                // We are asynchronously spilling dump segments to disk, need to wait\n                // for this process to complete before returning to the caller.\n                _segmentSpillingTask.Wait();\n                _logger.WriteLine(\n                    \"Total dump writing time including async flush was {0:N2}ms\",\n                    sw.Elapsed.TotalMilliseconds);\n            }\n\n            userStreamParam.Delete();\n            DumpNativeMethods.CloseHandle(hProcess);\n            _dumpFileStream.Close();\n        }\n\n        private void SpillDumpSegmentsToDisk()\n        {\n            foreach (var segment in _dumpedSegments.GetConsumingEnumerable())\n            {\n                _dumpFileStream.Seek((long)segment.Offset, SeekOrigin.Begin);\n                _dumpFileStream.Write(segment.Data, 0, segment.Data.Length);\n            }\n        }\n\n        private static MINIDUMP_USER_STREAM_INFORMATION PrepareUserStream(string dumpComment)\n        {\n            MINIDUMP_USER_STREAM userStream = new MINIDUMP_USER_STREAM();\n            userStream.Type = MINIDUMP_STREAM_TYPE.CommentStreamW;\n            userStream.Buffer = Marshal.StringToHGlobalUni(dumpComment);\n            userStream.BufferSize = (uint)(dumpComment.Length + 1) * 2;\n            return new MINIDUMP_USER_STREAM_INFORMATION(userStream);\n        }\n    }\n}\n"
  },
  {
    "path": "DumpWriter/DumpWriter.csproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"12.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <Import Project=\"$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props\" Condition=\"Exists('$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props')\" />\n  <PropertyGroup>\n    <Configuration Condition=\" '$(Configuration)' == '' \">Debug</Configuration>\n    <Platform Condition=\" '$(Platform)' == '' \">AnyCPU</Platform>\n    <ProjectGuid>{1C19B4D7-E6A6-4A9A-8495-8231FA167D1C}</ProjectGuid>\n    <OutputType>Library</OutputType>\n    <AppDesignerFolder>Properties</AppDesignerFolder>\n    <RootNamespace>DumpWriter</RootNamespace>\n    <AssemblyName>gt</AssemblyName>\n    <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>\n    <FileAlignment>512</FileAlignment>\n    <SolutionDir Condition=\"$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'\">..\\</SolutionDir>\n    <RestorePackages>true</RestorePackages>\n    <TargetFrameworkProfile />\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)' == 'Debug|x86'\">\n    <DebugSymbols>true</DebugSymbols>\n    <OutputPath>bin\\x86\\Debug\\</OutputPath>\n    <DefineConstants>DEBUG;TRACE</DefineConstants>\n    <DebugType>full</DebugType>\n    <PlatformTarget>x86</PlatformTarget>\n    <ErrorReport>prompt</ErrorReport>\n    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>\n    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)' == 'Release|x86'\">\n    <OutputPath>bin\\x86\\Release\\</OutputPath>\n    <DefineConstants>TRACE</DefineConstants>\n    <Optimize>true</Optimize>\n    <DebugType>pdbonly</DebugType>\n    <PlatformTarget>x86</PlatformTarget>\n    <ErrorReport>prompt</ErrorReport>\n    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>\n    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)' == 'Debug|x64'\">\n    <DebugSymbols>true</DebugSymbols>\n    <OutputPath>bin\\x64\\Debug\\</OutputPath>\n    <DefineConstants>TRACE;DEBUG;X64</DefineConstants>\n    <DebugType>full</DebugType>\n    <PlatformTarget>x64</PlatformTarget>\n    <ErrorReport>prompt</ErrorReport>\n    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>\n    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)' == 'Release|x64'\">\n    <OutputPath>bin\\x64\\Release\\</OutputPath>\n    <DefineConstants>TRACE;X64</DefineConstants>\n    <Optimize>true</Optimize>\n    <DebugType>pdbonly</DebugType>\n    <PlatformTarget>x64</PlatformTarget>\n    <ErrorReport>prompt</ErrorReport>\n    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>\n    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>\n  </PropertyGroup>\n  <ItemGroup>\n    <Reference Include=\"C5, Version=2.4.5947.17248, Culture=neutral, PublicKeyToken=282361b99ded7e8e, processorArchitecture=MSIL\">\n      <HintPath>..\\packages\\C5.2.4.5947.17249\\lib\\net45\\C5.dll</HintPath>\n      <Private>True</Private>\n    </Reference>\n    <Reference Include=\"Microsoft.Diagnostics.Runtime, Version=1.0.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL\">\n      <HintPath>..\\packages\\Microsoft.Diagnostics.Runtime.1.0.3\\lib\\net45\\Microsoft.Diagnostics.Runtime.dll</HintPath>\n    </Reference>\n    <Reference Include=\"System\" />\n    <Reference Include=\"System.Core\" />\n    <Reference Include=\"System.Xml.Linq\" />\n    <Reference Include=\"System.Data.DataSetExtensions\" />\n    <Reference Include=\"Microsoft.CSharp\" />\n    <Reference Include=\"System.Data\" />\n    <Reference Include=\"System.Xml\" />\n  </ItemGroup>\n  <ItemGroup>\n    <Compile Include=\"DumpReaderLogger.cs\" />\n    <Compile Include=\"DumpWriter.cs\" />\n    <Compile Include=\"Native.cs\" />\n    <Compile Include=\"Properties\\AssemblyInfo.cs\" />\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"packages.config\" />\n  </ItemGroup>\n  <Import Project=\"$(MSBuildToolsPath)\\Microsoft.CSharp.targets\" />\n  <Import Project=\"$(SolutionDir)\\.nuget\\NuGet.targets\" Condition=\"Exists('$(SolutionDir)\\.nuget\\NuGet.targets')\" />\n  <Target Name=\"EnsureNuGetPackageBuildImports\" BeforeTargets=\"PrepareForBuild\">\n    <PropertyGroup>\n      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>\n    </PropertyGroup>\n    <Error Condition=\"!Exists('$(SolutionDir)\\.nuget\\NuGet.targets')\" Text=\"$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\\.nuget\\NuGet.targets'))\" />\n  </Target>\n  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. \n       Other similar extension points exist, see Microsoft.Common.targets.\n  <Target Name=\"BeforeBuild\">\n  </Target>\n  <Target Name=\"AfterBuild\">\n  </Target>\n  -->\n</Project>"
  },
  {
    "path": "DumpWriter/Native.cs",
    "content": "﻿using System;\nusing System.Runtime.InteropServices;\n\nnamespace DumpWriter\n{\n#pragma warning disable 0649\n    [Flags]\n    enum MINIDUMP_TYPE : int\n    {\n        MiniDumpNormal = 0x00000000,\n        MiniDumpWithDataSegs = 0x00000001,\n        MiniDumpWithFullMemory = 0x00000002,\n        MiniDumpWithHandleData = 0x00000004,\n        MiniDumpFilterMemory = 0x00000008,\n        MiniDumpScanMemory = 0x00000010,\n        MiniDumpWithUnloadedModules = 0x00000020,\n        MiniDumpWithIndirectlyReferencedMemory = 0x00000040,\n        MiniDumpFilterModulePaths = 0x00000080,\n        MiniDumpWithProcessThreadData = 0x00000100,\n        MiniDumpWithPrivateReadWriteMemory = 0x00000200,\n        MiniDumpWithoutOptionalData = 0x00000400,\n        MiniDumpWithFullMemoryInfo = 0x00000800,\n        MiniDumpWithThreadInfo = 0x00001000,\n        MiniDumpWithCodeSegs = 0x00002000,\n        MiniDumpWithoutAuxiliaryState = 0x00004000,\n        MiniDumpWithFullAuxiliaryState = 0x00008000,\n        MiniDumpWithPrivateWriteCopyMemory = 0x00010000,\n        MiniDumpIgnoreInaccessibleMemory = 0x00020000,\n        MiniDumpWithTokenInformation = 0x00040000,\n        MiniDumpWithModuleHeaders = 0x00080000,\n        MiniDumpFilterTriage = 0x00100000,\n        MiniDumpValidTypeFlags = 0x001fffff\n    }\n\n    [StructLayout(LayoutKind.Sequential, Pack = 4)]\n    public struct EXCEPTION_POINTERS\n    {\n        public IntPtr ExceptionRecord;\n        public byte[] ContextRecord;\n    }\n\n    [StructLayout(LayoutKind.Sequential, Pack = 4)]\n    public struct MINIDUMP_EXCEPTION_INFORMATION\n    {\n        public uint ThreadId;\n        public IntPtr ExceptionPointers;\n        [MarshalAs(UnmanagedType.Bool)]\n        public bool ClientPointers;\n    }\n\n    enum MINIDUMP_STREAM_TYPE : uint\n    {\n        UnusedStream = 0,\n        ReservedStream0 = 1,\n        ReservedStream1 = 2,\n        ThreadListStream = 3,\n        ModuleListStream = 4,\n        MemoryListStream = 5,\n        ExceptionStream = 6,\n        SystemInfoStream = 7,\n        ThreadExListStream = 8,\n        Memory64ListStream = 9,\n        CommentStreamA = 10,\n        CommentStreamW = 11,\n        HandleDataStream = 12,\n        FunctionTableStream = 13,\n        UnloadedModuleListStream = 14,\n        MiscInfoStream = 15,\n        MemoryInfoListStream = 16,\n        ThreadInfoListStream = 17,\n        HandleOperationListStream = 18,\n        LastReservedStream = 0xffff\n    }\n\n    [StructLayout(LayoutKind.Sequential, Pack = 4)]\n    struct MINIDUMP_USER_STREAM\n    {\n        public MINIDUMP_STREAM_TYPE Type;\n        public uint BufferSize;\n        public IntPtr Buffer;\n    }\n\n    [StructLayout(LayoutKind.Sequential, Pack = 4)]\n    struct MINIDUMP_USER_STREAM_INFORMATION\n    {\n        public MINIDUMP_USER_STREAM_INFORMATION(params MINIDUMP_USER_STREAM[] streams)\n        {\n            UserStreamCount = (uint)streams.Length;\n            int sizeOfStream = Marshal.SizeOf(typeof(MINIDUMP_USER_STREAM));\n            UserStreamArray = Marshal.AllocHGlobal((int)(UserStreamCount * sizeOfStream));\n            for (int i = 0; i < streams.Length; ++i)\n            {\n                Marshal.StructureToPtr(streams[i], UserStreamArray + (i * sizeOfStream), false);\n            }\n        }\n\n        public void Delete()\n        {\n            Marshal.FreeHGlobal(UserStreamArray);\n            UserStreamCount = 0;\n            UserStreamArray = IntPtr.Zero;\n        }\n\n        public uint UserStreamCount;\n        public IntPtr UserStreamArray;\n    }\n\n    enum MINIDUMP_CALLBACK_TYPE : uint\n    {\n        ModuleCallback,\n        ThreadCallback,\n        ThreadExCallback,\n        IncludeThreadCallback,\n        IncludeModuleCallback,\n        MemoryCallback,\n        CancelCallback,\n        WriteKernelMinidumpCallback,\n        KernelMinidumpStatusCallback,\n        RemoveMemoryCallback,\n        IncludeVmRegionCallback,\n        IoStartCallback,\n        IoWriteAllCallback,\n        IoFinishCallback,\n        ReadMemoryFailureCallback,\n        SecondaryFlagsCallback\n    }\n\n    [StructLayout(LayoutKind.Sequential, Pack = 4)]\n    unsafe struct MINIDUMP_THREAD_CALLBACK\n    {\n        public uint ThreadId;\n        public IntPtr ThreadHandle;\n        public fixed byte Context[DumpNativeMethods.CONTEXT_SIZE];\n        public uint SizeOfContext;\n        public ulong StackBase;\n        public ulong StackEnd;\n    }\n\n    [StructLayout(LayoutKind.Sequential, Pack = 4)]\n    struct MINIDUMP_THREAD_EX_CALLBACK\n    {\n        public MINIDUMP_THREAD_CALLBACK BasePart;\n        public ulong BackingStoreBase;\n        public ulong BackingStoreEnd;\n    }\n\n    enum VS_FIXEDFILEINFO_FileFlags : uint\n    {\n        VS_FF_DEBUG = 0x00000001,\n        VS_FF_INFOINFERRED = 0x00000010,\n        VS_FF_PATCHED = 0x00000004,\n        VS_FF_PRERELEASE = 0x00000002,\n        VS_FF_PRIVATEBUILD = 0x00000008,\n        VS_FF_SPECIALBUILD = 0x00000020\n    }\n\n    enum VS_FIXEDFILEINFO_FileOSFlags : uint\n    {\n        VOS_DOS = 0x00010000,\n        VOS_NT = 0x00040000,\n        VOS__WINDOWS16 = 0x00000001,\n        VOS__WINDOWS32 = 0x00000004,\n        VOS_OS216 = 0x00020000,\n        VOS_OS232 = 0x00030000,\n        VOS__PM16 = 0x00000002,\n        VOS__PM32 = 0x00000003,\n        VOS_UNKNOWN = 0x00000000\n    }\n\n    enum VS_FIXEDFILEINFO_FileTypeFlags : uint\n    {\n        VFT_APP = 0x00000001,\n        VFT_DLL = 0x00000002,\n        VFT_DRV = 0x00000003,\n        VFT_FONT = 0x00000004,\n        VFT_STATIC_LIB = 0x00000007,\n        VFT_UNKNOWN = 0x00000000,\n        VFT_VXD = 0x00000005\n    }\n\n    enum VS_FIXEFILEINFO_FileSubTypeFlags : uint\n    {\n        // If the FileType is VFT_DRV\n        VFT2_DRV_COMM = 0x0000000A,\n        VFT2_DRV_DISPLAY = 0x00000004,\n        VFT2_DRV_INSTALLABLE = 0x00000008,\n        VFT2_DRV_KEYBOARD = 0x00000002,\n        VFT2_DRV_LANGUAGE = 0x00000003,\n        VFT2_DRV_MOUSE = 0x00000005,\n        VFT2_DRV_NETWORK = 0x00000006,\n        VFT2_DRV_PRINTER = 0x00000001,\n        VFT2_DRV_SOUND = 0x00000009,\n        VFT2_DRV_SYSTEM = 0x00000007,\n        VFT2_DRV_VERSIONED_PRINTER = 0x0000000C,\n\n        // If the FileType is VFT_FONT\n        VFT2_FONT_RASTER = 0x00000001,\n        VFT2_FONT_TRUETYPE = 0x00000003,\n        VFT2_FONT_VECTOR = 0x00000002,\n\n        VFT2_UNKNOWN = 0x00000000\n    }\n\n    [StructLayout(LayoutKind.Sequential, Pack = 4)]\n    struct VS_FIXEDFILEINFO\n    {\n        public uint dwSignature;\n        public uint dwStrucVersion;\n        public uint dwFileVersionMS;\n        public uint dwFileVersionLS;\n        public uint dwProductVersionMS;\n        public uint dwProductVersionLS;\n        public uint dwFileFlagsMask;\n        public uint dwFileFlags;\n        public uint dwFileOS;\n        public uint dwFileType;\n        public uint dwFileSubtype;\n        public uint dwFileDateMS;\n        public uint dwFileDateLS;\n    }\n\n    [StructLayout(LayoutKind.Sequential, Pack = 4)]\n    struct MINIDUMP_MODULE_CALLBACK\n    {\n        public IntPtr FullPath; // This is a PCWSTR\n        public ulong BaseOfImage;\n        public uint SizeOfImage;\n        public uint CheckSum;\n        public uint TimeDateStamp;\n        public VS_FIXEDFILEINFO VersionInfo;\n        public IntPtr CvRecord;\n        public uint SizeOfCvRecord;\n        public IntPtr MiscRecord;\n        public uint SizeOfMiscRecord;\n    }\n\n    struct MINIDUMP_INCLUDE_THREAD_CALLBACK\n    {\n        public uint ThreadId;\n    }\n\n    [StructLayout(LayoutKind.Sequential, Pack = 4)]\n    struct MINIDUMP_INCLUDE_MODULE_CALLBACK\n    {\n        public ulong BaseOfImage;\n    }\n\n    [StructLayout(LayoutKind.Sequential, Pack = 4)]\n    struct MINIDUMP_IO_CALLBACK\n    {\n        public IntPtr Handle;\n        public ulong Offset;\n        public IntPtr Buffer;\n        public uint BufferBytes;\n    }\n\n    [StructLayout(LayoutKind.Sequential, Pack = 4)]\n    struct MINIDUMP_READ_MEMORY_FAILURE_CALLBACK\n    {\n        public ulong Offset;\n        public uint Bytes;\n        public int FailureStatus; // HRESULT\n    }\n\n    [Flags]\n    enum MINIDUMP_SECONDARY_FLAGS : uint\n    {\n        MiniSecondaryWithoutPowerInfo = 0x00000001\n    }\n\n    [StructLayout(LayoutKind.Explicit)]\n    struct MINIDUMP_CALLBACK_INPUT\n    {\n#if X64\n        const int CallbackTypeOffset = 4 + 8;\n#else\n        const int CallbackTypeOffset = 4 + 4;\n#endif\n        const int UnionOffset = CallbackTypeOffset + 4;\n\n        [FieldOffset(0)]\n        public uint ProcessId;\n        [FieldOffset(4)]\n        public IntPtr ProcessHandle;\n        [FieldOffset(CallbackTypeOffset)]\n        public MINIDUMP_CALLBACK_TYPE CallbackType;\n\n        [FieldOffset(UnionOffset)]\n        public int Status; // HRESULT\n        [FieldOffset(UnionOffset)]\n        public MINIDUMP_THREAD_CALLBACK Thread;\n        [FieldOffset(UnionOffset)]\n        public MINIDUMP_THREAD_EX_CALLBACK ThreadEx;\n        [FieldOffset(UnionOffset)]\n        public MINIDUMP_MODULE_CALLBACK Module;\n        [FieldOffset(UnionOffset)]\n        public MINIDUMP_INCLUDE_THREAD_CALLBACK IncludeThread;\n        [FieldOffset(UnionOffset)]\n        public MINIDUMP_INCLUDE_MODULE_CALLBACK IncludeModule;\n        [FieldOffset(UnionOffset)]\n        public MINIDUMP_IO_CALLBACK Io;\n        [FieldOffset(UnionOffset)]\n        public MINIDUMP_READ_MEMORY_FAILURE_CALLBACK ReadMemoryFailure;\n        [FieldOffset(UnionOffset)]\n        public MINIDUMP_SECONDARY_FLAGS SecondaryFlags;\n    }\n\n    enum STATE : uint\n    {\n        MEM_COMMIT = 0x1000,\n        MEM_FREE = 0x10000,\n        MEM_RESERVE = 0x2000\n    }\n\n    enum TYPE : uint\n    {\n        MEM_IMAGE = 0x1000000,\n        MEM_MAPPED = 0x40000,\n        MEM_PRIVATE = 0x20000\n    }\n\n    [Flags]\n    enum PROTECT : uint\n    {\n        PAGE_EXECUTE = 0x10,\n        PAGE_EXECUTE_READ = 0x20,\n        PAGE_EXECUTE_READWRITE = 0x40,\n        PAGE_EXECUTE_WRITECOPY = 0x80,\n        PAGE_NOACCESS = 0x01,\n        PAGE_READONLY = 0x02,\n        PAGE_READWRITE = 0x04,\n        PAGE_WRITECOPY = 0x08,\n        PAGE_TARGETS_INVALID = 0x40000000,\n        PAGE_TARGETS_NO_UPDATE = 0x40000000,\n\n        PAGE_GUARD = 0x100,\n        PAGE_NOCACHE = 0x200,\n        PAGE_WRITECOMBINE = 0x400\n    }\n\n    [StructLayout(LayoutKind.Sequential, Pack = 4)]\n    struct MINIDUMP_MEMORY_INFO\n    {\n        public ulong BaseAddress;\n        public ulong AllocationBase;\n        public uint AllocationProtect;\n        public uint __alignment1;\n        public ulong RegionSize;\n        public STATE State;\n        public PROTECT Protect;\n        public TYPE Type;\n        public uint __alignment2;\n    }\n\n    [StructLayout(LayoutKind.Sequential, Pack = 4)]\n    struct MemoryCallbackOutput\n    {\n        public ulong MemoryBase;\n        public uint MemorySize;\n    }\n\n    [StructLayout(LayoutKind.Sequential, Pack = 4)]\n    struct CancelCallbackOutput\n    {\n        [MarshalAs(UnmanagedType.Bool)]\n        public bool CheckCancel;\n        [MarshalAs(UnmanagedType.Bool)]\n        public bool Cancel;\n    }\n\n    [StructLayout(LayoutKind.Sequential, Pack = 4)]\n    struct MemoryInfoCallbackOutput\n    {\n        public MINIDUMP_MEMORY_INFO VmRegion;\n        [MarshalAs(UnmanagedType.Bool)]\n        public bool Continue;\n    }\n\n    [Flags]\n    enum THREAD_WRITE_FLAGS : uint\n    {\n        ThreadWriteThread = 0x0001,\n        ThreadWriteStack = 0x0002,\n        ThreadWriteContext = 0x0004,\n        ThreadWriteBackingStore = 0x0008,\n        ThreadWriteInstructionWindow = 0x0010,\n        ThreadWriteThreadData = 0x0020,\n        ThreadWriteThreadInfo = 0x0040\n    }\n\n    [Flags]\n    enum MODULE_WRITE_FLAGS : uint\n    {\n        ModuleWriteModule = 0x0001,\n        ModuleWriteDataSeg = 0x0002,\n        ModuleWriteMiscRecord = 0x0004,\n        ModuleWriteCvRecord = 0x0008,\n        ModuleReferencedByMemory = 0x0010,\n        ModuleWriteTlsData = 0x0020,\n        ModuleWriteCodeSegs = 0x0040\n    }\n\n    [StructLayout(LayoutKind.Explicit, Pack = 4)]\n    struct MINIDUMP_CALLBACK_OUTPUT\n    {\n        [FieldOffset(0)]\n        public MODULE_WRITE_FLAGS ModuleWriteFlags;\n        [FieldOffset(0)]\n        public THREAD_WRITE_FLAGS ThreadWriteFlags;\n        [FieldOffset(0)]\n        public uint SecondaryFlags;\n        [FieldOffset(0)]\n        public MemoryCallbackOutput Memory;\n        [FieldOffset(0)]\n        public CancelCallbackOutput Cancel;\n        [FieldOffset(0)]\n        public IntPtr Handle;\n        [FieldOffset(0)]\n        public MemoryInfoCallbackOutput MemoryInfo;\n        [FieldOffset(0)]\n        public int Status; // HRESULT\n    }\n\n    [UnmanagedFunctionPointer(CallingConvention.StdCall)]\n    [return: MarshalAs(UnmanagedType.Bool)]\n    delegate bool MINIDUMP_CALLBACK_ROUTINE(\n        [In] IntPtr CallbackParam,\n        [In] ref MINIDUMP_CALLBACK_INPUT CallbackInput,\n        [In, Out] ref MINIDUMP_CALLBACK_OUTPUT CallbackOutput\n        );\n\n    struct MINIDUMP_CALLBACK_INFORMATION\n    {\n        public MINIDUMP_CALLBACK_ROUTINE CallbackRoutine;\n        public IntPtr CallbackParam;\n    }\n\n    [Flags]\n    enum ProcessAccessFlags : uint\n    {\n        All = 0x001F0FFF,\n        Terminate = 0x00000001,\n        CreateThread = 0x00000002,\n        VirtualMemoryOperation = 0x00000008,\n        VirtualMemoryRead = 0x00000010,\n        VirtualMemoryWrite = 0x00000020,\n        DuplicateHandle = 0x00000040,\n        CreateProcess = 0x000000080,\n        SetQuota = 0x00000100,\n        SetInformation = 0x00000200,\n        QueryInformation = 0x00000400,\n        QueryLimitedInformation = 0x00001000,\n        Synchronize = 0x00100000\n    }\n\n    class DumpNativeMethods\n    {\n#if X64\n        public const int CONTEXT_SIZE = 1232;\n#else\n        public const int CONTEXT_SIZE = 716;\n#endif\n\n        [DllImport(\"dbghelp.dll\", CallingConvention = CallingConvention.Winapi, SetLastError = true)]\n        [return: MarshalAs(UnmanagedType.Bool)]\n        public static extern bool MiniDumpWriteDump(\n            IntPtr hProcess,\n            uint ProcessId,\n            IntPtr hFile,\n            MINIDUMP_TYPE DumpType,\n            IntPtr ExceptionParams,\n            [In] ref MINIDUMP_USER_STREAM_INFORMATION UserStreamParam,\n            [In] ref MINIDUMP_CALLBACK_INFORMATION CallbackParam\n            );\n\n        [DllImport(\"kernel32.dll\", CallingConvention = CallingConvention.Winapi, SetLastError = true)]\n        public static extern IntPtr OpenProcess(\n            ProcessAccessFlags dwDesiredAccess,\n            bool bInheritHandle,\n            uint dwProcessId\n            );\n\n        [DllImport(\"kernel32.dll\", CallingConvention = CallingConvention.Winapi, SetLastError = true)]\n        [return: MarshalAs(UnmanagedType.Bool)]\n        public static extern bool CloseHandle(IntPtr Handle);\n    }\n#pragma warning restore 0649\n}\n"
  },
  {
    "path": "DumpWriter/Properties/AssemblyInfo.cs",
    "content": "﻿using System.Reflection;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\n\n// General Information about an assembly is controlled through the following \n// set of attributes. Change these attribute values to modify the information\n// associated with an assembly.\n[assembly: AssemblyTitle(\"DumpWriter\")]\n[assembly: AssemblyDescription(\"\")]\n[assembly: AssemblyConfiguration(\"\")]\n[assembly: AssemblyCompany(\"\")]\n[assembly: AssemblyProduct(\"DumpWriter\")]\n[assembly: AssemblyCopyright(\"Copyright © Sasha Goldshtein 2015\")]\n[assembly: AssemblyTrademark(\"\")]\n[assembly: AssemblyCulture(\"\")]\n\n// Setting ComVisible to false makes the types in this assembly not visible \n// to COM components.  If you need to access a type in this assembly from \n// COM, set the ComVisible attribute to true on that type.\n[assembly: ComVisible(false)]\n\n// The following GUID is for the ID of the typelib if this project is exposed to COM\n[assembly: Guid(\"eb73c681-da0e-4d18-a31f-550dc46670a0\")]\n\n// Version information for an assembly consists of the following four values:\n//\n//      Major Version\n//      Minor Version \n//      Build Number\n//      Revision\n//\n// You can specify all the values or you can default the Build and Revision Numbers \n// by using the '*' as shown below:\n// [assembly: AssemblyVersion(\"1.0.*\")]\n[assembly: AssemblyVersion(\"1.0.0.0\")]\n[assembly: AssemblyFileVersion(\"1.0.0.0\")]\n"
  },
  {
    "path": "DumpWriter/packages.config",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<packages>\n  <package id=\"C5\" version=\"2.4.5947.17249\" targetFramework=\"net45\" />\n  <package id=\"Microsoft.Diagnostics.Runtime\" version=\"1.0.3\" targetFramework=\"net452\" />\n</packages>"
  },
  {
    "path": "LICENSE.md",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 Sasha Goldshtein\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "MiniDumper/App.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n    <startup> \n        <supportedRuntime version=\"v4.0\" sku=\".NETFramework,Version=v4.5.2\"/>\n    </startup>\n</configuration>\n"
  },
  {
    "path": "MiniDumper/CommandLineOptions.cs",
    "content": "﻿using CommandLine;\nusing System.Collections.Generic;\n\nnamespace MiniDumper\n{\n    class CommandLineOptions\n    {\n        [Option('m', HelpText =\n            \"Create a dump file: \" +\n            \"-mm (dump file with crash info and call stacks); \" +\n            \"-mh (dump file with the CLR heap, no native memory); \" +\n            \"-ma (complete dump file with the full memory address space)\", Required = true)]\n        public char DumpType { get; set; }\n\n        [Option(\"async\", HelpText =\n            \"Write dump chunks to disk asynchronously. Reduces process suspension time \" +\n            \"at the expense of higher memory usage.\")]\n        public bool Async { get; set; }\n\n        // FUTURE\n        //[Option('r', HelpText = \"Dump using a clone.\")]\n        //public bool CloneProcess { get; set; }\n\n        [Option('e', HelpText =\"Write a dump when the process encounters an unhandled exception. \" +\n            \"Include the 1 to create dump on first chance exceptions, include the 2 to create dump on second chance exceptions.\")]\n        public int DumpOnException { get; set; }\n\n        [Option('l', HelpText = \"Display the debug logging of the process + diagnostics info from the minidumper.\")]\n        public bool Verbose { get; set; }\n\n        [Option(\"maxmem\", HelpText = \"Memory commit threshold in MB at which to create a dump.\")]\n        public uint? MemoryCommitThreshold { get; set; }\n        \n        [Option(\"minmem\", HelpText = \"Trigger when memory commit drops below specified MB value.\")]\n        public uint? MemoryCommitDrops { get; set; }\n\n        [Option('f', HelpText = \"Filter on the content of exceptions and debug logging. Wildcards (*) are supported.\")]\n        public string ExceptionFilter { get; set; }\n\n        [Option('x', HelpText = \"Launch the specified image with optional arguments.\")]\n        public string DumpFolderForNewlyStartedProcess { get; set; }\n\n        [Option('n', HelpText = \"Number of dumps to write before exiting.\", Default = 1)]\n        public int NumberOfDumps { get; set; }\n\n        [Option('t', HelpText = \"Write a dump when the process terminates.\")]\n        public bool DumpOnProcessTerminate { get; set; }\n\n        [Option('c', HelpText = \"Start the process in a new console window.\")]\n        public bool StartProcessInNewConsoleWindow { get; set; }\n\n        [Value(0, Required = true, HelpText = \"PID or process name\")]\n        public string ProcessInfo { get; set; }\n\n        [Value(0, Required = false, HelpText = \"Arguments for the process to start\")]\n        public IList<string> Args { get; set; }\n\n        public bool NoDumpOptionSelected\n        {\n            get { return !DumpOnProcessTerminate && DumpOnException == 0 && !(MemoryCommitThreshold.HasValue || MemoryCommitDrops.HasValue); }\n        }\n\n        public bool NeedAttachDebugger\n        {\n            get { return DumpOnProcessTerminate || DumpOnException == 1 || DumpOnException == 2; }\n        }\n    }\n}\n"
  },
  {
    "path": "MiniDumper/Debugger.cs",
    "content": "﻿using CommandLine;\nusing DumpWriter;\nusing System;\nusing System.Diagnostics;\nusing System.IO;\nusing System.Runtime.InteropServices;\nusing System.Text;\nusing System.Timers;\nusing VsChromium.Core.Win32;\nusing VsChromium.Core.Win32.Debugging;\nusing VsChromium.Core.Win32.Processes;\nusing DebuggingNativeMethods = VsChromium.Core.Win32.Debugging.NativeMethods;\nusing ProcessNativeMethods = VsChromium.Core.Win32.Processes.NativeMethods;\n\nnamespace MiniDumper\n{\n    class Debugger\n    {\n        static void Main(string[] args)\n        {\n            try\n            {\n                var result = Parser.Default.ParseArguments<CommandLineOptions>(args);\n                result.WithParsed(options => new Debugger(options).TakeDumps());\n            }\n            catch (Exception ex)\n            {\n                Console.Error.WriteLine(\"ERROR: {0}\", ex.Message);\n            }\n        }\n\n        private readonly CommandLineOptions _options;\n        private readonly TextWriter _logger;\n        private readonly string _dumpFolder;\n        private bool _detached;\n        private bool _shouldStop;\n        private int _pid;\n        private string _processName;\n        private Timer _timer;\n\n        public Debugger(CommandLineOptions options)\n        {\n            ValidateOptions(options);\n            _options = options;\n            _logger = options.Verbose ? Console.Out : TextWriter.Null;\n            _dumpFolder = options.DumpFolderForNewlyStartedProcess ?? Directory.GetCurrentDirectory();\n            _timer = new Timer(1000);\n        }\n\n        void TakeDumps()\n        {\n            CreateProcess();\n\n            ShowBanner();\n\n            // setup Ctrl+C listener\n            Console.CancelKeyPress += (o, ev) =>\n            {\n                Console.WriteLine(\"Ctrl + C received - detaching from a process\");\n                ev.Cancel = true;\n                _shouldStop = true;\n                _timer.Stop();\n            };\n\n            WaitForDebugEvents();\n        }\n\n        private void WaitForDebugEvents()\n        {\n            using (var miniDumper = CreateMiniDumper())\n            {\n                if (_options.NoDumpOptionSelected)\n                {\n                    miniDumper.DumpWithoutReason();\n                    DetachProcess();\n                    return;\n                }\n\n                if (_options.MemoryCommitThreshold.HasValue || _options.MemoryCommitDrops.HasValue)\n                {\n                    _timer.Elapsed += (o, ev) => CheckMemoryCommitThreshold(miniDumper);\n                    _timer.Start();\n                }\n\n                while (!_detached)\n                {\n                    var debugEvent = WaitForDebugEvent(1000);\n                    if (_shouldStop)\n                    {\n                        DetachProcess();\n                        return;\n                    }\n\n                    if (debugEvent.HasValue)\n                    {\n                        switch (debugEvent.Value.dwDebugEventCode)\n                        {\n                            case DEBUG_EVENT_CODE.EXIT_PROCESS_DEBUG_EVENT:\n                                if (_options.DumpOnProcessTerminate)\n                                {\n                                    miniDumper.DumpOnProcessExit(debugEvent.Value.ExitProcess.dwExitCode);\n                                }\n                                _shouldStop = true;\n                                _timer.Stop();\n                                break;\n                            case DEBUG_EVENT_CODE.EXCEPTION_DEBUG_EVENT:\n                                var exception = debugEvent.Value.Exception;\n                                if (_options.DumpOnException == 1 && exception.dwFirstChance == 1 ||\n                                    _options.DumpOnException == 2 && exception.dwFirstChance == 0)\n                                {\n                                    miniDumper.DumpOnException((uint)debugEvent.Value.dwThreadId, exception.ExceptionRecord);\n                                }\n                                break;\n                            case DEBUG_EVENT_CODE.OUTPUT_DEBUG_STRING_EVENT:\n                                if (_options.Verbose)\n                                {\n                                    miniDumper.PrintDebugString(debugEvent.Value.DebugString);\n                                }\n                                break;\n                            default:\n                                break;\n                        }\n                    }\n\n                    if (!_shouldStop && miniDumper.NumberOfDumpsTaken >= _options.NumberOfDumps)\n                    {\n                        Console.WriteLine(\"Number of dumps exceeded the specified limit - detaching.\");\n                        _shouldStop = true;\n                        _timer.Stop();\n                    }\n                    if (_shouldStop)\n                    {\n                        DetachProcess();\n                        return;\n                    }\n                    if (_detached)\n                    {\n                        return;\n                    }\n\n                    if (debugEvent.HasValue)\n                    {\n                        var continueStatus = HandleDebugEvent(debugEvent.Value);\n                        if (!DebuggingNativeMethods.ContinueDebugEvent(debugEvent.Value.dwProcessId,\n                            debugEvent.Value.dwThreadId, continueStatus))\n                        {\n                            throw new LastWin32ErrorException(\"Error in ContinueDebugEvent\");\n                        }\n                    }\n                }\n                Debug.Assert(!_timer.Enabled);\n            }\n        }\n\n        private void CheckMemoryCommitThreshold(MiniDumper miniDumper)\n        {\n            try\n            {\n                miniDumper.DumpOnMemoryCommitThreshold(_options.MemoryCommitThreshold, _options.MemoryCommitDrops);\n\n                if (!_shouldStop && miniDumper.NumberOfDumpsTaken >= _options.NumberOfDumps)\n                {\n                    Console.WriteLine(\"Number of dumps exceeded the specified limit - detaching.\");\n                    _shouldStop = true;\n                    _timer.Stop();\n                }\n            }\n            catch (Exception ex)\n            {\n                Console.WriteLine(ex.Message);\n                _shouldStop = true;\n                _timer.Stop();\n            }\n        }\n\n        private static DEBUG_EVENT? WaitForDebugEvent(uint timeout)\n        {\n            DEBUG_EVENT debugEvent;\n            var success = DebuggingNativeMethods.WaitForDebugEvent(out debugEvent, timeout);\n            if (!success)\n            {\n                int hr = Marshal.GetHRForLastWin32Error();\n                if (hr == HResults.HR_ERROR_SEM_TIMEOUT)\n                    return null;\n\n                Marshal.ThrowExceptionForHR(hr);\n            }\n            return debugEvent;\n        }\n\n        private static CONTINUE_STATUS HandleDebugEvent(DEBUG_EVENT value)\n        {\n            if (value.dwDebugEventCode == DEBUG_EVENT_CODE.EXCEPTION_DEBUG_EVENT)\n            {\n                return CONTINUE_STATUS.DBG_EXCEPTION_NOT_HANDLED;\n            }\n            return CONTINUE_STATUS.DBG_CONTINUE;\n        }\n\n        static void ValidateOptions(CommandLineOptions options)\n        {\n            if (string.IsNullOrEmpty(options.ProcessInfo))\n            {\n                throw new ArgumentException(\"Either a process id or process name is required\");\n            }\n            // file name and dump folder\n            if (options.DumpFolderForNewlyStartedProcess != null &&\n                !Directory.Exists(options.DumpFolderForNewlyStartedProcess))\n            {\n                throw new ArgumentException(\"The specified dump folder does not exist.\");\n            }\n            if (options.NoDumpOptionSelected && !string.IsNullOrEmpty(\n                options.DumpFolderForNewlyStartedProcess))\n            {\n                throw new ArgumentException(\"Option to create an immediate dump when starting a process is not supported.\");\n            }\n        }\n\n        void CreateProcess()\n        {\n            bool spawnNew = !string.IsNullOrEmpty(_options.DumpFolderForNewlyStartedProcess);\n            _processName = null;\n\n            int pid;\n            if (int.TryParse(_options.ProcessInfo, out pid))\n            {\n                _pid = pid;\n            }\n            else\n            {\n                // not numeric - let's try to find it by name\n                var procs = Process.GetProcesses();\n                foreach (var proc in procs)\n                {\n                    try\n                    {\n                        if (_options.ProcessInfo.Equals(proc.MainModule.ModuleName, StringComparison.OrdinalIgnoreCase))\n                        {\n                            _pid = proc.Id;\n                            break;\n                        }\n                    }\n                    catch\n                    {\n                        // just ignore it\n                    }\n                }\n            }\n            if (_pid > 0)\n            {\n                // process found - let's attach to it\n                if (!DebuggingNativeMethods.DebugActiveProcess(_pid))\n                {\n                    Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());\n                }\n                _processName = GetProcessName(_pid);\n                return;\n            }\n            if (spawnNew)\n            {\n                // final try - let's try creating it (but only if -x option is set)\n                var commandLine = _options.ProcessInfo + \" \" + string.Join(\" \", _options.Args ?? new string[0]);\n\n                var startupInfo = new STARTUPINFO();\n                var processInformation = new PROCESS_INFORMATION();\n                var processCreationFlags = ProcessCreationFlags.DEBUG_ONLY_THIS_PROCESS |\n                                           ProcessCreationFlags.CREATE_UNICODE_ENVIRONMENT;\n                if (_options.StartProcessInNewConsoleWindow)\n                {\n                    processCreationFlags |= ProcessCreationFlags.CREATE_NEW_CONSOLE;\n                }\n                bool res = ProcessNativeMethods.CreateProcess(null, new StringBuilder(commandLine),\n                    null, null, false, processCreationFlags, IntPtr.Zero, null,\n                    startupInfo, processInformation);\n                if (!res)\n                {\n                    Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());\n                }\n\n                if (!DebuggingNativeMethods.DebugSetProcessKillOnExit(false))\n                {\n                    Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());\n                }\n                _pid = processInformation.dwProcessId;\n                _processName = GetProcessName(_pid);\n                return;\n            }\n            throw new ArgumentException(\"Something is wrong with the arguments - couldn't find or create a requested process.\");\n        }\n\n        void DetachProcess()\n        {\n            if (_detached)\n            {\n                return;\n            }\n            if (!DebuggingNativeMethods.DebugActiveProcessStop(_pid))\n            {\n                _logger.Write(\"Exception occured when detaching from the process: {0}\",\n                    Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()));\n            }\n            _detached = true;\n        }\n\n        void ShowBanner()\n        {\n            Console.WriteLine(\"MiniDumper - writes .NET process dump files\");\n            Console.WriteLine(\"Copyright (C) 2019 Sasha Goldstein (@goldshtn)\");\n            Console.WriteLine();\n            Console.WriteLine(\"With contributions from Sebastian Solnica (@lowleveldesign)\");\n            Console.WriteLine();\n\n            Console.WriteLine(\"Process:             {0} ({1})\", _processName, _pid);\n            Console.WriteLine(\"Exception monitor:   {0}\", _options.DumpOnException == 1 ? \"First Chance+Unhandled\" :\n                (_options.DumpOnException == 2 ? \"Unhandled\" : \"Disabled\"));\n            Console.WriteLine(\"Exception filter:    {0}\", _options.ExceptionFilter ?? \"*\");\n            Console.WriteLine(\"Dump folder:         {0}\", _dumpFolder);\n            Console.WriteLine(\"Number of dumps:     {0}\", _options.NumberOfDumps);\n            Console.WriteLine(\"Dump filename/mask:  PROCESSNAME_YYMMDD_HHMMSS\");\n            Console.WriteLine(\"Terminal monitor:    {0}\", _options.DumpOnProcessTerminate ? \"Enabled\" : \"Disabled\");\n            Console.WriteLine(\"Debug output:        {0}\", _options.Verbose ? \"Enabled\" : \"Disabled\");\n            Console.WriteLine(\"Commit threshold:    {0}\", _options.MemoryCommitThreshold.HasValue ? $\">= {_options.MemoryCommitThreshold} MB\" : \"Disabled\");\n            Console.WriteLine();\n            Console.WriteLine(\"Press Ctrl-C to end monitoring without terminating the process.\");\n            Console.WriteLine();\n        }\n\n        private MiniDumper CreateMiniDumper()\n        {\n            return new MiniDumper(_dumpFolder, _pid, _processName, _logger,\n                OptionToDumpType(_options), _options.Async, _options.ExceptionFilter, _options.NumberOfDumps);\n        }\n\n        static string GetProcessName(int processId)\n        {\n            return Process.GetProcessById(processId).ProcessName;\n        }\n\n        static DumpType OptionToDumpType(CommandLineOptions options)\n        {\n            if (options.DumpType == 'm')\n                return DumpType.Minimal;\n            if (options.DumpType == 'h')\n                return DumpType.MinimalWithFullCLRHeap;\n            if (options.DumpType == 'a')\n                return DumpType.FullMemory;\n\n            // Should never get here\n            return DumpType.MinimalWithFullCLRHeap;\n        }\n    }\n}\n"
  },
  {
    "path": "MiniDumper/FodyWeavers.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<Weavers>\n  <Costura />\n</Weavers>"
  },
  {
    "path": "MiniDumper/MiniDumper.cs",
    "content": "﻿using DumpWriter;\nusing Microsoft.Diagnostics.Runtime;\nusing MiniDumper.Win32.Processes;\nusing System;\nusing System.Diagnostics;\nusing System.IO;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Text;\nusing System.Text.RegularExpressions;\nusing System.Threading;\nusing VsChromium.Core.Win32.Debugging;\nusing VsChromium.Core.Win32.Processes;\nusing ProcessNativeMethod = VsChromium.Core.Win32.Processes.NativeMethods;\n\nnamespace MiniDumper\n{\n    [Flags]\n    public enum ThreadAccess : int\n    {\n        TERMINATE = (0x0001),\n        SUSPEND_RESUME = (0x0002),\n        GET_CONTEXT = (0x0008),\n        SET_CONTEXT = (0x0010),\n        SET_INFORMATION = (0x0020),\n        QUERY_INFORMATION = (0x0040),\n        SET_THREAD_TOKEN = (0x0080),\n        IMPERSONATE = (0x0100),\n        DIRECT_IMPERSONATION = (0x0200)\n    }\n\n    class Native\n    {\n#if X64\n        public const int CONTEXT_SIZE = 1232;\n#else\n        public const int CONTEXT_SIZE = 716;\n#endif\n    }\n\n    class MiniDumper : IDisposable\n    {\n        const int _1MB = 1024 * 1024;\n        const uint CLRDBG_NOTIFICATION_EXCEPTION_CODE = 0x04242420;\n        const uint BREAKPOINT_CODE = 0x80000003;\n        const uint CTRL_C_EXCEPTION_CODE = 0x40010005;\n        const string dumpComment = \"Generated by MiniDumper\";\n\n        private static readonly object dumpLock = new object();\n        private readonly string dumpFolder;\n        private readonly int pid;\n        private readonly string processName;\n        private readonly TextWriter logger;\n        private readonly DumpType dumpType;\n        private readonly bool writeAsync;\n        private readonly Regex rgxFilter;\n        private int numberOfDumpsTaken;\n        private SafeProcessHandle hProcess;\n        uint processCommit;\n        int numberOfDumps;\n\n        public MiniDumper(string dumpFolder, int pid, string processName,\n            TextWriter logger, DumpType dumpType, bool writeAsync, string filter, int numberOfDumps)\n        {\n            this.dumpFolder = dumpFolder;\n            this.pid = pid;\n            this.processName = processName;\n            this.logger = logger;\n            this.dumpType = dumpType;\n            this.writeAsync = writeAsync;\n            rgxFilter = new Regex((filter ?? \"*\").Replace(\"*\", \".*\").Replace('?', '.'),\n                RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase);\n            hProcess = ProcessNativeMethod.OpenProcess(ProcessAccessFlags.QueryInformation | ProcessAccessFlags.VmRead, false, pid);\n            if (hProcess.IsInvalid)\n            {\n                throw new ArgumentException(String.Format(\"Unable to open process {0}, error {1:x8}\", pid, Marshal.GetLastWin32Error()));\n            }\n\n            this.numberOfDumps = numberOfDumps;\n        }\n\n        public void DumpWithoutReason()\n        {\n            PrintTrace(\"Taking a dump.\");\n            MakeActualDump(IntPtr.Zero);\n        }\n\n        public void DumpOnException(uint threadId, EXCEPTION_RECORD ev)\n        {\n            byte[] threadContext = new byte[Native.CONTEXT_SIZE];\n            bool shouldMakeDump = false;\n\n            using (var target = DataTarget.AttachToProcess(pid, 1000, AttachFlag.Passive))\n            {\n                if (ev.ExceptionCode == BREAKPOINT_CODE)\n                {\n                    return;\n                }\n                if (ev.ExceptionCode == CLRDBG_NOTIFICATION_EXCEPTION_CODE)\n                {\n                    // based on https://social.msdn.microsoft.com/Forums/vstudio/en-US/bca092d4-d2b5-49ef-8bbc-cbce2c67aa89/net-40-firstchance-exception-0x04242420?forum=clr\n                    // it's a \"notification exception\" and can be safely ignored\n                    return;\n                }\n                if (ev.ExceptionCode == CTRL_C_EXCEPTION_CODE)\n                {\n                    // we will also ignore CTRL+C events\n                    return;\n                }\n                // print information about the exception (decode it)\n                ClrException managedException = null;\n                foreach (var clrver in target.ClrVersions)\n                {\n                    var runtime = clrver.CreateRuntime();\n                    var thr = runtime.Threads.FirstOrDefault(t => t.OSThreadId == threadId);\n                    if (thr != null)\n                    {\n                        managedException = thr.CurrentException;\n                        break;\n                    }\n                }\n                var exceptionInfo = string.Format(\"{0:X}.{1} (\\\"{2}\\\")\", ev.ExceptionCode,\n                    managedException != null ? managedException.Type.Name : \"Native\",\n                    managedException != null ? managedException.Message : \"N/A\");\n\n                PrintTrace(\"Exception: \" + exceptionInfo);\n\n                shouldMakeDump = rgxFilter.IsMatch(exceptionInfo);\n\n                if (shouldMakeDump)\n                {\n                    target.DataReader.GetThreadContext(threadId, 0, Native.CONTEXT_SIZE, threadContext);\n                }\n            }\n\n            if (shouldMakeDump)\n            {\n                IntPtr pev = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(EXCEPTION_RECORD)));\n                Marshal.StructureToPtr(new EXCEPTION_RECORD {\n                    ExceptionAddress = ev.ExceptionAddress,\n                    ExceptionFlags = ev.ExceptionFlags,\n                    ExceptionCode = ev.ExceptionCode,\n                    ExceptionRecord = IntPtr.Zero,\n                    NumberParameters = ev.NumberParameters,\n                    ExceptionInformation = ev.ExceptionInformation\n                }, pev, false);\n                var excpointers = new EXCEPTION_POINTERS {\n                    ExceptionRecord = pev,\n                    ContextRecord = threadContext\n                };\n                IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(excpointers));\n                Marshal.StructureToPtr(excpointers, ptr, false);\n                var excinfo = new MINIDUMP_EXCEPTION_INFORMATION() {\n                    ThreadId = threadId,\n                    ClientPointers = false,\n                    ExceptionPointers = ptr\n                };\n                var pexcinfo = Marshal.AllocHGlobal(Marshal.SizeOf(excinfo));\n                Marshal.StructureToPtr(excinfo, pexcinfo, false);\n\n                MakeActualDump(pexcinfo);\n\n                Marshal.FreeHGlobal(pev);\n                Marshal.FreeHGlobal(pexcinfo);\n                Marshal.FreeHGlobal(ptr);\n            }\n        }\n\n        public void DumpOnProcessExit(uint exitCode)\n        {\n            PrintTrace(string.Format(\"Process has terminated.\"));\n            MakeActualDump(IntPtr.Zero);\n        }\n\n        public void PrintDebugString(OUTPUT_DEBUG_STRING_INFO outputDbgStrInfo)\n        {\n            var dbgString = new byte[outputDbgStrInfo.nDebugStringLength];\n\n            uint numberOfBytesRead;\n            var result = ProcessNativeMethod.ReadProcessMemory(hProcess, outputDbgStrInfo.lpDebugStringData, dbgString, outputDbgStrInfo.nDebugStringLength, out numberOfBytesRead);\n\n            if (result)\n            {\n                if (outputDbgStrInfo.fUnicode == 0)\n                {\n                    Console.WriteLine(\"Debug String: {0}\", Encoding.ASCII.GetString(dbgString));\n                }\n                else\n                {\n                    Console.WriteLine(\"Debug String: {0}\", Encoding.Unicode.GetString(dbgString));\n                }\n            }\n        }\n\n        public void DumpOnMemoryCommitThreshold(uint? commitThreshold, uint? commitDrops)\n        {\n            processCommit = GetProcessCommit() / _1MB;\n            if ((commitThreshold.HasValue && processCommit >= commitThreshold.Value) ||\n                (commitDrops.HasValue && processCommit <= commitDrops.Value))\n            {\n                Console.WriteLine(\"Commit {0}MB\", processCommit);\n\n                MakeActualDump(IntPtr.Zero);\n            }\n        }\n\n        private UInt32 GetProcessCommit()\n        {\n            PROCESS_MEMORY_COUNTERS_EX counters;\n            var result = ProcessNativeMethod.GetProcessMemoryInfo(hProcess, out counters, (uint)Marshal.SizeOf<PROCESS_MEMORY_COUNTERS_EX>());\n            Debug.Assert(result);\n            if (!result)\n            {\n                var lastWin32Error = Marshal.GetLastWin32Error();\n                throw new Exception($\"Unable to query process memory info {pid}, error {lastWin32Error:x8}\");\n            }\n            return counters.PrivateUsage.ToUInt32();\n        }\n\n        private void MakeActualDump(IntPtr excinfo)\n        {\n            lock (dumpLock)\n            {\n                if (numberOfDumpsTaken < numberOfDumps)\n                {\n                    var dumper = new DumpWriter.DumpWriter(logger);\n                    var filename = GetDumpFileName();\n\n                    PrintTrace($\"Dump {numberOfDumpsTaken + 1} Dumping process memory to file: {filename}\");\n                    dumper.Dump(pid, dumpType, excinfo, filename, writeAsync, dumpComment);\n\n                    Interlocked.Increment(ref numberOfDumpsTaken);\n                }\n            }\n        }\n\n        string GetDumpFileName()\n        {\n            var bfilename = Path.Combine(dumpFolder, string.Format(\"{0}_{1:yyMMdd_HHmmss}\", processName, DateTime.Now));\n            int cnt = 0;\n\n            var filename = bfilename;\n            while (true)\n            {\n                if (!File.Exists(filename + \".dmp\"))\n                {\n                    break;\n                }\n                cnt++;\n                filename = bfilename + \"_\" + cnt;\n            }\n            return filename + \".dmp\";\n        }\n\n        void PrintTrace(string message)\n        {\n            Console.WriteLine(\"[{0:HH:mm.ss}] {1}\", DateTime.Now, message);\n        }\n\n        public int NumberOfDumpsTaken\n        {\n            get { return numberOfDumpsTaken; }\n        }\n\n        public void Dispose()\n        {\n            hProcess.Dispose();\n        }\n    }\n}\n"
  },
  {
    "path": "MiniDumper/MiniDumper.csproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"14.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <Import Project=\"$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props\" Condition=\"Exists('$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props')\" />\n  <PropertyGroup>\n    <Configuration Condition=\" '$(Configuration)' == '' \">Debug</Configuration>\n    <Platform Condition=\" '$(Platform)' == '' \">AnyCPU</Platform>\n    <ProjectGuid>{8824AA9B-8D64-4C3A-BD50-1742FDA827A5}</ProjectGuid>\n    <OutputType>Exe</OutputType>\n    <AppDesignerFolder>Properties</AppDesignerFolder>\n    <RootNamespace>MiniDumper</RootNamespace>\n    <AssemblyName>MiniDumper</AssemblyName>\n    <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>\n    <FileAlignment>512</FileAlignment>\n    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>\n    <NuGetPackageImportStamp>\n    </NuGetPackageImportStamp>\n    <TargetFrameworkProfile />\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)' == 'Debug|x64'\">\n    <DebugSymbols>true</DebugSymbols>\n    <OutputPath>bin\\x64\\Debug\\</OutputPath>\n    <DefineConstants>TRACE;DEBUG;X64</DefineConstants>\n    <DebugType>full</DebugType>\n    <PlatformTarget>x64</PlatformTarget>\n    <ErrorReport>prompt</ErrorReport>\n    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>\n    <Prefer32Bit>true</Prefer32Bit>\n    <LangVersion>default</LangVersion>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)' == 'Release|x64'\">\n    <OutputPath>bin\\x64\\Release\\</OutputPath>\n    <DefineConstants>TRACE;X64</DefineConstants>\n    <Optimize>true</Optimize>\n    <DebugType>pdbonly</DebugType>\n    <PlatformTarget>x64</PlatformTarget>\n    <ErrorReport>prompt</ErrorReport>\n    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>\n    <Prefer32Bit>true</Prefer32Bit>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)' == 'Debug|x86'\">\n    <DebugSymbols>true</DebugSymbols>\n    <OutputPath>bin\\x86\\Debug\\</OutputPath>\n    <DefineConstants>DEBUG;TRACE</DefineConstants>\n    <DebugType>full</DebugType>\n    <PlatformTarget>x86</PlatformTarget>\n    <ErrorReport>prompt</ErrorReport>\n    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>\n    <Prefer32Bit>true</Prefer32Bit>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)' == 'Release|x86'\">\n    <OutputPath>bin\\x86\\Release\\</OutputPath>\n    <DefineConstants>TRACE</DefineConstants>\n    <Optimize>true</Optimize>\n    <DebugType>pdbonly</DebugType>\n    <PlatformTarget>x86</PlatformTarget>\n    <ErrorReport>prompt</ErrorReport>\n    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>\n    <Prefer32Bit>true</Prefer32Bit>\n  </PropertyGroup>\n  <PropertyGroup>\n    <StartupObject>\n    </StartupObject>\n  </PropertyGroup>\n  <ItemGroup>\n    <Reference Include=\"CommandLine, Version=2.0.275.0, Culture=neutral, PublicKeyToken=de6f01bd326f8c32, processorArchitecture=MSIL\">\n      <HintPath>..\\packages\\CommandLineParser.2.0.275-beta\\lib\\net45\\CommandLine.dll</HintPath>\n      <Private>True</Private>\n    </Reference>\n    <Reference Include=\"Microsoft.Diagnostics.Runtime, Version=1.0.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL\">\n      <HintPath>..\\packages\\Microsoft.Diagnostics.Runtime.1.0.3\\lib\\net45\\Microsoft.Diagnostics.Runtime.dll</HintPath>\n    </Reference>\n    <Reference Include=\"System\" />\n    <Reference Include=\"System.Core\" />\n    <Reference Include=\"System.Xml.Linq\" />\n    <Reference Include=\"System.Data.DataSetExtensions\" />\n    <Reference Include=\"Microsoft.CSharp\" />\n    <Reference Include=\"System.Data\" />\n    <Reference Include=\"System.Net.Http\" />\n    <Reference Include=\"System.Xml\" />\n  </ItemGroup>\n  <ItemGroup>\n    <Compile Include=\"CommandLineOptions.cs\" />\n    <Compile Include=\"MiniDumper.cs\" />\n    <Compile Include=\"Debugger.cs\" />\n    <Compile Include=\"Properties\\AssemblyInfo.cs\" />\n    <Compile Include=\"Win32\\ComPtr.cs\" />\n    <Compile Include=\"Win32\\Contants.cs\" />\n    <Compile Include=\"Win32\\Debugging\\CONTINUE_STATUS.cs\" />\n    <Compile Include=\"Win32\\Debugging\\CREATE_PROCESS_DEBUG_INFO.cs\" />\n    <Compile Include=\"Win32\\Debugging\\CREATE_THREAD_DEBUG_INFO.cs\" />\n    <Compile Include=\"Win32\\Debugging\\DEBUG_EVENT.cs\" />\n    <Compile Include=\"Win32\\Debugging\\DEBUG_EVENT_CODE.cs\" />\n    <Compile Include=\"Win32\\Debugging\\EXCEPTION_DEBUG_INFO.cs\" />\n    <Compile Include=\"Win32\\Debugging\\EXCEPTION_RECORD.cs\" />\n    <Compile Include=\"Win32\\Debugging\\EXIT_PROCESS_DEBUG_INFO.cs\" />\n    <Compile Include=\"Win32\\Debugging\\EXIT_THREAD_DEBUG_INFO.cs\" />\n    <Compile Include=\"Win32\\Debugging\\LOAD_DLL_DEBUG_INFO.cs\" />\n    <Compile Include=\"Win32\\Debugging\\NativeMethods.cs\" />\n    <Compile Include=\"Win32\\Debugging\\OUTPUT_DEBUG_STRING_INFO.cs\" />\n    <Compile Include=\"Win32\\Debugging\\PTHREAD_START_ROUTINE.cs\" />\n    <Compile Include=\"Win32\\Debugging\\RIP_INFO.cs\" />\n    <Compile Include=\"Win32\\Debugging\\UNLOAD_DLL_DEBUG_INFO.cs\" />\n    <Compile Include=\"Win32\\Handles\\NativeMethods.cs\" />\n    <Compile Include=\"Win32\\HResults.cs\" />\n    <Compile Include=\"Win32\\Interop\\SecurityAttributes.cs\" />\n    <Compile Include=\"Win32\\LastWin32ErrorException.cs\" />\n    <Compile Include=\"Win32\\NtStatus.cs\" />\n    <Compile Include=\"Win32\\Processes\\NativeEnums.cs\" />\n    <Compile Include=\"Win32\\Processes\\NativeMethods.cs\" />\n    <Compile Include=\"Win32\\Processes\\NativeStructs.cs\" />\n    <Compile Include=\"Win32\\Processes\\ProcessCreationFlags.cs\" />\n    <Compile Include=\"Win32\\Processes\\PROCESS_INFORMATION.cs\" />\n    <Compile Include=\"Win32\\Processes\\PROCESS_MEMORY_COUNTERS_EX.cs\" />\n    <Compile Include=\"Win32\\Processes\\SafeProcessHandle.cs\" />\n    <Compile Include=\"Win32\\Processes\\SafeThreadHandle.cs\" />\n    <Compile Include=\"Win32\\Processes\\Startupinfo.cs\" />\n    <Compile Include=\"Win32\\UnicodeString.cs\" />\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"App.config\" />\n    <None Include=\"packages.config\" />\n    <None Include=\"Win32\\vschromium-LICENSE\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ProjectReference Include=\"..\\DumpWriter\\DumpWriter.csproj\">\n      <Project>{1c19b4d7-e6a6-4a9a-8495-8231fa167d1c}</Project>\n      <Name>DumpWriter</Name>\n    </ProjectReference>\n  </ItemGroup>\n  <ItemGroup>\n    <Content Include=\"FodyWeavers.xml\">\n      <SubType>Designer</SubType>\n    </Content>\n  </ItemGroup>\n  <Import Project=\"$(MSBuildToolsPath)\\Microsoft.CSharp.targets\" />\n  <Import Project=\"..\\packages\\Fody.1.29.4\\build\\dotnet\\Fody.targets\" Condition=\"Exists('..\\packages\\Fody.1.29.4\\build\\dotnet\\Fody.targets')\" />\n  <Target Name=\"EnsureNuGetPackageBuildImports\" BeforeTargets=\"PrepareForBuild\">\n    <PropertyGroup>\n      <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>\n    </PropertyGroup>\n    <Error Condition=\"!Exists('..\\packages\\Fody.1.29.4\\build\\dotnet\\Fody.targets')\" Text=\"$([System.String]::Format('$(ErrorText)', '..\\packages\\Fody.1.29.4\\build\\dotnet\\Fody.targets'))\" />\n  </Target>\n  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. \n       Other similar extension points exist, see Microsoft.Common.targets.\n  <Target Name=\"BeforeBuild\">\n  </Target>\n  <Target Name=\"AfterBuild\">\n  </Target>\n  -->\n</Project>"
  },
  {
    "path": "MiniDumper/Properties/AssemblyInfo.cs",
    "content": "﻿using System.Reflection;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\n\n// General Information about an assembly is controlled through the following \n// set of attributes. Change these attribute values to modify the information\n// associated with an assembly.\n[assembly: AssemblyTitle(\"MiniDumper\")]\n[assembly: AssemblyDescription(\"\")]\n[assembly: AssemblyConfiguration(\"\")]\n[assembly: AssemblyCompany(\"\")]\n[assembly: AssemblyProduct(\"MiniDumper\")]\n[assembly: AssemblyCopyright(\"Copyright (C) 2018 Sasha Goldshtein, Sebastian Solnica\")]\n[assembly: AssemblyTrademark(\"\")]\n[assembly: AssemblyCulture(\"\")]\n\n// Setting ComVisible to false makes the types in this assembly not visible \n// to COM components.  If you need to access a type in this assembly from \n// COM, set the ComVisible attribute to true on that type.\n[assembly: ComVisible(false)]\n\n// The following GUID is for the ID of the typelib if this project is exposed to COM\n[assembly: Guid(\"8824aa9b-8d64-4c3a-bd50-1742fda827a5\")]\n\n// Version information for an assembly consists of the following four values:\n//\n//      Major Version\n//      Minor Version \n//      Build Number\n//      Revision\n//\n// You can specify all the values or you can default the Build and Revision Numbers \n// by using the '*' as shown below:\n// [assembly: AssemblyVersion(\"1.0.*\")]\n[assembly: AssemblyVersion(\"2.2.0.0\")]\n[assembly: AssemblyFileVersion(\"2.2.0.0\")]\n"
  },
  {
    "path": "MiniDumper/Win32/ComPtr.cs",
    "content": "﻿// Copyright 2014 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nusing System;\nusing System.Diagnostics;\nusing System.Runtime.InteropServices;\n\nnamespace VsChromium.Core.Win32 {\n  public struct ComPtr<T> : IDisposable  where T : class {\n    private T ptr;\n\n    public ComPtr(T ptr) {\n      Debug.Assert(ptr == null || Marshal.IsComObject(ptr));\n      this.ptr = ptr;\n    }\n\n    public T Ptr { get { return ptr; } }\n\n    public void Dispose() {\n      if (ptr != null)\n        Marshal.ReleaseComObject(ptr);\n\n      ptr = null;\n    }\n\n    public T Detach() {\n      T result = ptr;\n      ptr = null;\n      return result;\n    }\n  }\n\n  public static class ComPtr {\n    public static ComPtr<T> Create<T>(T ptr) where T : class {\n      return new ComPtr<T>(ptr);\n    }\n  }\n}\n"
  },
  {
    "path": "MiniDumper/Win32/Contants.cs",
    "content": "namespace VsChromium.Core.Win32 {\n  public static class Contants {\n    public const uint INFINITE = 0xFFFFFFFF;\n  }\n}"
  },
  {
    "path": "MiniDumper/Win32/Debugging/CONTINUE_STATUS.cs",
    "content": "namespace VsChromium.Core.Win32.Debugging {\n  public enum CONTINUE_STATUS : uint {\n    DBG_CONTINUE = 0x00010002,\n    DBG_EXCEPTION_NOT_HANDLED = 0x80010001,\n  }\n}"
  },
  {
    "path": "MiniDumper/Win32/Debugging/CREATE_PROCESS_DEBUG_INFO.cs",
    "content": "using System;\nusing System.Runtime.InteropServices;\n\nnamespace VsChromium.Core.Win32.Debugging {\n  [StructLayout(LayoutKind.Sequential)]\n  public struct CREATE_PROCESS_DEBUG_INFO {\n    public IntPtr hFile;\n    public IntPtr hProcess;\n    public IntPtr hThread;\n    public IntPtr lpBaseOfImage;\n    public uint dwDebugInfoFileOffset;\n    public uint nDebugInfoSize;\n    public IntPtr lpThreadLocalBase;\n    public PTHREAD_START_ROUTINE lpStartAddress;\n    public IntPtr lpImageName;\n    public ushort fUnicode;\n  }\n}"
  },
  {
    "path": "MiniDumper/Win32/Debugging/CREATE_THREAD_DEBUG_INFO.cs",
    "content": "using System;\nusing System.Runtime.InteropServices;\n\nnamespace VsChromium.Core.Win32.Debugging {\n  [StructLayout(LayoutKind.Sequential)]\n  public struct CREATE_THREAD_DEBUG_INFO {\n    public IntPtr hThread;\n    public IntPtr lpThreadLocalBase;\n    public PTHREAD_START_ROUTINE lpStartAddress;\n  }\n}"
  },
  {
    "path": "MiniDumper/Win32/Debugging/DEBUG_EVENT.cs",
    "content": "using System;\nusing System.Runtime.InteropServices;\n\nnamespace VsChromium.Core.Win32.Debugging {\n  [StructLayout(LayoutKind.Sequential)]\n  public struct DEBUG_EVENT {\n    public DEBUG_EVENT_CODE dwDebugEventCode;\n    public int dwProcessId;\n    public int dwThreadId;\n\n    // Note: We need 164 bytes because:\n    // * On x86, offset is 12 and size is 84\n    // * On x64, offset is 16 and size is 160 (so we skip first 4 bytes).\n    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 164, ArraySubType = UnmanagedType.U1)]\n    public byte[] debugInfo;\n\n    public EXCEPTION_DEBUG_INFO Exception {\n      get { return GetDebugInfo<EXCEPTION_DEBUG_INFO>(); }\n    }\n\n    public CREATE_THREAD_DEBUG_INFO CreateThread {\n      get { return GetDebugInfo<CREATE_THREAD_DEBUG_INFO>(); }\n    }\n\n    public CREATE_PROCESS_DEBUG_INFO CreateProcessInfo {\n      get { return GetDebugInfo<CREATE_PROCESS_DEBUG_INFO>(); }\n    }\n\n    public EXIT_THREAD_DEBUG_INFO ExitThread {\n      get { return GetDebugInfo<EXIT_THREAD_DEBUG_INFO>(); }\n    }\n\n    public EXIT_PROCESS_DEBUG_INFO ExitProcess {\n      get { return GetDebugInfo<EXIT_PROCESS_DEBUG_INFO>(); }\n    }\n\n    public LOAD_DLL_DEBUG_INFO LoadDll {\n      get { return GetDebugInfo<LOAD_DLL_DEBUG_INFO>(); }\n    }\n\n    public UNLOAD_DLL_DEBUG_INFO UnloadDll {\n      get { return GetDebugInfo<UNLOAD_DLL_DEBUG_INFO>(); }\n    }\n\n    public OUTPUT_DEBUG_STRING_INFO DebugString {\n      get { return GetDebugInfo<OUTPUT_DEBUG_STRING_INFO>(); }\n    }\n\n    public RIP_INFO RipInfo {\n      get { return GetDebugInfo<RIP_INFO>(); }\n    }\n\n    private T GetDebugInfo<T>() where T : struct {\n      var structSize = Marshal.SizeOf(typeof(T));\n      var pointer = Marshal.AllocHGlobal(structSize);\n      try {\n        // See note above: offset of union is 4 on x64.\n        int offset = IntPtr.Size == 4 ? 0 : 4;\n        Marshal.Copy(debugInfo, offset, pointer, structSize);\n\n        var result = Marshal.PtrToStructure(pointer, typeof(T));\n        return (T)result;\n      }\n      finally {\n        Marshal.FreeHGlobal(pointer);\n      }\n    }\n  }\n}"
  },
  {
    "path": "MiniDumper/Win32/Debugging/DEBUG_EVENT_CODE.cs",
    "content": "namespace VsChromium.Core.Win32.Debugging {\n  public enum DEBUG_EVENT_CODE : uint {\n    EXCEPTION_DEBUG_EVENT = 1,\n    CREATE_THREAD_DEBUG_EVENT = 2,\n    CREATE_PROCESS_DEBUG_EVENT = 3,\n    EXIT_THREAD_DEBUG_EVENT = 4,\n    EXIT_PROCESS_DEBUG_EVENT = 5,\n    LOAD_DLL_DEBUG_EVENT = 6,\n    UNLOAD_DLL_DEBUG_EVENT = 7,\n    OUTPUT_DEBUG_STRING_EVENT = 8,\n    RIP_EVENT = 9,\n  }\n}"
  },
  {
    "path": "MiniDumper/Win32/Debugging/EXCEPTION_DEBUG_INFO.cs",
    "content": "using System.Runtime.InteropServices;\n\nnamespace VsChromium.Core.Win32.Debugging {\n  [StructLayout(LayoutKind.Sequential)]\n  public struct EXCEPTION_DEBUG_INFO {\n    public EXCEPTION_RECORD ExceptionRecord;\n    public uint dwFirstChance;\n  }\n}"
  },
  {
    "path": "MiniDumper/Win32/Debugging/EXCEPTION_RECORD.cs",
    "content": "using System;\nusing System.Runtime.InteropServices;\n\nnamespace VsChromium.Core.Win32.Debugging\n{\n    [StructLayout(LayoutKind.Sequential)]\n    public struct EXCEPTION_RECORD\n    {\n        public UInt32 ExceptionCode;\n        public UInt32 ExceptionFlags;\n        public IntPtr ExceptionRecord;\n        public IntPtr ExceptionAddress;\n        public UInt32 NumberParameters;\n#if X64\n        public UInt32 __unusedAlignment;\n#endif\n#if X64\n        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 15, ArraySubType = UnmanagedType.U8)]\n        public UInt64[] ExceptionInformation;\n#else\n        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 15, ArraySubType = UnmanagedType.U4)]\n        public uint[] ExceptionInformation;\n#endif\n    }\n}"
  },
  {
    "path": "MiniDumper/Win32/Debugging/EXIT_PROCESS_DEBUG_INFO.cs",
    "content": "using System.Runtime.InteropServices;\n\nnamespace VsChromium.Core.Win32.Debugging {\n  [StructLayout(LayoutKind.Sequential)]\n  public struct EXIT_PROCESS_DEBUG_INFO {\n    public uint dwExitCode;\n  }\n}"
  },
  {
    "path": "MiniDumper/Win32/Debugging/EXIT_THREAD_DEBUG_INFO.cs",
    "content": "using System.Runtime.InteropServices;\n\nnamespace VsChromium.Core.Win32.Debugging {\n  [StructLayout(LayoutKind.Sequential)]\n  public struct EXIT_THREAD_DEBUG_INFO {\n    public uint dwExitCode;\n  }\n}"
  },
  {
    "path": "MiniDumper/Win32/Debugging/LOAD_DLL_DEBUG_INFO.cs",
    "content": "using System;\nusing System.Runtime.InteropServices;\n\nnamespace VsChromium.Core.Win32.Debugging {\n  [StructLayout(LayoutKind.Sequential)]\n  public struct LOAD_DLL_DEBUG_INFO {\n    public IntPtr hFile;\n    public IntPtr lpBaseOfDll;\n    public uint dwDebugInfoFileOffset;\n    public uint nDebugInfoSize;\n    public IntPtr lpImageName;\n    public ushort fUnicode;\n  }\n}"
  },
  {
    "path": "MiniDumper/Win32/Debugging/NativeMethods.cs",
    "content": "﻿// Copyright 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nusing System.Runtime.InteropServices;\n\nnamespace VsChromium.Core.Win32.Debugging {\n  public static class NativeMethods {\n    [DllImport(\"kernel32.dll\", SetLastError = true)]\n    public static extern bool DebugActiveProcess(int processId);\n\n    [DllImport(\"kernel32.dll\", SetLastError = true)]\n    public static extern bool DebugActiveProcessStop(int processId);\n\n    [DllImport(\"kernel32.dll\", SetLastError = true)]\n    public static extern bool WaitForDebugEvent(out DEBUG_EVENT debugEvent, uint timeout);\n\n    [DllImport(\"kernel32.dll\", SetLastError = true)]\n    public static extern bool ContinueDebugEvent(int processId, int threadId, CONTINUE_STATUS continuteStatus);\n\n    [DllImport(\"kernel32.dll\", CallingConvention = CallingConvention.Winapi, SetLastError = true)]\n    [return: MarshalAs(UnmanagedType.Bool)]\n    public static extern bool DebugSetProcessKillOnExit([In] bool flag);\n  }\n}\n"
  },
  {
    "path": "MiniDumper/Win32/Debugging/OUTPUT_DEBUG_STRING_INFO.cs",
    "content": "using System;\nusing System.Runtime.InteropServices;\n\nnamespace VsChromium.Core.Win32.Debugging {\n  [StructLayout(LayoutKind.Sequential)]\n  public struct OUTPUT_DEBUG_STRING_INFO {\n    /// <summary>\n    /// The debugging string in the calling process's address space. The\n    /// debugger can use the ReadProcessMemory function to retrieve the value of\n    /// the string.\n    /// </summary>\n    public IntPtr lpDebugStringData;\n    /// <summary>\n    /// The format of the debugging string. If this member is zero, the debugging\n    /// string is ANSI; if it is nonzero, the string is Unicode.\n    /// </summary>\n    public ushort fUnicode;\n    /// <summary>\n    /// The size of the debugging string, in characters. The length includes the\n    /// string's terminating null character.\n    /// </summary>\n    public ushort nDebugStringLength;\n  }\n}"
  },
  {
    "path": "MiniDumper/Win32/Debugging/PTHREAD_START_ROUTINE.cs",
    "content": "﻿// Copyright 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nusing System;\n\nnamespace VsChromium.Core.Win32.Debugging {\n  public delegate uint PTHREAD_START_ROUTINE(IntPtr lpThreadParameter);\n}\n"
  },
  {
    "path": "MiniDumper/Win32/Debugging/RIP_INFO.cs",
    "content": "using System.Runtime.InteropServices;\n\nnamespace VsChromium.Core.Win32.Debugging {\n  [StructLayout(LayoutKind.Sequential)]\n  public struct RIP_INFO {\n    public uint dwError;\n    public uint dwType;\n  }\n}"
  },
  {
    "path": "MiniDumper/Win32/Debugging/UNLOAD_DLL_DEBUG_INFO.cs",
    "content": "using System;\nusing System.Runtime.InteropServices;\n\nnamespace VsChromium.Core.Win32.Debugging {\n  [StructLayout(LayoutKind.Sequential)]\n  public struct UNLOAD_DLL_DEBUG_INFO {\n    public IntPtr lpBaseOfDll;\n  }\n}"
  },
  {
    "path": "MiniDumper/Win32/HResults.cs",
    "content": "namespace VsChromium.Core.Win32 {\n  public static class HResults {\n    public const int HR_ERROR_SEM_TIMEOUT = unchecked((int)0x80070079);\n    public const int HR_ERROR_NOT_SUPPORTED = unchecked((int)0x80070032);\n  }\n}"
  },
  {
    "path": "MiniDumper/Win32/Handles/NativeMethods.cs",
    "content": "﻿// Copyright 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nusing System;\nusing System.Runtime.InteropServices;\nusing Microsoft.Win32.SafeHandles;\n\nnamespace VsChromium.Core.Win32.Handles {\n  static class NativeMethods {\n    public static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);\n\n    [DllImport(\"kernel32.dll\", CharSet = CharSet.Auto, ExactSpelling = true, SetLastError = true)]\n    public static extern bool CloseHandle(IntPtr handle);\n\n    [DllImport(\"kernel32.dll\", CharSet = CharSet.Ansi, SetLastError = true)]\n    public static extern IntPtr GetStdHandle(int whichHandle);\n\n    [DllImport(\"kernel32.dll\", BestFitMapping = false, CharSet = CharSet.Ansi, SetLastError = true)]\n    public static extern bool DuplicateHandle(\n      HandleRef hSourceProcessHandle,\n      SafeHandle hSourceHandle,\n      HandleRef hTargetProcess,\n      out SafeFileHandle targetHandle,\n      int dwDesiredAccess,\n      bool bInheritHandle,\n      int dwOptions);\n  }\n}\n"
  },
  {
    "path": "MiniDumper/Win32/Interop/SecurityAttributes.cs",
    "content": "// Copyright 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nusing System;\nusing System.Runtime.InteropServices;\n\nnamespace VsChromium.Core.Win32.Interop\n{\n    [StructLayout(LayoutKind.Sequential)]\n    public class SecurityAttributes\n    {\n        public int nLength;\n        public IntPtr lpSecurityDescriptor;\n        public int bInheritHandle;\n    }\n}\n"
  },
  {
    "path": "MiniDumper/Win32/LastWin32ErrorException.cs",
    "content": "﻿// Copyright 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nusing System.ComponentModel;\nusing System.Runtime.InteropServices;\n\nnamespace VsChromium.Core.Win32 {\n  public class LastWin32ErrorException : Win32Exception {\n    public LastWin32ErrorException()\n      : base(Marshal.GetLastWin32Error()) {\n    }\n    public LastWin32ErrorException(string message)\n      : this(Marshal.GetLastWin32Error(), message) {\n    }\n    public LastWin32ErrorException(int errorCode)\n      : base(errorCode) {\n    }\n    public LastWin32ErrorException(int errorCode, string message)\n      : base(errorCode, string.Format(\"{0}: {1}\", message, new Win32Exception(errorCode).Message)) {\n    }\n  }\n}\n"
  },
  {
    "path": "MiniDumper/Win32/NtStatus.cs",
    "content": "﻿// Copyright 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nnamespace VsChromium.Core.Win32 {\n  public static class NtStatus {\n    public const int Success = 0;\n  }\n}"
  },
  {
    "path": "MiniDumper/Win32/Processes/NativeEnums.cs",
    "content": "﻿// Copyright 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nusing System;\n\nnamespace VsChromium.Core.Win32.Processes {\n  // The target architecture of a given executable image.  The various values correspond\n  // to the magic numbers defined by the PE Executable Image File Format.\n  // http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx\n  public enum MachineType : ushort {\n    Unknown = 0x0,\n    X64 = 0x8664,\n    X86 = 0x14c,\n    Ia64 = 0x200\n  }\n\n  // A flag indicating the format of the path string that Windows returns from a call to\n  // QueryFullProcessImageName().\n  public enum ProcessQueryImageNameMode : uint {\n    Win32 = 0,\n    NativeSystemFormat = 1\n  }\n\n  // Flags indicating the level of permission requested when opening a handle to an external\n  // process.  Used by OpenProcess().\n  [Flags]\n  public enum ProcessAccessFlags : uint {\n    None = 0x0,\n    All = 0x001F0FFF,\n    VmOperation = 0x00000008,\n    VmRead = 0x00000010,\n    QueryInformation = 0x00000400,\n    QueryLimitedInformation = 0x00001000\n  }\n\n  // Determines the amount of information requested (and hence the type of structure returned)\n  // by a call to NtQueryInformationProcess.\n  public enum ProcessInfoClass : int {\n    BasicInformation = 0\n  };\n\n  [Flags]\n  public enum SHGFI : uint {\n    Icon = 0x000000100,\n    DisplayName = 0x000000200,\n    TypeName = 0x000000400,\n    Attributes = 0x000000800,\n    IconLocation = 0x000001000,\n    ExeType = 0x000002000,\n    SysIconIndex = 0x000004000,\n    LinkOverlay = 0x000008000,\n    Selected = 0x000010000,\n    Attr_Specified = 0x000020000,\n    LargeIcon = 0x000000000,\n    SmallIcon = 0x000000001,\n    OpenIcon = 0x000000002,\n    ShellIconSize = 0x000000004,\n    PIDL = 0x000000008,\n    UseFileAttributes = 0x000000010,\n    AddOverlays = 0x000000020,\n    OverlayIndex = 0x000000040,\n  }\n}\n"
  },
  {
    "path": "MiniDumper/Win32/Processes/NativeMethods.cs",
    "content": "﻿// Copyright 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nusing MiniDumper.Win32.Processes;\nusing System;\nusing System.Runtime.InteropServices;\nusing System.Text;\nusing VsChromium.Core.Win32.Interop;\n\nnamespace VsChromium.Core.Win32.Processes\n{\n    static class NativeMethods\n    {\n        [DllImport(\"shell32.dll\", SetLastError = true)]\n        public static extern IntPtr CommandLineToArgvW(\n          [MarshalAs(UnmanagedType.LPWStr)] string lpCmdLine,\n          out int pNumArgs);\n\n        [DllImport(\"kernel32.dll\", CharSet = CharSet.Ansi, SetLastError = true)]\n        public static extern IntPtr GetCurrentProcess();\n\n        [DllImport(\"kernel32.dll\", BestFitMapping = false, CharSet = CharSet.Auto, SetLastError = true)]\n        public static extern bool CreateProcess(\n          [MarshalAs(UnmanagedType.LPTStr)] string lpApplicationName,\n          StringBuilder lpCommandLine,\n          SecurityAttributes lpProcessAttributes,\n          SecurityAttributes lpThreadAttributes,\n          bool bInheritHandles,\n          ProcessCreationFlags dwCreationFlags,\n          IntPtr lpEnvironment,\n          [MarshalAs(UnmanagedType.LPTStr)] string lpCurrentDirectory,\n          STARTUPINFO lpStartupInfo,\n          [In, Out]\n      PROCESS_INFORMATION lpProcessInformation);\n\n        [DllImport(\"ntdll.dll\", SetLastError = true)]\n        public static extern int NtReadVirtualMemory(\n            SafeProcessHandle hProcess,\n            IntPtr baseAddress,\n            [Out] byte[] buffer,\n            uint size,\n            out uint lpNumberOfBytesRead);\n\n        [DllImport(\"ntdll.dll\", SetLastError = true)]\n        public static extern int NtWow64ReadVirtualMemory64(\n            SafeProcessHandle hProcess,\n            ulong baseAddress,\n            IntPtr buffer,\n            ulong bufferSize,\n            out ulong lpNumberOfBytesRead);\n\n        [DllImport(\"kernel32.dll\", SetLastError = true)]\n        public static extern SafeProcessHandle OpenProcess(\n          [MarshalAs(UnmanagedType.U4)] ProcessAccessFlags dwDesiredAccess,\n          [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle,\n          int dwProcessId);\n\n        [DllImport(\"kernel32.dll\", SetLastError = true, CallingConvention = CallingConvention.StdCall,\n          CharSet = CharSet.Unicode)]\n        public static extern uint QueryFullProcessImageName(\n          SafeProcessHandle hProcess,\n          [MarshalAs(UnmanagedType.U4)] ProcessQueryImageNameMode flags,\n          [Out] StringBuilder lpImageName, ref int size);\n\n        [DllImport(\"kernel32.dll\", SetLastError = true)]\n        [return: MarshalAs(UnmanagedType.Bool)]\n        public static extern bool ReadProcessMemory(SafeProcessHandle hProcess, IntPtr lpBaseAddress,\n          [Out] byte[] buffer, uint size, out UInt32 lpNumberOfBytesRead);\n\n        [DllImport(\"ntdll.dll\", SetLastError = true)]\n        public static extern int NtQueryInformationProcess(SafeProcessHandle hProcess, ProcessInfoClass pic, ref ProcessBasicInformation pbi, int cb, out int pSize);\n\n        [DllImport(\"ntdll.dll\", SetLastError = true)]\n        public static extern int NtWow64QueryInformationProcess64(SafeProcessHandle hProcess, ProcessInfoClass pic, ref ProcessBasicInformationWow64 pbi, int cb, out int pSize);\n\n        [DllImport(\"psapi.dll\", SetLastError = true)]\n       public static extern bool GetProcessMemoryInfo(SafeProcessHandle hProcess, out PROCESS_MEMORY_COUNTERS_EX counters, uint size);\n        \n    }    \n}\n"
  },
  {
    "path": "MiniDumper/Win32/Processes/NativeStructs.cs",
    "content": "﻿// Copyright 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nusing System;\nusing System.Runtime.InteropServices;\n\nnamespace VsChromium.Core.Win32.Processes {\n  // In general, for all structures below which contains a pointer (represented here by IntPtr),\n  // the pointers refer to memory in the address space of the process from which the original\n  // structure was read.  While this seems obvious, it means we cannot provide an elegant\n  // interface to the various fields in the structure due to the de-reference requiring a\n  // handle to the target process.  Instead, that functionality needs to be provided at a\n  // higher level.\n  //\n  // Additionally, since we usually explicitly define the fields that we're interested in along\n  // with their respective offsets, we frequently specify the exact size of the native structure.\n\n  // Win32 RTL_USER_PROCESS_PARAMETERS structure.\n  [StructLayout(LayoutKind.Sequential, Pack=1)]\n  public struct RtlUserProcessParameters {\n    private uint maximumLength;\n    private uint length;\n    private uint flags;\n    private uint debugFlags;\n    private IntPtr consoleHandle;\n    private uint consoleFlags;\n    private IntPtr stdInputHandle;\n    private IntPtr stdOutputHandle;\n    private IntPtr stdErrorHandle;\n    private UnicodeString currentDirectoryPath;\n    private IntPtr currentDirectoryHandle;\n    private UnicodeString dllPath;\n    private UnicodeString imagePathName;\n    private UnicodeString commandLine;\n\n    public UnicodeString CommandLine { get { return commandLine; } }\n  };\n\n  // Win32 RTL_USER_PROCESS_PARAMETERS structure.\n  [StructLayout(LayoutKind.Sequential, Pack = 1)]\n  public struct RtlUserProcessParametersWow64 {\n    private uint maximumLength;\n    private uint length;\n    private uint flags;\n    private uint debugFlags;\n    private ulong consoleHandle;\n    private uint consoleFlags;\n    private uint padding;\n    private ulong stdInputHandle;\n    private ulong stdOutputHandle;\n    private ulong stdErrorHandle;\n    private UnicodeStringWow64 currentDirectoryPath;\n    private ulong currentDirectoryHandle;\n    private UnicodeStringWow64 dllPath;\n    private UnicodeStringWow64 imagePathName;\n    private UnicodeStringWow64 commandLine;\n\n    public UnicodeStringWow64 CommandLine { get { return commandLine; } }\n  };\n\n  // Win32 PEB structure.  Represents the process environment block of a process.\n  [StructLayout(LayoutKind.Sequential, Pack = 1)]\n  public struct Peb {\n    private byte inheritedAddressSpace;\n    private byte readImageFileExecutionOptions;\n    private byte isBeingDebugged;\n    private byte reserved;\n    private IntPtr mutant;\n    private IntPtr imageBaseAddress;\n    private IntPtr loaderData;\n    private IntPtr processParameters;\n\n    public bool IsBeingDebugged { get { return !(isBeingDebugged == 0); } }\n    public IntPtr ProcessParameters { get { return processParameters; } }\n  };\n\n  // Win32 PEB structure.  Represents the process environment block of a process.\n  [StructLayout(LayoutKind.Sequential, Pack = 1)]\n  public struct PebWow64 {\n    private byte inheritedAddressSpace;\n    private byte readImageFileExecutionOptions;\n    private byte isBeingDebugged;\n    private byte reserved;\n    private uint padding;\n    private ulong mutant;\n    private ulong imageBaseAddress;\n    private ulong loaderData;\n    private ulong processParameters;\n\n    public bool IsBeingDebugged { get { return !(isBeingDebugged == 0); } }\n    public ulong ProcessParameters { get { return processParameters; } }\n  };\n  // Win32 PROCESS_BASIC_INFORMATION.  Contains a pointer to the PEB, and various other\n  // information about a process.\n  [StructLayout(LayoutKind.Sequential, Pack = 1)]\n  public struct ProcessBasicInformation {\n    private IntPtr reserved;\n    private IntPtr pebBaseAddress;\n    private IntPtr reserved2;\n    private IntPtr reserved3;\n    private UIntPtr uniqueProcessId;\n    private IntPtr parentProcessId;\n\n    public IntPtr PebBaseAddress { get { return pebBaseAddress; } }\n    public UIntPtr UniqueProcessId { get { return uniqueProcessId; } }\n    public IntPtr ParentProcessId { get { return parentProcessId; } }\n  }\n\n  // Win32 PROCESS_BASIC_INFORMATION.  Contains a pointer to the PEB, and various other\n  // information about a process.\n  [StructLayout(LayoutKind.Sequential, Pack = 1)]\n  public struct ProcessBasicInformationWow64 {\n    private ulong reserved;\n    private ulong pebBaseAddress;\n    private ulong reserved2;\n    private ulong reserved3;\n    private ulong uniqueProcessId;\n    private ulong parentProcessId;\n\n    public ulong PebBaseAddress { get { return pebBaseAddress; } }\n    public ulong UniqueProcessId { get { return uniqueProcessId; } }\n    public ulong ParentProcessId { get { return parentProcessId; } }\n  }\n}\n"
  },
  {
    "path": "MiniDumper/Win32/Processes/PROCESS_INFORMATION.cs",
    "content": "// Copyright 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nusing System;\nusing System.Runtime.InteropServices;\n\nnamespace VsChromium.Core.Win32.Processes {\n  [StructLayout(LayoutKind.Sequential)]\n  public class PROCESS_INFORMATION {\n    /// <summary>\n    /// Handle to the created process. The caller *must* call CloseHandle to avoid leaks.\n    /// </summary>\n    public IntPtr hProcess;\n    /// <summary>\n    /// Handle to the created process main thread. The caller *must* call CloseHandle to avoid leaks.\n    /// </summary>\n    public IntPtr hThread;\n    public int dwProcessId;\n    public int dwThreadId;\n  }\n}\n"
  },
  {
    "path": "MiniDumper/Win32/Processes/PROCESS_MEMORY_COUNTERS_EX.cs",
    "content": "﻿using System;\nusing System.Runtime.InteropServices;\n\nnamespace MiniDumper.Win32.Processes\n{\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct PROCESS_MEMORY_COUNTERS_EX\n    {\n        public uint cb;\n        public uint PageFaultCount;\n        public UIntPtr PeakWorkingSetSize;\n        public UIntPtr WorkingSetSize;\n        public UIntPtr QuotaPeakPagedPoolUsage;\n        public UIntPtr QuotaPagedPoolUsage;\n        public UIntPtr QuotaPeakNonPagedPoolUsage;\n        public UIntPtr QuotaNonPagedPoolUsage;\n        public UIntPtr PagefileUsage;\n        public UIntPtr PeakPagefileUsage;\n        public UIntPtr PrivateUsage;\n    }\n}\n"
  },
  {
    "path": "MiniDumper/Win32/Processes/ProcessCreationFlags.cs",
    "content": "// Copyright 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nusing System;\n\nnamespace VsChromium.Core.Win32.Processes {\n  [Flags]\n  public enum ProcessCreationFlags : int {\n    /// <summary>\n    /// The calling thread starts and debugs the new process and all child\n    /// processes created by the new process. It can receive all related debug\n    /// events using the WaitForDebugEvent function. A process that uses\n    /// DEBUG_PROCESS becomes the root of a debugging chain. This continues\n    /// until another process in the chain is created with DEBUG_PROCESS. If\n    /// this flag is combined with DEBUG_ONLY_THIS_PROCESS, the caller debugs\n    /// only the new process, not any child processes.\n    /// </summary>\n    DEBUG_PROCESS = 0x00000001,\n    /// <summary>\n    /// The calling thread starts and debugs the new process. It can receive all\n    /// related debug events using the WaitForDebugEvent function.\n    /// </summary>\n    DEBUG_ONLY_THIS_PROCESS = 0x00000002,\n    /// <summary>\n    /// The child processes of a process associated with a job are not\n    /// associated with the job. If the calling process is not associated with a\n    /// job, this constant has no effect. If the calling process is associated\n    /// with a job, the job must set the JOB_OBJECT_LIMIT_BREAKAWAY_OK limit.\n    /// </summary>\n    CREATE_BREAKAWAY_FROM_JOB = 0x01000000,\n    /// <summary>\n    /// The process is a console application that is being run without a console\n    /// window. Therefore, the console handle for the application is not set.\n    /// This flag is ignored if the application is not a console application, or\n    /// if it is used with either CREATE_NEW_CONSOLE or DETACHED_PROCESS.\n    /// </summary>\n    CREATE_NO_WINDOW = 0x08000000,\n    /// <summary>\n    /// The primary thread of the new process is created in a suspended state,\n    /// and does not run until the ResumeThread function is called.\n    CREATE_SUSPENDED = 0x00000004,\n    /// <summary>\n    /// The new process has a new console, instead of inheriting its parent's console (the default). \n    /// \n    /// This flag cannot be used with DETACHED_PROCESS.\n    /// </summary>\n    CREATE_NEW_CONSOLE = 0x00000010,\n    /// <summary>\n    /// If this flag is set, the environment block pointed to by lpEnvironment uses Unicode characters. \n    /// Otherwise, the environment block uses ANSI characters.\n    /// </summary>\n    CREATE_UNICODE_ENVIRONMENT = 0x00000400\n  }\n}\n"
  },
  {
    "path": "MiniDumper/Win32/Processes/SafeProcessHandle.cs",
    "content": "﻿// Copyright 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nusing System;\nusing Microsoft.Win32.SafeHandles;\n\nnamespace VsChromium.Core.Win32.Processes {\n  public sealed class SafeProcessHandle : SafeHandleZeroOrMinusOneIsInvalid {\n    public SafeProcessHandle()\n      : base(true) {\n    }\n\n    public SafeProcessHandle(IntPtr handle)\n      : base(true) {\n      base.SetHandle(handle);\n    }\n\n    public void InitialSetHandle(IntPtr handlePtr) {\n      handle = handlePtr;\n    }\n\n    protected override bool ReleaseHandle() {\n      return Handles.NativeMethods.CloseHandle(handle);\n    }\n  }\n}\n"
  },
  {
    "path": "MiniDumper/Win32/Processes/SafeThreadHandle.cs",
    "content": "﻿// Copyright 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nusing System;\nusing Microsoft.Win32.SafeHandles;\n\nnamespace VsChromium.Core.Win32.Processes {\n  public sealed class SafeThreadHandle : SafeHandleZeroOrMinusOneIsInvalid {\n    public SafeThreadHandle()\n      : base(true) {\n    }\n\n    public SafeThreadHandle(IntPtr handle)\n      : base(true) {\n      base.SetHandle(handle);\n    }\n\n    public void InitialSetHandle(IntPtr h) {\n      base.SetHandle(h);\n    }\n\n    protected override bool ReleaseHandle() {\n      return Handles.NativeMethods.CloseHandle(handle);\n    }\n  }\n}\n"
  },
  {
    "path": "MiniDumper/Win32/Processes/Startupinfo.cs",
    "content": "// Copyright 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nusing System;\nusing System.Runtime.InteropServices;\nusing Microsoft.Win32.SafeHandles;\n\nnamespace VsChromium.Core.Win32.Processes {\n  [StructLayout(LayoutKind.Sequential)]\n  public class STARTUPINFO : IDisposable {\n    public int cb;\n    public IntPtr lpReserved = IntPtr.Zero;\n    public IntPtr lpDesktop = IntPtr.Zero;\n    public IntPtr lpTitle = IntPtr.Zero;\n    public int dwX;\n    public int dwY;\n    public int dwXSize;\n    public int dwYSize;\n    public int dwXCountChars;\n    public int dwYCountChars;\n    public int dwFillAttribute;\n    public int dwFlags;\n    public short wShowWindow;\n    public short cbReserved2;\n    public IntPtr lpReserved2 = IntPtr.Zero;\n    public SafeFileHandle hStdInput = new SafeFileHandle(IntPtr.Zero, false);\n    public SafeFileHandle hStdOutput = new SafeFileHandle(IntPtr.Zero, false);\n    public SafeFileHandle hStdError = new SafeFileHandle(IntPtr.Zero, false);\n\n    public STARTUPINFO() {\n      cb = Marshal.SizeOf(this);\n    }\n\n    public void Dispose() {\n      if (hStdInput != null && !hStdInput.IsInvalid) {\n        hStdInput.Close();\n        hStdInput = null;\n      }\n      if (hStdOutput != null && !hStdOutput.IsInvalid) {\n        hStdOutput.Close();\n        hStdOutput = null;\n      }\n      if (hStdError != null && !hStdError.IsInvalid) {\n        hStdError.Close();\n        hStdError = null;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "MiniDumper/Win32/UnicodeString.cs",
    "content": "﻿// Copyright 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nusing System;\nusing System.Runtime.InteropServices;\n\nnamespace VsChromium.Core.Win32 {\n  // Win32 UNICODE_STRING structure.\n  [StructLayout(LayoutKind.Sequential, Pack=1)]\n  public struct UnicodeString {\n    // The length in bytes of the string pointed to by buffer, not including the null-terminator.\n    private ushort length;\n    // The total allocated size in memory pointed to by buffer.\n    private ushort maximumLength;\n    // A pointer to the buffer containing the string data.\n    private IntPtr buffer;\n\n    public ushort Length { get { return length; } }\n    public ushort MaximumLength { get { return maximumLength; } }\n    public IntPtr Buffer { get { return buffer; } }\n  }\n\n  [StructLayout(LayoutKind.Sequential, Pack = 1)] \n  public struct UnicodeStringWow64 {\n    // The length in bytes of the string pointed to by buffer, not including the null-terminator.\n    private ushort length;\n    // The total allocated size in memory pointed to by buffer.\n    private ushort maximumLength;\n\n    // 4 bytes of padding.\n    private uint padding;\n\n    // A 64-bit pointer to the buffer containing the string data.\n    private ulong buffer;\n\n    public ushort Length { get { return length; } }\n    public ushort MaximumLength { get { return maximumLength; } }\n    public ulong Buffer { get { return buffer; } }\n  }\n}\n"
  },
  {
    "path": "MiniDumper/Win32/vschromium-LICENSE",
    "content": "Copyright 2013 The Chromium Authors. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n   * Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n   * Redistributions in binary form must reproduce the above\ncopyright notice, this list of conditions and the following disclaimer\nin the documentation and/or other materials provided with the\ndistribution.\n   * Neither the name of Google Inc. nor the names of its\ncontributors may be used to endorse or promote products derived from\nthis software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "MiniDumper/packages.config",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<packages>\n  <package id=\"CommandLineParser\" version=\"2.0.275-beta\" targetFramework=\"net46\" />\n  <package id=\"Costura.Fody\" version=\"1.3.3.0\" targetFramework=\"net461\" developmentDependency=\"true\" />\n  <package id=\"Fody\" version=\"1.29.4\" targetFramework=\"net45\" developmentDependency=\"true\" />\n  <package id=\"Microsoft.Diagnostics.Runtime\" version=\"1.0.3\" targetFramework=\"net452\" />\n</packages>"
  },
  {
    "path": "README.md",
    "content": "### Minidumper\n\nMinidumper is a command-line tool that can capture dump files of .NET processes in three modes: **minimal**, which is enough just for basic triage; **heap**, which includes managed heap information and other data required to diagnose more intricate .NET issues; and **full**, which creates a complete dump file.\n\nWhat makes Minidumper interesting is the **heap** mode. For large applications, especially with a lot of modules or when unmanaged memory and code are involved, dumps generated by the **heap** mode can be 5x or 10x smaller than full memory dumps, but will still allow complete investigation of many .NET issues by tools like Visual Studio and WinDbg (SOS).\n\nHead over to the [releases](https://github.com/goldshtn/minidumper/releases) section to download precompiled binaries if that's your thing.\n\n### DumpWriter\n\nAlso included is a stand-alone library (DumpWriter) that can be added to any project to capture dumps of arbitrary processes. The DumpWriter project also contains the full interop signatures for the Win32 `MiniDumpWriteDump` API and all associated data structures, including callback input and output structures.\n\n> #### NOTES\n> * To create dumps of 32-bit processes, make sure to use the 32-bit version of the application -- and vice versa for 64-bit.\n> * MiniDumper has gone through very minimal testing. Although it is unlikely that it will cause any damage to the target process (if dump generation fails, MiniDumper exits and the target continues running), but YMMV.\n> * The `--async` option will not necessarily speed up dump generation if you are using a fast disk.\n\n### Usage\n\nThe command line options resemble those from procdump (not all features are yet implemented) so if you are familiar with that tool you should find yourself easily in minidumper.\n\n```\n  -m              Required. Create a dump file, second paramer:\n    -mm\n                  minidump enough to diagnose crashes and display call\n                  stacks.\n    -mh dump file with the CLR heap, but without\n                  module code or unmanaged memory contents\n    -ma complete\n                  dump file with the full memory address space\n\n  --async         Write dump chunks to disk asynchronously. Reduces process\n                  suspension time at the expense of higher memory usage.\n\n  -e              Write a dump when the process encounters an unhandled\n                  exception. Include the 1 to create dump on first chance\n                  exceptions, include the 2 to create dump on second chance\n                  exceptions.\n\n  -l              Display the debug logging of the process + diagnostics info\n                  from the minidumper.\n\n  --maxmem        Memory commit threshold in MB at which to create a dump.\n\n  --minmem        Trigger when memory commit drops below specified MB value.\n\n  -f              Filter on the content of exceptions and debug logging.\n                  Wildcards (*) are supported.\n\n  -x              Launch the specified image with optional arguments.\n\n  -n              (Default: 1) Number of dumps to write before exiting.\n\n  -t              Write a dump when the process terminates.\n\n  -c              Start the process in a new console window.\n\n  --help          Display this help screen.\n\n  --version       Display version information.\n\n  value pos. 0    Required. PID or process name\n\n  value pos. 0    Arguments for the process to start\n```\n\n### Articles about minidumper\n\n- [Minidumper - a better way to create managed memory dumps](http://www.codeproject.com/Articles/1102423/Minidumper-a-better-way-to-create-managed-memory-d)\n- [Creating Smaller, But Still Usable, Dumps of .NET Applications](http://blogs.microsoft.co.il/sasha/2015/08/19/minidumper-smaller-dumps-net-applications/)\n- [More on MiniDumper: Getting the Right Memory Pages for .NET Analysis](http://blogs.microsoft.co.il/sasha/2015/09/30/more-on-minidumper-getting-the-right-memory-pages-for-net-analysis/)\n- [New features coming to minidumper](https://lowleveldesign.wordpress.com/2015/12/21/new-features-coming-to-minidumper)\n"
  },
  {
    "path": "minidumper.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 14\nVisualStudioVersion = 14.0.24720.0\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"Solution Items\", \"Solution Items\", \"{A82A1C60-8298-42E3-9AFE-C0B37391952C}\"\n\tProjectSection(SolutionItems) = preProject\n\t\t.nuget\\NuGet.Config = .nuget\\NuGet.Config\n\t\t.nuget\\NuGet.exe = .nuget\\NuGet.exe\n\t\t.nuget\\NuGet.targets = .nuget\\NuGet.targets\n\tEndProjectSection\nEndProject\nProject(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"MiniDumper\", \"MiniDumper\\MiniDumper.csproj\", \"{8824AA9B-8D64-4C3A-BD50-1742FDA827A5}\"\nEndProject\nProject(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"DumpWriter\", \"DumpWriter\\DumpWriter.csproj\", \"{1C19B4D7-E6A6-4A9A-8495-8231FA167D1C}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|Any CPU = Debug|Any CPU\n\t\tDebug|x64 = Debug|x64\n\t\tDebug|x86 = Debug|x86\n\t\tRelease|Any CPU = Release|Any CPU\n\t\tRelease|x64 = Release|x64\n\t\tRelease|x86 = Release|x86\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{8824AA9B-8D64-4C3A-BD50-1742FDA827A5}.Debug|Any CPU.ActiveCfg = Debug|x86\n\t\t{8824AA9B-8D64-4C3A-BD50-1742FDA827A5}.Debug|Any CPU.Build.0 = Debug|x86\n\t\t{8824AA9B-8D64-4C3A-BD50-1742FDA827A5}.Debug|x64.ActiveCfg = Debug|x64\n\t\t{8824AA9B-8D64-4C3A-BD50-1742FDA827A5}.Debug|x64.Build.0 = Debug|x64\n\t\t{8824AA9B-8D64-4C3A-BD50-1742FDA827A5}.Debug|x86.ActiveCfg = Debug|x86\n\t\t{8824AA9B-8D64-4C3A-BD50-1742FDA827A5}.Debug|x86.Build.0 = Debug|x86\n\t\t{8824AA9B-8D64-4C3A-BD50-1742FDA827A5}.Release|Any CPU.ActiveCfg = Release|x86\n\t\t{8824AA9B-8D64-4C3A-BD50-1742FDA827A5}.Release|x64.ActiveCfg = Release|x64\n\t\t{8824AA9B-8D64-4C3A-BD50-1742FDA827A5}.Release|x64.Build.0 = Release|x64\n\t\t{8824AA9B-8D64-4C3A-BD50-1742FDA827A5}.Release|x86.ActiveCfg = Release|x86\n\t\t{8824AA9B-8D64-4C3A-BD50-1742FDA827A5}.Release|x86.Build.0 = Release|x86\n\t\t{1C19B4D7-E6A6-4A9A-8495-8231FA167D1C}.Debug|Any CPU.ActiveCfg = Debug|x86\n\t\t{1C19B4D7-E6A6-4A9A-8495-8231FA167D1C}.Debug|Any CPU.Build.0 = Debug|x86\n\t\t{1C19B4D7-E6A6-4A9A-8495-8231FA167D1C}.Debug|x64.ActiveCfg = Debug|x64\n\t\t{1C19B4D7-E6A6-4A9A-8495-8231FA167D1C}.Debug|x64.Build.0 = Debug|x64\n\t\t{1C19B4D7-E6A6-4A9A-8495-8231FA167D1C}.Debug|x86.ActiveCfg = Debug|x86\n\t\t{1C19B4D7-E6A6-4A9A-8495-8231FA167D1C}.Debug|x86.Build.0 = Debug|x86\n\t\t{1C19B4D7-E6A6-4A9A-8495-8231FA167D1C}.Release|Any CPU.ActiveCfg = Release|x86\n\t\t{1C19B4D7-E6A6-4A9A-8495-8231FA167D1C}.Release|x64.ActiveCfg = Release|x64\n\t\t{1C19B4D7-E6A6-4A9A-8495-8231FA167D1C}.Release|x64.Build.0 = Release|x64\n\t\t{1C19B4D7-E6A6-4A9A-8495-8231FA167D1C}.Release|x86.ActiveCfg = Release|x86\n\t\t{1C19B4D7-E6A6-4A9A-8495-8231FA167D1C}.Release|x86.Build.0 = Release|x86\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\nEndGlobal\n"
  }
]