Skip to content

Commit 697fea1

Browse files
committed
Better control on when to set us active, and fixes the VS virtual profile bug
1 parent 85d85de commit 697fea1

File tree

8 files changed

+81
-21
lines changed

8 files changed

+81
-21
lines changed

SmartCmdArgs/SmartCmdArgs.Shared/CmdArgsOptionPage.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Microsoft.VisualStudio.Shell;
22
using SmartCmdArgs.Helper;
3+
using System;
34
using System.ComponentModel;
45
using System.Linq;
56
using System.Reflection;
@@ -45,6 +46,19 @@ public enum EnableBehaviour
4546
[Description("Enable by default (old behaviour)")]
4647
EnableByDefault,
4748
}
49+
[Flags]
50+
[TypeConverter(typeof(EnumDescriptionTypeConverter))]
51+
public enum SetActiveProfileBehavior
52+
{
53+
[Description("Never, due to a bug in virtual profiles you will have to reselect Smart CLI Args every time you open a project")]
54+
Never = 1 << 0,
55+
[Description("On Smart CLI Arg tree changed (ie option checked)")]
56+
OnTreeChanged = 1 << 1,
57+
[Description("On first run/debug")]
58+
OnRun = 1 << 2,
59+
[Description("On Smart CLI Arg option checked or first run/debug")]
60+
OnCheckedOrRun = OnTreeChanged | OnRun
61+
}
4862

4963
public class CmdArgsOptionPage : DialogPage, INotifyPropertyChanged
5064
{
@@ -64,6 +78,7 @@ public CmdArgsOptionPage() : base()
6478
}
6579

6680
private EnableBehaviour _enableBehaviour;
81+
private SetActiveProfileBehavior _setActiveProfileBehavior;
6782
private RelativePathRootOption _relativePathRoot;
6883

6984
private bool _useMonospaceFont;
@@ -92,6 +107,16 @@ public EnableBehaviour EnableBehaviour
92107
set => SetAndNotify(value, ref _enableBehaviour);
93108
}
94109

110+
[Category("Settings Defaults")]
111+
[DisplayName("Set Active Profile Behavior")]
112+
[Description("When we should automatically make ourselves the active profile")]
113+
[DefaultValue(SetActiveProfileBehavior.OnTreeChanged)]
114+
public SetActiveProfileBehavior SetActiveProfileBehavior
115+
{
116+
get => _setActiveProfileBehavior;
117+
set => SetAndNotify(value, ref _setActiveProfileBehavior);
118+
}
119+
95120
[Category("General")]
96121
[DisplayName("Relative path root")]
97122
[Description("Sets the base path that is used to resolve relative paths for the open/reveal file/folder context menu option.")]

SmartCmdArgs/SmartCmdArgs.Shared/Helper/CpsProjectConfigService.cs

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public interface ICpsProjectConfigService
3535
IDisposable ListenToLaunchProfileChanges(Project project, Action listener);
3636
void SetActiveLaunchProfileByName(Project project, string profileName);
3737
void SetActiveLaunchProfileToVirtualProfile(Project project);
38-
void SetConfig(Project project, string arguments, IDictionary<string, string> envVars, string workDir, string launchApp);
38+
void SetConfig(Project project, string arguments, IDictionary<string, string> envVars, string workDir, string launchApp, UpdateProjectConfigReason reason);
3939
}
4040

4141
public class CpsProjectConfigService : ICpsProjectConfigService
@@ -134,7 +134,7 @@ public IDisposable ListenToLaunchProfileChanges(EnvDTE.Project project, Action l
134134
return null;
135135
}
136136

137-
public void SetConfig(EnvDTE.Project project, string arguments, IDictionary<string, string> envVars, string workDir, string launchApp)
137+
public void SetConfig(EnvDTE.Project project, string arguments, IDictionary<string, string> envVars, string workDir, string launchApp, UpdateProjectConfigReason reason)
138138
{
139139
IUnconfiguredProjectServices unconfiguredProjectServices;
140140
IProjectServices projectServices;
@@ -143,6 +143,7 @@ public void SetConfig(EnvDTE.Project project, string arguments, IDictionary<stri
143143
{
144144
var launchSettingsProvider = unconfiguredProjectServices.ExportProvider.GetExportedValue<ILaunchSettingsProvider>();
145145
ILaunchProfile baseLaunchProfile = null;
146+
var applyProfileFix=true;
146147
if (optionsSettingsService.UseCpsVirtualProfile)
147148
{
148149
baseLaunchProfile = launchSettingsProvider.CurrentSnapshot.Profiles.FirstOrDefault(x => x.Name == VirtualProfileName);
@@ -152,14 +153,21 @@ public void SetConfig(EnvDTE.Project project, string arguments, IDictionary<stri
152153
{
153154
baseLaunchProfile = launchSettingsProvider?.ActiveProfile;
154155
}
156+
else
157+
applyProfileFix = false; //we already existed
155158

159+
var dbgsnapshot = launchSettingsProvider.CurrentSnapshot;
160+
var dbgactiveProfile = launchSettingsProvider.ActiveProfile;
161+
//OurLogger.Info(LogCat.Other, $"dbgsnapshot {dbgsnapshot?.ActiveProfile?.Name}, dbgactiveProfile {dbgactiveProfile?.Name}, baseLaunchProfile: {baseLaunchProfile?.Name} forceOurProfileActive: {applyProfileFix}");
156162
if (baseLaunchProfile == null)
157163
return;
158164

159165
var writableLaunchProfile = WritableLaunchProfile.GetWritableLaunchProfile(baseLaunchProfile);
160166

161167
if (arguments != null)
162168
writableLaunchProfile.CommandLineArgs = arguments;
169+
else
170+
applyProfileFix = false;//incase not used on a solution
163171

164172
if (envVars != null)
165173
writableLaunchProfile.EnvironmentVariables = envVars.ToImmutableDictionary();
@@ -175,10 +183,23 @@ public void SetConfig(EnvDTE.Project project, string arguments, IDictionary<stri
175183
writableLaunchProfile.Name = VirtualProfileName;
176184
writableLaunchProfile.DoNotPersist = true;
177185
}
186+
var activeProfileBehavior = optionsSettingsService.SetActiveProfileBehavior;
187+
var setActiveProfile = (activeProfileBehavior.HasFlag(SetActiveProfileBehavior.OnRun) && (reason == UpdateProjectConfigReason.RunDebugLaunch && applyProfileFix)) || (activeProfileBehavior.HasFlag(SetActiveProfileBehavior.OnTreeChanged) && reason == UpdateProjectConfigReason.TreeChange); //applyprofilefix is set on first run only when we are added, if this happens due to a tree change but the behavior is OnRun we want to set the active profile. Note as this only happens on first run it is not the same as setting it active on every tree change
178188

179-
projectServices.ThreadingPolicy.ExecuteSynchronously(() =>
189+
190+
projectServices.ThreadingPolicy.ExecuteSynchronously(async () =>
180191
{
181-
return launchSettingsProvider.AddOrUpdateProfileAsync(writableLaunchProfile, addToFront: false);
192+
193+
if (applyProfileFix){
194+
var activeProfile = launchSettingsProvider.ActiveProfile?.Name;
195+
if (! String.IsNullOrWhiteSpace( activeProfile))
196+
await launchSettingsProvider.SetActiveProfileAsync(activeProfile);
197+
}
198+
199+
await launchSettingsProvider.AddOrUpdateProfileAsync(writableLaunchProfile, addToFront: false);
200+
if (setActiveProfile)
201+
await launchSettingsProvider.SetActiveProfileAsync(writableLaunchProfile.Name);
202+
182203
});
183204
}
184205
}
@@ -340,4 +361,5 @@ internal static WritableLaunchProfile GetWritableLaunchProfile(ILaunchProfile pr
340361
}
341362

342363
}
364+
343365
}

SmartCmdArgs/SmartCmdArgs.Shared/Services/OptionsSettingsEventHandlingService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ private void UseCpsVirtualProfileChanged()
128128
{
129129
foreach (var project in vsHelper.GetSupportedProjects().Where(x => x.SupportsLaunchProfiles()))
130130
{
131-
projectConfigService.UpdateProjectConfig(project);
131+
projectConfigService.UpdateProjectConfig(project, UpdateProjectConfigReason.UseVirtualProfileChanged);
132132
cpsProjectConfigService.SetActiveLaunchProfileToVirtualProfile(project.GetProject());
133133
}
134134
}

SmartCmdArgs/SmartCmdArgs.Shared/Services/OptionsSettingsService.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public interface IOptionsSettingsService
3030
bool DeleteEmptyFilesAutomatically { get; }
3131
bool DeleteUnnecessaryFilesAutomatically { get; }
3232
EnableBehaviour EnableBehaviour { get; }
33+
SetActiveProfileBehavior SetActiveProfileBehavior { get; }
3334
InactiveDisableMode DisableInactiveItems { get; }
3435
RelativePathRootOption RelativePathRoot { get; }
3536

@@ -77,6 +78,7 @@ public OptionsSettingsService(
7778
#endif
7879
public bool UseMonospaceFont => OptionsPage.UseMonospaceFont;
7980
public bool DisplayTagForCla => OptionsPage.DisplayTagForCla;
81+
public SetActiveProfileBehavior SetActiveProfileBehavior => OptionsPage.SetActiveProfileBehavior;
8082
public bool DeleteEmptyFilesAutomatically => OptionsPage.DeleteEmptyFilesAutomatically;
8183
public bool DeleteUnnecessaryFilesAutomatically => OptionsPage.DeleteUnnecessaryFilesAutomatically;
8284
public EnableBehaviour EnableBehaviour => OptionsPage.EnableBehaviour;

SmartCmdArgs/SmartCmdArgs.Shared/Services/ProjectConfigService.cs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,16 @@
88

99
namespace SmartCmdArgs.Services
1010
{
11+
public enum UpdateProjectConfigReason{ RunDebugLaunch, TreeChange,UseVirtualProfileChanged }
1112
public interface IProjectConfigService
1213
{
1314
bool IsSupportedProject(IVsHierarchyWrapper project);
1415

1516
List<CmdItemJson> GetItemsFromProjectConfig(IVsHierarchyWrapper project);
1617

17-
void UpdateProjectConfig(IVsHierarchyWrapper project);
18+
void UpdateProjectConfig(IVsHierarchyWrapper project, UpdateProjectConfigReason reason);
19+
20+
1821
}
1922

2023
public class ProjectConfigService : IProjectConfigService
@@ -48,7 +51,7 @@ public ProjectConfigService(
4851

4952
private class ProjectConfigHandlers
5053
{
51-
public delegate void SetConfigDelegate(EnvDTE.Project project, string arguments, IDictionary<string, string> envVars, string workDir, string launchApp);
54+
public delegate void SetConfigDelegate(EnvDTE.Project project, string arguments, IDictionary<string, string> envVars, string workDir, string launchApp, UpdateProjectConfigReason reason);
5255
public delegate void GetAllArgumentsDelegate(EnvDTE.Project project, List<CmdItemJson> allArgs, bool includeArgs, bool includeEnvVars, bool includeWorkDir, bool includeLaunchApp);
5356
public SetConfigDelegate SetConfig;
5457
public GetAllArgumentsDelegate GetItemsFromConfig;
@@ -59,7 +62,7 @@ private Dictionary<Guid, ProjectConfigHandlers> InitConfigHandlerForSupportedPro
5962
{
6063
// C#
6164
{ProjectKinds.CS, new ProjectConfigHandlers() {
62-
SetConfig = (project, arguments, envVars, workDir, launchApp) => {
65+
SetConfig = (project, arguments, envVars, workDir, launchApp, reason) => {
6366
SetMultiConfigProperty(project, arguments, "StartArguments");
6467
SetMultiConfigProperty(project, workDir, "StartWorkingDirectory");
6568
SetMultiConfigProperty(project, launchApp, "StartProgram");
@@ -68,13 +71,13 @@ private Dictionary<Guid, ProjectConfigHandlers> InitConfigHandlerForSupportedPro
6871
} },
6972
// C# UWP
7073
{ProjectKinds.CS_UWP, new ProjectConfigHandlers() {
71-
SetConfig = (project, arguments, envVars, workDir, launchApp) => SetMultiConfigProperty(project, arguments, "UAPDebug.CommandLineArguments"),
74+
SetConfig = (project, arguments, envVars, workDir, launchApp, reason) => SetMultiConfigProperty(project, arguments, "UAPDebug.CommandLineArguments"),
7275
GetItemsFromConfig = GetItemsFromMultiConfig("UAPDebug.CommandLineArguments")
7376
} },
7477

7578
// VB.NET
7679
{ProjectKinds.VB, new ProjectConfigHandlers() {
77-
SetConfig = (project, arguments, _, workDir, launchApp) => {
80+
SetConfig = (project, arguments, _, workDir, launchApp, reason) => {
7881
SetMultiConfigProperty(project, arguments, "StartArguments");
7982
SetMultiConfigProperty(project, workDir, "StartWorkingDirectory");
8083
SetMultiConfigProperty(project, launchApp, "StartProgram");
@@ -88,7 +91,7 @@ private Dictionary<Guid, ProjectConfigHandlers> InitConfigHandlerForSupportedPro
8891
} },
8992
// Python
9093
{ProjectKinds.Py, new ProjectConfigHandlers() {
91-
SetConfig = (project, arguments, envVars, workDir, _) => {
94+
SetConfig = (project, arguments, envVars, workDir, _, reason) => {
9295
SetSingleConfigProperty(project, arguments, "CommandLineArguments");
9396
SetSingleConfigEnvVars(project, envVars, "Environment");
9497
SetSingleConfigProperty(project, workDir, "WorkingDirectory");
@@ -97,7 +100,7 @@ private Dictionary<Guid, ProjectConfigHandlers> InitConfigHandlerForSupportedPro
97100
} },
98101
// Node.js
99102
{ProjectKinds.Node, new ProjectConfigHandlers() {
100-
SetConfig = (project, arguments, envVars, workDir, _) => {
103+
SetConfig = (project, arguments, envVars, workDir, _, reason) => {
101104
SetSingleConfigProperty(project, arguments, "ScriptArguments");
102105
SetSingleConfigEnvVars(project, envVars, "Environment");
103106
SetSingleConfigProperty(project, workDir, "WorkingDirectory");
@@ -111,7 +114,7 @@ private Dictionary<Guid, ProjectConfigHandlers> InitConfigHandlerForSupportedPro
111114
} },
112115
// F#
113116
{ProjectKinds.FS, new ProjectConfigHandlers() {
114-
SetConfig = (project, arguments, _, workDir, launchApp) => {
117+
SetConfig = (project, arguments, _, workDir, launchApp, reason) => {
115118
SetMultiConfigProperty(project, arguments, "StartArguments");
116119
SetMultiConfigProperty(project, workDir, "StartWorkingDirectory");
117120
SetMultiConfigProperty(project, launchApp, "StartProgram");
@@ -377,7 +380,7 @@ private static ProjectConfigHandlers.GetAllArgumentsDelegate GetItemsFromMultiCo
377380
("AppHostLocalDebugger", "CommandLineArgs", null, null, null),
378381
};
379382

380-
private static void SetVCProjEngineConfig(EnvDTE.Project project, string arguments, IDictionary<string, string> envVars, string workDir, string launchApp)
383+
private static void SetVCProjEngineConfig(EnvDTE.Project project, string arguments, IDictionary<string, string> envVars, string workDir, string launchApp, UpdateProjectConfigReason reason)
381384
{
382385
ThreadHelper.ThrowIfNotOnUIThread();
383386

@@ -591,7 +594,7 @@ private static string VFFormatConfigName(EnvDTE.Configuration vcCfg)
591594
// to optain the right configurations object from `Project.Object.Configurations`
592595
// this object is simmilar to the VCProjEngine configuration and has `DebugSettings`
593596
// which contain the CommandArguments which we can use to set the args.
594-
private static void SetVFProjEngineConfig(EnvDTE.Project project, string arguments, IDictionary<string, string> envVars, string workDir, string launchApp)
597+
private static void SetVFProjEngineConfig(EnvDTE.Project project, string arguments, IDictionary<string, string> envVars, string workDir, string launchApp, UpdateProjectConfigReason reason)
595598
{
596599
ThreadHelper.ThrowIfNotOnUIThread();
597600

@@ -773,7 +776,7 @@ public List<CmdItemJson> GetItemsFromProjectConfig(IVsHierarchyWrapper project)
773776
return result;
774777
}
775778

776-
public void UpdateProjectConfig(IVsHierarchyWrapper project)
779+
public void UpdateProjectConfig(IVsHierarchyWrapper project, UpdateProjectConfigReason reason)
777780
{
778781
if (!lifeCycleService.Value.IsEnabled || project == null)
779782
return;
@@ -788,10 +791,11 @@ public void UpdateProjectConfig(IVsHierarchyWrapper project)
788791

789792
if (TryGetProjectConfigHandlers(project, out ProjectConfigHandlers handler))
790793
{
791-
handler.SetConfig(project.GetProject(), commandLineArgs, envVars, workDir, launchApp);
794+
handler.SetConfig(project.GetProject(), commandLineArgs, envVars, workDir, launchApp, reason);
795+
792796
}
793797

794-
Logger.Info($"Updated Configuration for Project: {project.GetName()}");
798+
Logger.Info($"Updated Configuration for Project: {project.GetName()} command line: {commandLineArgs}");
795799
}
796800
}
797801

SmartCmdArgs/SmartCmdArgs.Shared/Services/TreeViewEventHandlingService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ private void OnTreeChangedThrottled(object sender, TreeViewModel.TreeChangedEven
8686
{
8787
var projectGuid = e.AffectedProject.Id;
8888
var project = vsHelper.HierarchyForProjectGuid(projectGuid);
89-
projectConfigService.UpdateProjectConfig(project);
89+
projectConfigService.UpdateProjectConfig(project, UpdateProjectConfigReason.TreeChange);
9090
}
9191

9292
private void OnTreeChanged(object sender, TreeViewModel.TreeChangedEventArgs e)

SmartCmdArgs/SmartCmdArgs.Shared/Services/VsEventHandlingService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ private void VsHelper_ProjectWillRun(object sender, EventArgs e)
140140
foreach (var startupProject in treeViewModel.StartupProjects)
141141
{
142142
var project = vsHelper.HierarchyForProjectGuid(startupProject.Id);
143-
projectConfigService.UpdateProjectConfig(project);
143+
projectConfigService.UpdateProjectConfig(project, UpdateProjectConfigReason.RunDebugLaunch);
144144
fileStorage.SaveProject(project);
145145
}
146146
}

SmartCmdArgs/SmartCmdArgs.Shared/ViewModel/ToolWindowViewModel.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Collections.Generic;
33
using System.IO;
44
using System.Linq;
@@ -36,6 +36,13 @@ public bool DisplayTagForCla
3636
set => SetAndNotify(value, ref _displayTagForCla);
3737
}
3838

39+
private SetActiveProfileBehavior _setActiveProfileBehavior;
40+
public SetActiveProfileBehavior SetActiveProfileBehavior
41+
{
42+
get => _setActiveProfileBehavior;
43+
set => SetAndNotify(value, ref _setActiveProfileBehavior);
44+
}
45+
3946

4047
private bool _showDisabledScreen;
4148
public bool ShowDisabledScreen {

0 commit comments

Comments
 (0)