diff --git a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/Core/AppCrashDumpCollection.cs b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/Core/AppCrashDumpCollection.cs new file mode 100644 index 00000000..17acfa3a --- /dev/null +++ b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/Core/AppCrashDumpCollection.cs @@ -0,0 +1,223 @@ +//---------------------------------------------------------------------------------------------- +// +// Licensed under the MIT License. See LICENSE.TXT in the project root license information. +// +//---------------------------------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.Serialization; +using System.Threading.Tasks; + +namespace Microsoft.Tools.WindowsDevicePortal +{ + /// + /// Wrappers for app crash dump collection methods. + /// + public partial class DevicePortal + { + /// + /// API to retrieve list of the available crash dumps (for sideloaded applications). + /// + public static readonly string AvailableCrashDumpsApi = "api/debug/dump/usermode/dumps"; + + /// + /// API to download or delete a crash dump file (for a sideloaded application). + /// + public static readonly string CrashDumpFileApi = "api/debug/dump/usermode/crashdump"; + + /// + /// API to control the crash dump settings for a sideloaded application. + /// + public static readonly string CrashDumpSettingsApi = "api/debug/dump/usermode/crashcontrol"; + + /// + /// Get a list of app crash dumps on the device. + /// + /// List of AppCrashDump objects, which represent crashdumps on the device. + public async Task> GetAppCrashDumpListAsync() + { + AppCrashDumpList cdl = await this.GetAsync(AvailableCrashDumpsApi); + return cdl.CrashDumps; + } + + /// + /// Download a sideloaded app's crash dump. + /// + /// The AppCrashDump to download + /// Stream of the crash dump + public async Task GetAppCrashDumpAsync(AppCrashDump crashdump) + { + string queryString = CrashDumpFileApi + string.Format("?packageFullName={0}&fileName={1}", crashdump.PackageFullName, crashdump.Filename); + Uri uri = Utilities.BuildEndpoint( + this.deviceConnection.Connection, + queryString); + + return await this.GetAsync(uri); + } + + /// + /// Delete an app crash dump stored on the device. + /// + /// The crashdump to be deleted + /// Task tracking completion of the request. + public async Task DeleteAppCrashDumpAsync(AppCrashDump crashdump) + { + await this.DeleteAsync(CrashDumpFileApi, + string.Format("packageFullName={0}&fileName={1}", crashdump.PackageFullName, crashdump.Filename)); + } + + /// + /// Get the crash settings for a sideloaded app. + /// + /// The app to get settings for + /// The crash settings for the app + public async Task GetAppCrashDumpSettingsAsync(AppPackage app) + { + return await this.GetAppCrashDumpSettingsAsync(app.PackageFullName); + } + + /// + /// Get the crash settings for a sideloaded app. + /// + /// The app to get settings for + /// The crash settings for the app + public async Task GetAppCrashDumpSettingsAsync(string packageFullname) + { + return await this.GetAsync( + CrashDumpSettingsApi, + string.Format("packageFullname={0}", packageFullname)); + } + + /// + /// Set the crash settings for a sideloaded app. + /// + /// The app to set crash settings for. + /// Whether to enable or disable crash collection for the app. + /// Task tracking completion of the request. + public async Task SetAppCrashDumpSettingsAsync(AppPackage app, bool enable = true) + { + string pfn = app.PackageFullName; + await SetAppCrashDumpSettingsAsync(pfn, enable); + } + + /// + /// Set the crash settings for a sideloaded app. + /// + /// The app to set crash settings for. + /// Whether to enable or disable crash collection for the app. + /// Task tracking completion of the request. + public async Task SetAppCrashDumpSettingsAsync(string packageFullName, bool enable = true) + { + if (enable) + { + await this.PostAsync( + CrashDumpSettingsApi, + string.Format("packageFullName={0}", packageFullName)); + } + else + { + await this.DeleteAsync( + CrashDumpSettingsApi, + string.Format("packageFullName={0}", packageFullName)); + } + } + + #region Data contract + + /// + /// Per-app crash dump settings. + /// + [DataContract] + public class AppCrashDumpSettings + { + /// + /// Gets whether crash dumps are enabled for the app + /// + [DataMember(Name = "CrashDumpEnabled")] + public bool CrashDumpEnabled + { + get; + private set; + } + } + + /// + /// Represents a crash dump collected from a sideloaded app. + /// + [DataContract] + public class AppCrashDump + { + + /// + /// Gets the timestamp of the crash as a string. + /// + [DataMember(Name = "FileDate")] + public string FileDateAsString + { + get; + private set; + } + + /// + /// Gets the timestamp of the crash. + /// + public DateTime FileDate + { + get + { + return DateTime.Parse(this.FileDateAsString); + } + } + + /// + /// Gets the filename of the crash file. + /// + [DataMember(Name = "FileName")] + public string Filename + { + get; + private set; + } + + /// + /// Gets the size of the crash dump, in bytes + /// + [DataMember(Name = "FileSize")] + public uint FileSizeInBytes + { + get; + private set; + } + + /// + /// Gets the package full name of the app that crashed. + /// + [DataMember(Name = "PackageFullName")] + public string PackageFullName + { + get; + private set; + } + } + + /// + /// A list of crash dumps. Internal usage only. + /// + [DataContract] + private class AppCrashDumpList + { + /// + /// Gets a list of crash dumps on the device. + /// + [DataMember(Name = "CrashDumps")] + public List CrashDumps + { + get; + private set; + } + } + #endregion Data contract + } +} diff --git a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/Core/DumpCollection.cs b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/Core/DumpCollection.cs index dce34655..94b32808 100644 --- a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/Core/DumpCollection.cs +++ b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/Core/DumpCollection.cs @@ -4,6 +4,12 @@ // //---------------------------------------------------------------------------------------------- +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.Serialization; +using System.Threading.Tasks; + namespace Microsoft.Tools.WindowsDevicePortal { /// @@ -14,12 +20,7 @@ public partial class DevicePortal /// /// API to retrieve list of the available bugcheck minidumps. /// - public static readonly string AvailableBugChecksApi = "api/debug/dump/kernel/dumplish"; - - /// - /// API to retrieve list of the available crash dumps (for sideloaded applications). - /// - public static readonly string AvailableCrashDumpsApi = "api/debug/dump/usermode/dumps"; + public static readonly string AvailableBugChecksApi = "api/debug/dump/kernel/dumplist"; /// /// API to download a bugcheck minidump file. @@ -32,23 +33,207 @@ public partial class DevicePortal public static readonly string BugcheckSettingsApi = "api/debug/dump/kernel/crashcontrol"; /// - /// API to download or delete a crash dump file (for a sideloaded application). + /// API to retrieve a live kernel dump. /// - public static readonly string CrashDumpFileApi = "api/debug/dump/usermode/crashdump"; + public static readonly string LiveKernelDumpApi = "api/debug/dump/livekernel"; /// - /// API to control the crash dump settings for a sideloaded application. + /// API to retrieve a live dump from a running user mode process. /// - public static readonly string CrashDumpSettingsApi = "api/debug/dump/usermode/crashcontrol"; + public static readonly string LiveProcessDumpApi = "api/debug/dump/usermode/live"; /// - /// API to retrieve a live kernel dump. + /// Get a list of dumpfiles on the system. /// - public static readonly string LiveKernelDumpApi = "api/debug/dump/livekernel"; + /// List of Dumpfiles. Use GetDumpFile to download the file. + public async Task> GetDumpfileListAsync() + { + DumpFileList dfl = await this.GetAsync(AvailableBugChecksApi); + return dfl.DumpFiles; + } /// - /// API to retrieve a live dump from a running user mode process. + /// Download a dumpfile from the system. /// - public static readonly string LiveProcessDumpApi = "api/debug/dump/usermode/live"; + /// Dumpfile object to be downloaded + /// Stream of the dump file + public async Task GetDumpFileAsync(Dumpfile crashdump) + { + string queryString = BugcheckFileApi + string.Format("?filename={0}", crashdump.Filename); + Uri uri = Utilities.BuildEndpoint( + this.deviceConnection.Connection, + queryString); + + return await this.GetAsync(uri); + } + + /// + /// Takes a live kernel dump of the device. This does not reboot the device. + /// + /// Stream of the kernel dump + public async Task GetLiveKernelDumpAsync() + { + Uri uri = Utilities.BuildEndpoint( + this.deviceConnection.Connection, + LiveKernelDumpApi); + + return await this.GetAsync(uri); + } + + /// + /// Take a live dump of a process on the system. + /// + /// PID of the process to get a live dump of. + /// Stream of the process live dump + public async Task GetLiveProcessDumpAsync(int pid) + { + string queryString = LiveProcessDumpApi + string.Format("?pid={0}", pid); + Uri uri = Utilities.BuildEndpoint( + this.deviceConnection.Connection, + queryString); + + return await this.GetAsync(uri); + } + + /// + /// Get information on how and when dump files are saved on the device. + /// + /// Dumpfile settings object. This can be edited and returned to the device to alter the settings. + public async Task GetDumpFileSettingsAsync() + { + return await this.GetAsync(BugcheckSettingsApi); + } + + /// + /// Set how and when dump files are saved on the device. + /// + /// Altered DumpFileSettings object to set on the device + /// Task tracking completion of the request + public async Task SetDumpFileSettingsAsync(DumpFileSettings dfs) + { + await this.PostAsync( + BugcheckSettingsApi, + string.Format( + "autoreboot={0}&overwrite={1}&dumptype={2}&maxdumpcount={3}", + dfs.AutoReboot ? "1" : "0", dfs.Overwrite ? "1" : "0", (int)dfs.DumpType, dfs.MaxDumpCount)); + } + } + + #region Data Contract + + /// + /// DumpFileSettings object. Used to get and set how and when a dump is saved on the device. + /// + [DataContract] + public class DumpFileSettings + { + /// + /// Gets or sets whether the device should restart after a crash dump is taken. + /// + [DataMember(Name = "autoreboot")] + public bool AutoReboot { get; set; } + + /// + /// Gets or sets the type of dump to be saved when a bugcheck occurs. + /// + [DataMember(Name = "dumptype")] + public DumpTypes DumpType { get; set; } + + /// + /// Gets or sets the max number of dumps to be saved on the device. + /// + [DataMember(Name = "maxdumpcount")] + public int MaxDumpCount { get; set; } + + /// + /// Gets or sets whether new dumps should overwrite older dumps. + /// + [DataMember(Name = "overwrite")] + public bool Overwrite { get; set; } + + /// + /// The 3 types of dumps that can be saved on the device (or not saved at all). + /// + public enum DumpTypes + { + /// + /// Don't collect device crash dumps + /// + Disabled = 0, + + /// + /// Collect all in use memory + /// + CompleteMemoryDump = 1, + + /// + /// Don't include usermode memory in the dump + /// + KernelDump = 2, + + /// + /// Limited kernel dump + /// + Minidump = 3 + } + } + + /// + /// Gets a list of kernel dumps on the device. + /// + [DataContract] + public class DumpFileList + { + /// + /// Gets a list of kernel dumps on the device. + /// + [DataMember(Name = "DumpFiles")] + public List DumpFiles { get; private set; } + } + + /// + /// Represents a dumpfile stored on the device. + /// + [DataContract] + public class Dumpfile + { + /// + /// Gets the timestamp of the crash as a string. + /// + [DataMember(Name = "FileDate")] + public string FileDateAsString + { + get; private set; + } + + /// + /// Gets the timestamp of the crash. + /// + public DateTime FileDate + { + get + { + return DateTime.Parse(this.FileDateAsString); + } + } + + /// + /// Gets the filename of the crash file. + /// + [DataMember(Name = "FileName")] + public string Filename + { + get; private set; + } + + /// + /// Gets the size of the crash dump, in bytes + /// + [DataMember(Name = "FileSize")] + public uint FileSizeInBytes + { + get; private set; + } } + #endregion Data Contract } diff --git a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/IoT/ApplicationManager.cs b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/IoT/ApplicationManager.cs index ee0f3a2c..2842f4e2 100644 --- a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/IoT/ApplicationManager.cs +++ b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/IoT/ApplicationManager.cs @@ -117,7 +117,7 @@ public class AppsListInfo public string DefaultApp { get; private set; } /// - /// Gets or sets the application packages + /// Gets the application packages /// [DataMember(Name = "AppPackages")] public List AppPackages { get; private set; } diff --git a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/WindowsDevicePortalWrapper.Shared.projitems b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/WindowsDevicePortalWrapper.Shared.projitems index 658e39da..488cd40d 100644 --- a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/WindowsDevicePortalWrapper.Shared.projitems +++ b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/WindowsDevicePortalWrapper.Shared.projitems @@ -9,6 +9,7 @@ Microsoft.Tools.WindowsDevicePortal +