Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ You should have received a copy of the GNU General Public License
using dnSpy.Contracts.Debugger.DotNet.CorDebug;
using dnSpy.Contracts.Debugger.StartDebugging.Dialog;
using dnSpy.Contracts.MVVM;
using dnSpy.Contracts.Settings;
using dnSpy.Debugger.DotNet.CorDebug.Properties;

namespace dnSpy.Debugger.DotNet.CorDebug.Dialogs.DebugProgram {
Expand Down Expand Up @@ -173,6 +174,25 @@ protected T InitializeDefault<T>(T options, string breakKind) where T : CorDebug
return options;
}

protected static void SerializeCorDebugOptions(ISettingsSection section, CorDebugStartDebuggingOptions options) {
if (options.BreakKind is not null)
section.Attribute(nameof(options.BreakKind), options.BreakKind);
if (options.Filename is not null)
section.Attribute(nameof(options.Filename), options.Filename);
if (options.CommandLine is not null)
section.Attribute(nameof(options.CommandLine), options.CommandLine);
if (options.WorkingDirectory is not null)
section.Attribute(nameof(options.WorkingDirectory), options.WorkingDirectory);
// The environment isn't serialized, it always contains all of the current process' environment variables
}

protected static void DeserializeCorDebugOptions(ISettingsSection section, CorDebugStartDebuggingOptions options) {
options.BreakKind = section.Attribute<string>(nameof(options.BreakKind)) ?? options.BreakKind;
options.Filename = section.Attribute<string>(nameof(options.Filename));
options.CommandLine = section.Attribute<string>(nameof(options.CommandLine));
options.WorkingDirectory = section.Attribute<string>(nameof(options.WorkingDirectory));
}

protected T GetOptions<T>(T options) where T : CorDebugStartDebuggingOptions {
options.Filename = Filename;
options.CommandLine = CommandLine;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ You should have received a copy of the GNU General Public License
using dnSpy.Contracts.Debugger.StartDebugging;
using dnSpy.Contracts.Debugger.StartDebugging.Dialog;
using dnSpy.Contracts.MVVM;
using dnSpy.Contracts.Settings;
using dnSpy.Debugger.DotNet.CorDebug.Properties;
using dnSpy.Debugger.DotNet.CorDebug.Utilities;

Expand Down Expand Up @@ -121,6 +122,22 @@ public override bool SupportsDebugEngine(Guid engineGuid, out double order) {
return false;
}

public override bool SerializeOptions(ISettingsSection section, StartDebuggingOptions options) {
if (options is not DotNetFrameworkStartDebuggingOptions dnfOptions)
return false;
SerializeCorDebugOptions(section, dnfOptions);
if (dnfOptions.DebuggeeVersion is not null)
section.Attribute(nameof(dnfOptions.DebuggeeVersion), dnfOptions.DebuggeeVersion);
return true;
}

public override StartDebuggingOptions? DeserializeOptions(ISettingsSection section) {
var options = new DotNetFrameworkStartDebuggingOptions();
DeserializeCorDebugOptions(section, options);
options.DebuggeeVersion = section.Attribute<string>(nameof(options.DebuggeeVersion));
return options;
}

protected override bool CalculateIsValid() => string.IsNullOrEmpty(Verify(nameof(Filename)));

protected override string Verify(string columnName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ You should have received a copy of the GNU General Public License
using dnSpy.Contracts.Debugger.StartDebugging;
using dnSpy.Contracts.Debugger.StartDebugging.Dialog;
using dnSpy.Contracts.MVVM;
using dnSpy.Contracts.Settings;
using dnSpy.Debugger.DotNet.CorDebug.Utilities;

namespace dnSpy.Debugger.DotNet.CorDebug.Dialogs.DebugProgram {
Expand Down Expand Up @@ -162,6 +163,29 @@ public override bool SupportsDebugEngine(Guid engineGuid, out double order) {
return false;
}

public override bool SerializeOptions(ISettingsSection section, StartDebuggingOptions options) {
if (options is not DotNetStartDebuggingOptions dncOptions)
return false;
SerializeCorDebugOptions(section, dncOptions);
section.Attribute(nameof(dncOptions.UseHost), dncOptions.UseHost);
if (dncOptions.Host is not null)
section.Attribute(nameof(dncOptions.Host), dncOptions.Host);
if (dncOptions.HostArguments is not null)
section.Attribute(nameof(dncOptions.HostArguments), dncOptions.HostArguments);
section.Attribute(nameof(dncOptions.ConnectionTimeout), dncOptions.ConnectionTimeout);
return true;
}

public override StartDebuggingOptions? DeserializeOptions(ISettingsSection section) {
var options = new DotNetStartDebuggingOptions();
DeserializeCorDebugOptions(section, options);
options.UseHost = section.Attribute<bool?>(nameof(options.UseHost)) ?? options.UseHost;
options.Host = section.Attribute<string>(nameof(options.Host));
options.HostArguments = section.Attribute<string>(nameof(options.HostArguments));
options.ConnectionTimeout = section.Attribute<TimeSpan?>(nameof(options.ConnectionTimeout)) ?? options.ConnectionTimeout;
return options;
}

protected override bool CalculateIsValid() =>
string.IsNullOrEmpty(Verify(nameof(HostFilename))) &&
string.IsNullOrEmpty(Verify(nameof(Filename))) && !ConnectionTimeout.HasError;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ You should have received a copy of the GNU General Public License
using dnSpy.Contracts.Debugger;
using dnSpy.Contracts.Debugger.DotNet.Mono;
using dnSpy.Contracts.Debugger.StartDebugging.Dialog;
using dnSpy.Contracts.Settings;
using dnSpy.Debugger.DotNet.Mono.Properties;

namespace dnSpy.Debugger.DotNet.Mono.Dialogs.DebugProgram {
Expand Down Expand Up @@ -56,5 +57,18 @@ public override StartDebuggingOptionsInfo GetOptions() {
var options = GetOptions(new MonoConnectStartDebuggingOptions());
return new StartDebuggingOptionsInfo(options, null, StartDebuggingOptionsInfoFlags.None);
}

public override bool SerializeOptions(ISettingsSection section, StartDebuggingOptions options) {
if (options is not MonoConnectStartDebuggingOptions connectOptions)
return false;
SerializeMonoConnectOptions(section, connectOptions);
return true;
}

public override StartDebuggingOptions? DeserializeOptions(ISettingsSection section) {
var options = new MonoConnectStartDebuggingOptions();
DeserializeMonoConnectOptions(section, options);
return options;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ You should have received a copy of the GNU General Public License
using dnSpy.Contracts.Debugger.DotNet.Mono;
using dnSpy.Contracts.Debugger.StartDebugging.Dialog;
using dnSpy.Contracts.MVVM;
using dnSpy.Contracts.Settings;

namespace dnSpy.Debugger.DotNet.Mono.Dialogs.DebugProgram {
abstract class MonoConnectStartDebuggingOptionsPageBase : StartDebuggingOptionsPage, IDataErrorInfo {
Expand Down Expand Up @@ -108,6 +109,24 @@ protected T GetOptions<T>(T options) where T : MonoConnectStartDebuggingOptionsB
return options;
}

protected static void SerializeMonoConnectOptions(ISettingsSection section, MonoConnectStartDebuggingOptionsBase options) {
if (options.BreakKind is not null)
section.Attribute(nameof(options.BreakKind), options.BreakKind);
if (options.Address is not null)
section.Attribute(nameof(options.Address), options.Address);
section.Attribute(nameof(options.Port), options.Port);
section.Attribute(nameof(options.ConnectionTimeout), options.ConnectionTimeout);
section.Attribute(nameof(options.ProcessIsSuspended), options.ProcessIsSuspended);
}

protected static void DeserializeMonoConnectOptions(ISettingsSection section, MonoConnectStartDebuggingOptionsBase options) {
options.BreakKind = section.Attribute<string>(nameof(options.BreakKind)) ?? options.BreakKind;
options.Address = section.Attribute<string>(nameof(options.Address));
options.Port = section.Attribute<ushort?>(nameof(options.Port)) ?? options.Port;
options.ConnectionTimeout = section.Attribute<TimeSpan?>(nameof(options.ConnectionTimeout)) ?? options.ConnectionTimeout;
options.ProcessIsSuspended = section.Attribute<bool?>(nameof(options.ProcessIsSuspended)) ?? options.ProcessIsSuspended;
}

string IDataErrorInfo.Error => throw new NotImplementedException();
string IDataErrorInfo.this[string columnName] => Verify(columnName);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ You should have received a copy of the GNU General Public License
using dnSpy.Contracts.Debugger.StartDebugging;
using dnSpy.Contracts.Debugger.StartDebugging.Dialog;
using dnSpy.Contracts.MVVM;
using dnSpy.Contracts.Settings;

namespace dnSpy.Debugger.DotNet.Mono.Dialogs.DebugProgram {
sealed class MonoStartDebuggingOptionsPage : MonoStartDebuggingOptionsPageBase {
Expand Down Expand Up @@ -126,6 +127,24 @@ public override bool SupportsDebugEngine(Guid engineGuid, out double order) {
return false;
}

public override bool SerializeOptions(ISettingsSection section, StartDebuggingOptions options) {
if (options is not MonoStartDebuggingOptions msdOptions)
return false;
SerializeMonoOptions(section, msdOptions);
if (msdOptions.MonoExePath is not null)
section.Attribute(nameof(msdOptions.MonoExePath), msdOptions.MonoExePath);
section.Attribute(nameof(msdOptions.MonoExeOptions), msdOptions.MonoExeOptions);
return true;
}

public override StartDebuggingOptions? DeserializeOptions(ISettingsSection section) {
var options = new MonoStartDebuggingOptions();
DeserializeMonoOptions(section, options);
options.MonoExePath = section.Attribute<string>(nameof(options.MonoExePath));
options.MonoExeOptions = section.Attribute<MonoExeOptions?>(nameof(options.MonoExeOptions)) ?? options.MonoExeOptions;
return options;
}

protected override bool CalculateIsValidCore() => string.IsNullOrEmpty(Verify(nameof(MonoExePath)));

protected override string VerifyCore(string columnName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ You should have received a copy of the GNU General Public License
using dnSpy.Contracts.Debugger.DotNet.Mono;
using dnSpy.Contracts.Debugger.StartDebugging.Dialog;
using dnSpy.Contracts.MVVM;
using dnSpy.Contracts.Settings;
using dnSpy.Debugger.DotNet.Mono.Properties;

namespace dnSpy.Debugger.DotNet.Mono.Dialogs.DebugProgram {
Expand Down Expand Up @@ -194,6 +195,29 @@ protected void GetOptions(MonoStartDebuggingOptionsBase options) {
options.BreakKind = FilterBreakKind(BreakKind);
}

protected static void SerializeMonoOptions(ISettingsSection section, MonoStartDebuggingOptionsBase options) {
if (options.BreakKind is not null)
section.Attribute(nameof(options.BreakKind), options.BreakKind);
if (options.Filename is not null)
section.Attribute(nameof(options.Filename), options.Filename);
if (options.CommandLine is not null)
section.Attribute(nameof(options.CommandLine), options.CommandLine);
if (options.WorkingDirectory is not null)
section.Attribute(nameof(options.WorkingDirectory), options.WorkingDirectory);
section.Attribute(nameof(options.ConnectionPort), options.ConnectionPort);
section.Attribute(nameof(options.ConnectionTimeout), options.ConnectionTimeout);
// The environment isn't serialized, it always contains all of the current process' environment variables
}

protected static void DeserializeMonoOptions(ISettingsSection section, MonoStartDebuggingOptionsBase options) {
options.BreakKind = section.Attribute<string>(nameof(options.BreakKind)) ?? options.BreakKind;
options.Filename = section.Attribute<string>(nameof(options.Filename));
options.CommandLine = section.Attribute<string>(nameof(options.CommandLine));
options.WorkingDirectory = section.Attribute<string>(nameof(options.WorkingDirectory));
options.ConnectionPort = section.Attribute<ushort?>(nameof(options.ConnectionPort)) ?? options.ConnectionPort;
options.ConnectionTimeout = section.Attribute<TimeSpan?>(nameof(options.ConnectionTimeout)) ?? options.ConnectionTimeout;
}

string IDataErrorInfo.Error => throw new NotImplementedException();
string IDataErrorInfo.this[string columnName] => Verify(columnName);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ You should have received a copy of the GNU General Public License
using dnSpy.Contracts.Debugger.DotNet.Mono;
using dnSpy.Contracts.Debugger.StartDebugging.Dialog;
using dnSpy.Contracts.MVVM;
using dnSpy.Contracts.Settings;
using dnSpy.Debugger.DotNet.Mono.Properties;

namespace dnSpy.Debugger.DotNet.Mono.Dialogs.DebugProgram {
Expand Down Expand Up @@ -68,5 +69,18 @@ public override StartDebuggingOptionsInfo GetOptions() {
var options = GetOptions(new UnityConnectStartDebuggingOptions());
return new StartDebuggingOptionsInfo(options, null, StartDebuggingOptionsInfoFlags.None);
}

public override bool SerializeOptions(ISettingsSection section, StartDebuggingOptions options) {
if (options is not UnityConnectStartDebuggingOptions connectOptions)
return false;
SerializeMonoConnectOptions(section, connectOptions);
return true;
}

public override StartDebuggingOptions? DeserializeOptions(ISettingsSection section) {
var options = new UnityConnectStartDebuggingOptions { Port = DEFAULT_PORT };
DeserializeMonoConnectOptions(section, options);
return options;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ You should have received a copy of the GNU General Public License
using dnSpy.Contracts.Debugger.StartDebugging;
using dnSpy.Contracts.Debugger.StartDebugging.Dialog;
using dnSpy.Contracts.MVVM;
using dnSpy.Contracts.Settings;

namespace dnSpy.Debugger.DotNet.Mono.Dialogs.DebugProgram {
sealed class UnityStartDebuggingOptionsPage : MonoStartDebuggingOptionsPageBase {
Expand Down Expand Up @@ -104,6 +105,19 @@ public override bool SupportsDebugEngine(Guid engineGuid, out double order) {
return false;
}

public override bool SerializeOptions(ISettingsSection section, StartDebuggingOptions options) {
if (options is not UnityStartDebuggingOptions usdOptions)
return false;
SerializeMonoOptions(section, usdOptions);
return true;
}

public override StartDebuggingOptions? DeserializeOptions(ISettingsSection section) {
var options = new UnityStartDebuggingOptions();
DeserializeMonoOptions(section, options);
return options;
}

protected override bool CalculateIsValidCore() => true;
protected override string VerifyCore(string columnName) => string.Empty;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ public void Add(string filename, StartDebuggingOptions options, Guid pageGuid) {
return (info.Options, info.PageGuid);
}

public void SetLastOptions(StartDebuggingOptions options, Guid pageGuid) {
if (options is null)
throw new ArgumentNullException(nameof(options));
lastOptions = ((StartDebuggingOptions)options.Clone(), pageGuid);
}

public (StartDebuggingOptions options, Guid pageGuid)? TryGetLastOptions() => lastOptions;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,31 @@ You should have received a copy of the GNU General Public License
using dnSpy.Contracts.Debugger.StartDebugging.Dialog;
using dnSpy.Contracts.Documents.Tabs;
using dnSpy.Contracts.Documents.TreeView;
using dnSpy.Contracts.Settings;
using dnSpy.Debugger.Dialogs.DebugProgram;
using dnSpy.Debugger.Properties;

namespace dnSpy.Debugger.DbgUI {
[Export(typeof(StartDebuggingOptionsProvider))]
sealed class StartDebuggingOptionsProvider {
static readonly Guid SETTINGS_GUID = new Guid("1D06F2C9-BC3C-4D44-93B3-729F939F3F97");
const string PageGuidAttr = "PageGuid";
const string OptionsSectionName = "Options";

readonly IAppWindow appWindow;
readonly IDocumentTabService documentTabService;
readonly ISettingsService settingsService;
readonly Lazy<StartDebuggingOptionsPageProvider>[] startDebuggingOptionsPageProviders;
readonly Lazy<DbgProcessStarterService> dbgProcessStarterService;
readonly Lazy<GenericDebugEngineGuidProvider, IGenericDebugEngineGuidProviderMetadata>[] genericDebugEngineGuidProviders;
readonly StartDebuggingOptionsMru mru;
bool mruLoaded;

[ImportingConstructor]
StartDebuggingOptionsProvider(IAppWindow appWindow, IDocumentTabService documentTabService, Lazy<DbgProcessStarterService> dbgProcessStarterService, [ImportMany] IEnumerable<Lazy<StartDebuggingOptionsPageProvider>> startDebuggingOptionsPageProviders, [ImportMany] IEnumerable<Lazy<GenericDebugEngineGuidProvider, IGenericDebugEngineGuidProviderMetadata>> genericDebugEngineGuidProviders) {
StartDebuggingOptionsProvider(IAppWindow appWindow, IDocumentTabService documentTabService, ISettingsService settingsService, Lazy<DbgProcessStarterService> dbgProcessStarterService, [ImportMany] IEnumerable<Lazy<StartDebuggingOptionsPageProvider>> startDebuggingOptionsPageProviders, [ImportMany] IEnumerable<Lazy<GenericDebugEngineGuidProvider, IGenericDebugEngineGuidProviderMetadata>> genericDebugEngineGuidProviders) {
this.appWindow = appWindow;
this.documentTabService = documentTabService;
this.settingsService = settingsService;
this.dbgProcessStarterService = dbgProcessStarterService;
this.startDebuggingOptionsPageProviders = startDebuggingOptionsPageProviders.ToArray();
this.genericDebugEngineGuidProviders = genericDebugEngineGuidProviders.OrderBy(a => a.Metadata.Order).ToArray();
Expand Down Expand Up @@ -85,6 +93,11 @@ string GetCurrentFilename() {
if (pages.Length == 0)
return default;

if (!mruLoaded) {
mruLoaded = true;
LoadLastOptions(pages);
}

var oldOptions = mru.TryGetOptions(filename);
var lastOptions = mru.TryGetLastOptions();
foreach (var page in pages) {
Expand Down Expand Up @@ -130,9 +143,36 @@ string GetCurrentFilename() {
}

mru.Add(info.Filename!, info.Options, vm.SelectedPageGuid);
SaveLastOptions(pages, info.Options, vm.SelectedPageGuid);
return (info.Options, info.Flags);
}

void LoadLastOptions(StartDebuggingOptionsPage[] pages) {
var section = settingsService.GetOrCreateSection(SETTINGS_GUID);
var pageGuid = section.Attribute<Guid?>(PageGuidAttr);
if (pageGuid is null)
return;
var optionsSection = section.TryGetSection(OptionsSectionName);
if (optionsSection is null)
return;
// The page could be missing, eg. if its extension got uninstalled or disabled
var page = pages.FirstOrDefault(a => a.Guid == pageGuid.Value);
var options = page?.DeserializeOptions(optionsSection);
if (options is null)
return;
mru.SetLastOptions(options, pageGuid.Value);
}

void SaveLastOptions(StartDebuggingOptionsPage[] pages, StartDebuggingOptions options, Guid pageGuid) {
var page = pages.FirstOrDefault(a => a.Guid == pageGuid);
if (page is null)
return;
var section = settingsService.RecreateSection(SETTINGS_GUID);
section.Attribute(PageGuidAttr, pageGuid);
if (!page.SerializeOptions(section.CreateSection(OptionsSectionName), options))
settingsService.RemoveSection(SETTINGS_GUID);
}

static bool? IsCompatibleWithCurrentArchitecture(string fileName) {
int? bitness = null;
try {
Expand Down
Loading