diff --git a/SmallSharp.sln b/SmallSharp.sln
index acae116..6640e99 100644
--- a/SmallSharp.sln
+++ b/SmallSharp.sln
@@ -3,11 +3,10 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30516.212
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SmallSharp", "src\SmallSharp\SmallSharp.csproj", "{F87C7A13-669C-4F18-9266-B256F254DFA3}"
-EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{5420D663-3EA6-419B-8F73-C7EA374CFBBE}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
+ .netconfig = .netconfig
.github\dependabot.yml = .github\dependabot.yml
src\Directory.Build.props = src\Directory.Build.props
src\Directory.Build.targets = src\Directory.Build.targets
@@ -27,7 +26,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{
.github\workflows\sponsors.yml = .github\workflows\sponsors.yml
EndProjectSection
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SmallSharp.Build", "src\SmallSharp.Build\SmallSharp.Build.csproj", "{62834B0C-A2C2-4449-9E2A-00CC390A79BE}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SmallSharp", "src\SmallSharp\SmallSharp.csproj", "{97648980-AA30-4AC0-B8E9-FCF6359F56A0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -35,14 +34,10 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {F87C7A13-669C-4F18-9266-B256F254DFA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {F87C7A13-669C-4F18-9266-B256F254DFA3}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {F87C7A13-669C-4F18-9266-B256F254DFA3}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {F87C7A13-669C-4F18-9266-B256F254DFA3}.Release|Any CPU.Build.0 = Release|Any CPU
- {62834B0C-A2C2-4449-9E2A-00CC390A79BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {62834B0C-A2C2-4449-9E2A-00CC390A79BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {62834B0C-A2C2-4449-9E2A-00CC390A79BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {62834B0C-A2C2-4449-9E2A-00CC390A79BE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {97648980-AA30-4AC0-B8E9-FCF6359F56A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {97648980-AA30-4AC0-B8E9-FCF6359F56A0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {97648980-AA30-4AC0-B8E9-FCF6359F56A0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {97648980-AA30-4AC0-B8E9-FCF6359F56A0}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/src/SmallSharp.Build/MonitorActiveDocument.cs b/src/SmallSharp.Build/MonitorActiveDocument.cs
deleted file mode 100644
index eb8085d..0000000
--- a/src/SmallSharp.Build/MonitorActiveDocument.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-using System;
-using System.Diagnostics;
-using Microsoft.Build.Framework;
-using Microsoft.Build.Utilities;
-
-namespace SmallSharp.Build
-{
- public class MonitorActiveDocument : Task
- {
- [Required]
- public string? FlagFile { get; set; }
-
- [Required]
- public string? LaunchProfiles { get; set; }
-
- [Required]
- public string? UserFile { get; set; }
-
- public override bool Execute()
- {
- if (LaunchProfiles == null || UserFile == null || FlagFile == null)
- return true;
-
- try
- {
- if (BuildEngine4.GetRegisteredTaskObject(nameof(ActiveDocumentMonitor), RegisteredTaskObjectLifetime.AppDomain) is not ActiveDocumentMonitor monitor)
- {
- if (WindowsInterop.GetServiceProvider() is IServiceProvider services)
- {
- var documentMonitor = new ActiveDocumentMonitor(LaunchProfiles, UserFile, FlagFile, services);
-
- BuildEngine4.RegisterTaskObject(nameof(ActiveDocumentMonitor), documentMonitor,
- RegisteredTaskObjectLifetime.AppDomain, false);
-
- // Start monitoring at the end of the build, to avoid slowing down the DTB
- BuildEngine4.RegisterTaskObject("StartMonitor",
- new DisposableAction(() => documentMonitor.Start()),
- RegisteredTaskObjectLifetime.Build, false);
- }
- else
- {
- Debug.Fail("Failed to get IServiceProvider to monitor for active document.");
- }
- }
- else
- {
- // NOTE: this means we only support ONE project/launchProfiles per IDE.
- monitor.Refresh(LaunchProfiles, UserFile, FlagFile);
- }
- }
- catch (Exception e)
- {
- Log.LogWarning($"Failed to start active document monitoring: {e}");
- }
-
- return true;
- }
- }
-}
diff --git a/src/SmallSharp.Build/OpenStartupFile.cs b/src/SmallSharp.Build/OpenStartupFile.cs
deleted file mode 100644
index c14e796..0000000
--- a/src/SmallSharp.Build/OpenStartupFile.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-using System.IO;
-using Microsoft.Build.Framework;
-using Microsoft.Build.Utilities;
-
-namespace SmallSharp.Build
-{
- public class OpenStartupFile : Task
- {
- [Required]
- public string? FlagFile { get; set; }
-
- public string? StartupFile { get; set; }
-
- public override bool Execute()
- {
- if (string.IsNullOrEmpty(FlagFile) || string.IsNullOrEmpty(StartupFile))
- return true;
-
- if (!File.Exists(FlagFile) ||
- File.ReadAllText(FlagFile) != StartupFile)
- {
- // This defers the opening until the build completes.
- BuildEngine4.RegisterTaskObject(
- StartupFile,
- new DisposableAction(() => WindowsInterop.EnsureOpened(StartupFile!)),
- RegisteredTaskObjectLifetime.Build, false);
-
- File.WriteAllText(FlagFile, StartupFile);
- }
-
- return true;
- }
- }
-}
diff --git a/src/SmallSharp.Build/SmallSharp.Build.csproj b/src/SmallSharp.Build/SmallSharp.Build.csproj
deleted file mode 100644
index c02eae2..0000000
--- a/src/SmallSharp.Build/SmallSharp.Build.csproj
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
- net472
- build\netstandard2.0
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/SmallSharp.Build/ActiveDocumentMonitor.cs b/src/SmallSharp/ActiveDocumentMonitor.cs
similarity index 56%
rename from src/SmallSharp.Build/ActiveDocumentMonitor.cs
rename to src/SmallSharp/ActiveDocumentMonitor.cs
index d51e9e4..be8a94e 100644
--- a/src/SmallSharp.Build/ActiveDocumentMonitor.cs
+++ b/src/SmallSharp/ActiveDocumentMonitor.cs
@@ -6,121 +6,104 @@
using System.Threading;
using System.Xml.Linq;
using Microsoft.VisualStudio.Shell.Interop;
+using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace SmallSharp.Build
{
- class ActiveDocumentMonitor : MarshalByRefObject, IDisposable, IVsRunningDocTableEvents, IVsSelectionEvents
+ class ActiveDocumentMonitor : MarshalByRefObject, IDisposable, IVsRunningDocTableEvents, IVsSelectionEvents, IVsSolutionEvents
{
- FileSystemWatcher watcher;
- readonly IServiceProvider services;
-
+ IVsSolution? solution;
IVsRunningDocumentTable? rdt;
IVsMonitorSelection? selection;
+
+ uint solutionCookie;
uint rdtCookie;
uint selectionCookie;
string launchProfilesPath;
string userFile;
- string flagFile;
- Dictionary startupFiles = new();
+ Dictionary startupFiles;
+
+ string? activeFile;
- public ActiveDocumentMonitor(string launchProfilesPath, string userFile, string flagFile, IServiceProvider services)
+ public ActiveDocumentMonitor(string launchProfilesPath, string userFile,
+ string[] startupFiles, IServiceProvider services)
{
this.launchProfilesPath = launchProfilesPath;
this.userFile = userFile;
- this.flagFile = flagFile;
- this.services = services;
-
- watcher = new FileSystemWatcher(Path.GetDirectoryName(launchProfilesPath))
- {
- NotifyFilter = NotifyFilters.LastWrite,
- Filter = "launchSettings.json",
- };
-
- watcher.Changed += (_, _) => ReloadProfiles();
- watcher.Created += (_, _) => ReloadProfiles();
- watcher.EnableRaisingEvents = true;
- ReloadProfiles();
- }
+ this.startupFiles = startupFiles.ToDictionary(x => x, StringComparer.OrdinalIgnoreCase);
- public void Start()
- {
+ solution = (IVsSolution)services.GetService(typeof(SVsSolution));
rdt = (IVsRunningDocumentTable)services.GetService(typeof(SVsRunningDocumentTable));
- if (rdt != null)
- rdt.AdviseRunningDocTableEvents(this, out rdtCookie);
-
selection = (IVsMonitorSelection)services.GetService(typeof(SVsShellMonitorSelection));
- if (selection != null)
- selection.AdviseSelectionEvents(this, out selectionCookie);
+
+ EnsureMonitoring();
}
- public void Refresh(string launchProfiles, string userFile, string flagFile)
+ public void Refresh(string launchProfiles, string userFile, string[] startupFiles)
{
launchProfilesPath = launchProfiles;
this.userFile = userFile;
- this.flagFile = flagFile;
- watcher.Path = Path.GetDirectoryName(launchProfiles);
- ReloadProfiles();
- }
+ this.startupFiles = startupFiles.ToDictionary(x => x, StringComparer.OrdinalIgnoreCase);
- void ReloadProfiles()
- {
- if (!File.Exists(launchProfilesPath))
- return;
-
- var maxAttempts = 5;
- var exceptions = new List();
+ EnsureMonitoring();
- for (var i = 0; i < maxAttempts; i++)
- {
- try
- {
- var json = JObject.Parse(File.ReadAllText(launchProfilesPath));
- if (json.Property("profiles") is not JProperty prop ||
- prop.Value is not JObject profiles)
- return;
+ // For new files, we get the update before the new item is added to
+ // msbuild top-level files, so we retry on refresh
+ UpdateStartupFile(activeFile);
+ }
- startupFiles = profiles.Properties().Select(p => p.Name)
- .ToDictionary(x => x, StringComparer.OrdinalIgnoreCase);
+ void EnsureMonitoring()
+ {
+ if (solutionCookie == 0 && solution != null)
+ solution.AdviseSolutionEvents(this, out solutionCookie);
- return;
- }
- catch (Exception e)
- {
- exceptions.Add(e);
- Thread.Sleep(500);
- }
- }
+ if (rdtCookie == 0 && rdt != null)
+ rdt.AdviseRunningDocTableEvents(this, out rdtCookie);
- // NOTE: check exceptions list to see why.
- Debug.Fail("Could not read launchSettings.json");
+ if (selectionCookie == 0 && selection != null)
+ selection.AdviseSelectionEvents(this, out selectionCookie);
}
void UpdateStartupFile(string? path)
{
+ activeFile = path;
+
if (!string.IsNullOrEmpty(path) &&
path!.IndexOfAny(Path.GetInvalidPathChars()) == -1 &&
- Path.GetFileName(path) is string startupFile &&
- startupFiles.ContainsKey(startupFile))
+ startupFiles.TryGetValue(Path.GetFileName(path), out var startupFile))
{
+ var settings = new JObject(
+ new JProperty("profiles", new JObject(
+ new JProperty(startupFile, new JObject(
+ new JProperty("commandName", "Project")
+ ))
+ ))
+ );
+
+ var json = settings.ToString(Formatting.Indented);
+
+ // Only write if different content.
+ if (File.Exists(launchProfilesPath) &&
+ File.ReadAllText(launchProfilesPath) == json)
+ return;
+
+ File.WriteAllText(launchProfilesPath, json);
+
try
{
// Get the value as it was exists in the original dictionary,
// since it has to match what the source generator created in the
// launch profiles.
- startupFile = startupFiles[startupFile];
var xdoc = XDocument.Load(userFile);
var active = xdoc
.Descendants("{http://schemas.microsoft.com/developer/msbuild/2003}ActiveDebugProfile")
.FirstOrDefault();
- if (active != null && active.Value != startupFile)
+ if (active != null && !startupFile.Equals(active.Value, StringComparison.OrdinalIgnoreCase))
{
active.Value = startupFile;
- // First save to flag file so we don't cause another open
- // attempt via the OpenStartupFile task.
- File.WriteAllText(flagFile, startupFile);
xdoc.Save(userFile);
}
}
@@ -131,15 +114,22 @@ void UpdateStartupFile(string? path)
}
}
- void IDisposable.Dispose()
+ public void Dispose()
{
+ if (solutionCookie != 0 && solution != null)
+ Try(() => solution.UnadviseSolutionEvents(solutionCookie));
+
+ solutionCookie = 0;
+
if (rdtCookie != 0 && rdt != null)
Try(() => rdt.UnadviseRunningDocTableEvents(rdtCookie));
+ rdtCookie = 0;
+
if (selectionCookie != 0 && selection != null)
Try(() => selection.UnadviseSelectionEvents(selectionCookie));
- watcher.Dispose();
+ selectionCookie = 0;
}
void Try(Action action)
@@ -176,18 +166,32 @@ int IVsSelectionEvents.OnSelectionChanged(IVsHierarchy pHierOld, uint itemidOld,
return 0;
}
- int IVsRunningDocTableEvents.OnAfterFirstDocumentLock(uint docCookie, uint dwRDTLockType, uint dwReadLocksRemaining, uint dwEditLocksRemaining) => 0;
+ int IVsSolutionEvents.OnBeforeUnloadProject(IVsHierarchy pRealHierarchy, IVsHierarchy pStubHierarchy)
+ {
+ Dispose();
+ return 0;
+ }
- int IVsRunningDocTableEvents.OnBeforeLastDocumentUnlock(uint docCookie, uint dwRDTLockType, uint dwReadLocksRemaining, uint dwEditLocksRemaining) => 0;
+ int IVsSolutionEvents.OnBeforeCloseSolution(object pUnkReserved)
+ {
+ Dispose();
+ return 0;
+ }
+ int IVsRunningDocTableEvents.OnAfterFirstDocumentLock(uint docCookie, uint dwRDTLockType, uint dwReadLocksRemaining, uint dwEditLocksRemaining) => 0;
+ int IVsRunningDocTableEvents.OnBeforeLastDocumentUnlock(uint docCookie, uint dwRDTLockType, uint dwReadLocksRemaining, uint dwEditLocksRemaining) => 0;
int IVsRunningDocTableEvents.OnAfterSave(uint docCookie) => 0;
-
int IVsRunningDocTableEvents.OnBeforeDocumentWindowShow(uint docCookie, int fFirstShow, IVsWindowFrame pFrame) => 0;
-
int IVsRunningDocTableEvents.OnAfterDocumentWindowHide(uint docCookie, IVsWindowFrame pFrame) => 0;
-
int IVsSelectionEvents.OnElementValueChanged(uint elementid, object varValueOld, object varValueNew) => 0;
-
int IVsSelectionEvents.OnCmdUIContextChanged(uint dwCmdUICookie, int fActive) => 0;
+ int IVsSolutionEvents.OnAfterOpenProject(IVsHierarchy pHierarchy, int fAdded) => throw new NotImplementedException();
+ int IVsSolutionEvents.OnQueryCloseProject(IVsHierarchy pHierarchy, int fRemoving, ref int pfCancel) => throw new NotImplementedException();
+ int IVsSolutionEvents.OnBeforeCloseProject(IVsHierarchy pHierarchy, int fRemoved) => throw new NotImplementedException();
+ int IVsSolutionEvents.OnAfterLoadProject(IVsHierarchy pStubHierarchy, IVsHierarchy pRealHierarchy) => throw new NotImplementedException();
+ int IVsSolutionEvents.OnQueryUnloadProject(IVsHierarchy pRealHierarchy, ref int pfCancel) => throw new NotImplementedException();
+ int IVsSolutionEvents.OnAfterOpenSolution(object pUnkReserved, int fNewSolution) => throw new NotImplementedException();
+ int IVsSolutionEvents.OnQueryCloseSolution(object pUnkReserved, ref int pfCancel) => throw new NotImplementedException();
+ int IVsSolutionEvents.OnAfterCloseSolution(object pUnkReserved) => throw new NotImplementedException();
}
}
diff --git a/src/SmallSharp/AnalyzerConfigOptionsExtensions.cs b/src/SmallSharp/AnalyzerConfigOptionsExtensions.cs
deleted file mode 100644
index 4875954..0000000
--- a/src/SmallSharp/AnalyzerConfigOptionsExtensions.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using Microsoft.CodeAnalysis.Diagnostics;
-
-namespace SmallSharp
-{
- static class AnalyzerConfigOptionsExtensions
- {
- public static bool IsEnabled(this AnalyzerOptions options, string optionName)
- => IsEnabled(options.AnalyzerConfigOptionsProvider.GlobalOptions, optionName);
-
- public static bool IsEnabled(this AnalyzerConfigOptionsProvider options, string optionName)
- => IsEnabled(options.GlobalOptions, optionName);
-
- public static bool IsEnabled(this AnalyzerConfigOptions options, string optionName)
- => options.TryGetValue("build_property." + optionName, out var value) && bool.TryParse(value, out var enabled) && enabled;
- }
-}
diff --git a/src/SmallSharp/DebuggerExtension.cs b/src/SmallSharp/DebuggerExtension.cs
deleted file mode 100644
index bac4ca8..0000000
--- a/src/SmallSharp/DebuggerExtension.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using System.Diagnostics;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.Diagnostics;
-
-namespace SmallSharp
-{
- static class DebuggerExtension
- {
- //[Conditional("DEBUG")]
- public static void CheckDebugger(this GeneratorExecutionContext context, string generatorName = nameof(SmallSharp))
- => context.AnalyzerConfigOptions.CheckDebugger(generatorName);
-
- public static void CheckDebugger(this AnalyzerConfigOptionsProvider provider, string generatorName = nameof(SmallSharp))
- {
- if (Process.GetCurrentProcess().ProcessName == "devenv")
- return;
-
- if (provider.IsEnabled("DebugSourceGenerators") ||
- provider.IsEnabled("Debug" + generatorName))
- Debugger.Launch();
- }
- }
-}
diff --git a/src/SmallSharp.Build/DisposableAction.cs b/src/SmallSharp/DisposableAction.cs
similarity index 100%
rename from src/SmallSharp.Build/DisposableAction.cs
rename to src/SmallSharp/DisposableAction.cs
diff --git a/src/SmallSharp/LaunchSettingsGenerator.cs b/src/SmallSharp/LaunchSettingsGenerator.cs
deleted file mode 100644
index 51e3e04..0000000
--- a/src/SmallSharp/LaunchSettingsGenerator.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-using System.IO;
-using System.Linq;
-using Microsoft.CodeAnalysis;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-
-namespace SmallSharp
-{
- [Generator]
- public class LaunchSettingsGenerator : ISourceGenerator
- {
- public void Initialize(GeneratorInitializationContext context) { }
-
- public void Execute(GeneratorExecutionContext context)
- {
- context.CheckDebugger();
-
- var documents = from additional in context.AdditionalFiles
- let options = context.AnalyzerConfigOptions.GetOptions(additional)
- let compile = options.TryGetValue("build_metadata.AdditionalFiles.SourceItemType", out var itemType) && itemType == "Compile"
- where compile
- select additional.Path;
-
- var settings = new JObject(
- new JProperty("profiles", new JObject(
- documents.OrderBy(path => Path.GetFileName(path)).Select(path => new JProperty(Path.GetFileName(path), new JObject(
- new JProperty("commandName", "Project")
- )))
- ))
- );
-
- if (context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.MSBuildProjectDirectory", out var directory))
- {
- Directory.CreateDirectory(Path.Combine(directory, "Properties"));
- var filePath = Path.Combine(directory, "Properties", "launchSettings.json");
- var json = settings.ToString(Formatting.Indented);
-
- // Only write if different content.
- if (File.Exists(filePath) &&
- File.ReadAllText(filePath) == json)
- return;
-
- File.WriteAllText(filePath, json);
- }
- }
- }
-}
diff --git a/src/SmallSharp/MonitorActiveDocument.cs b/src/SmallSharp/MonitorActiveDocument.cs
new file mode 100644
index 0000000..e056bd3
--- /dev/null
+++ b/src/SmallSharp/MonitorActiveDocument.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+
+namespace SmallSharp.Build
+{
+ public class MonitorActiveDocument : Task
+ {
+ [Required]
+ public string? LaunchProfiles { get; set; }
+
+ [Required]
+ public string? UserFile { get; set; }
+
+ [Required]
+ public ITaskItem[] StartupFiles { get; set; } = Array.Empty();
+
+ public override bool Execute()
+ {
+ if (string.IsNullOrEmpty(LaunchProfiles) ||
+ string.IsNullOrEmpty(UserFile))
+ {
+ Debug.Fail("Should have gotten something to monitor");
+ return true;
+ }
+
+ try
+ {
+ if (BuildEngine4.GetRegisteredTaskObject(nameof(ActiveDocumentMonitor), RegisteredTaskObjectLifetime.AppDomain) is not ActiveDocumentMonitor monitor)
+ {
+ var maxAttempts = 5;
+ for (var i = 0; i < maxAttempts; i++)
+ {
+ if (WindowsInterop.GetServiceProvider() is IServiceProvider services)
+ {
+ BuildEngine4.RegisterTaskObject(nameof(ActiveDocumentMonitor),
+ new ActiveDocumentMonitor(LaunchProfiles!, UserFile!,
+ StartupFiles.Select(x => x.ItemSpec).ToArray(), services),
+ RegisteredTaskObjectLifetime.AppDomain, false);
+
+ return true;
+ }
+ else
+ {
+ BuildEngine4.Yield();
+ Thread.Sleep(200);
+ }
+ }
+
+ Debug.Fail("Failed to get IServiceProvider to monitor for active document.");
+ }
+ else
+ {
+ // NOTE: this means we only support ONE project/launchProfiles per IDE.
+ monitor.Refresh(LaunchProfiles!, UserFile!,
+ StartupFiles.Select(x => x.ItemSpec).ToArray());
+ }
+ }
+ catch (Exception e)
+ {
+ Log.LogWarning($"Failed to start active document monitoring: {e}");
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/src/SmallSharp.Build/NativeMethods.cs b/src/SmallSharp/NativeMethods.cs
similarity index 88%
rename from src/SmallSharp.Build/NativeMethods.cs
rename to src/SmallSharp/NativeMethods.cs
index 4b645b3..1ac2ba9 100644
--- a/src/SmallSharp.Build/NativeMethods.cs
+++ b/src/SmallSharp/NativeMethods.cs
@@ -2,6 +2,7 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
+using System.Text;
internal static class NativeMethods
{
@@ -15,6 +16,21 @@ internal static class NativeMethods
public static readonly Guid IID_IObjectWithSite = typeof(Microsoft.VisualStudio.OLE.Interop.IObjectWithSite).GUID;
public static Guid IID_IUnknown = new Guid("00000000-0000-0000-C000-000000000046");
+ [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
+ internal static extern int GetShortPathName(
+ [MarshalAs(UnmanagedType.LPTStr)]
+ string path,
+ [MarshalAs(UnmanagedType.LPTStr)]
+ StringBuilder shortPath,
+ int shortPathLength);
+
+ internal static string GetShortPath(string path)
+ {
+ var shortPath = new StringBuilder(MAX_PATH);
+ GetShortPathName(path, shortPath, MAX_PATH);
+ return shortPath.ToString();
+ }
+
[DllImport("ole32.dll")]
internal static extern int CoRegisterMessageFilter(IMessageFilter lpMessageFilter, out IMessageFilter lplpMessageFilter);
[DllImport("ole32.dll")]
diff --git a/src/SmallSharp/SmallSharp.csproj b/src/SmallSharp/SmallSharp.csproj
index 016c170..2aac7af 100644
--- a/src/SmallSharp/SmallSharp.csproj
+++ b/src/SmallSharp/SmallSharp.csproj
@@ -1,26 +1,32 @@
- netstandard2.0
+ net472
SmallSharp
Create, edit and run multiple C# 9.0 top-level programs in the same project 😍
- analyzers\dotnet\cs
+ build\netstandard2.0
+ true
+
-
+
+
+
+
+
-
+
+
-
-
+
-
+
\ No newline at end of file
diff --git a/src/SmallSharp.Build/SmallSharp.targets b/src/SmallSharp/SmallSharp.targets
similarity index 61%
rename from src/SmallSharp.Build/SmallSharp.targets
rename to src/SmallSharp/SmallSharp.targets
index d8023db..142c723 100644
--- a/src/SmallSharp.Build/SmallSharp.targets
+++ b/src/SmallSharp/SmallSharp.targets
@@ -1,23 +1,23 @@
-
-
+
$(MSBuildVersion.TrimEnd('0123456789').TrimEnd('.'))
+
+ *$(DefaultLanguageSourceExtension)
+
$(ActiveDebugProfile)
+ CollectStartupFile;SelectStartupFile;SelectTopLevelCompile
-
-
-
-
-
-
+
+
+
@@ -27,23 +27,38 @@
-
+
+
+
+
+
+
+
-
-
-
+
-
+
+
+
+
+
+
+
+
+
true
-
-
+
%(ReversedCompile.Identity)
@@ -117,7 +132,7 @@
@@ -126,39 +141,9 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
diff --git a/src/SmallSharp.Build/WindowsInterop.cs b/src/SmallSharp/WindowsInterop.cs
similarity index 86%
rename from src/SmallSharp.Build/WindowsInterop.cs
rename to src/SmallSharp/WindowsInterop.cs
index b727acc..734dadb 100644
--- a/src/SmallSharp.Build/WindowsInterop.cs
+++ b/src/SmallSharp/WindowsInterop.cs
@@ -14,39 +14,6 @@ static class WindowsInterop
{
static readonly Regex versionExpr = new Regex(@"Microsoft Visual Studio (?\d\d\.\d)", RegexOptions.Compiled | RegexOptions.ExplicitCapture);
- public static void EnsureOpened(string filePath, TimeSpan delay = default)
- {
- if (Environment.OSVersion.Platform != PlatformID.Win32NT)
- return;
-
- if (delay != default)
- Thread.Sleep(delay);
-
- var dte = GetDTE();
- if (dte == null)
- return;
-
- var maxAttempts = 5;
- var exceptions = new List();
-
- for (var i = 0; i < maxAttempts; i++)
- {
- try
- {
- dte.ExecuteCommand("File.OpenFile", filePath);
- return;
- }
- catch (Exception e)
- {
- exceptions.Add(e);
- Thread.Sleep(500);
- }
- }
-
- // NOTE: inspect exceptions variable
- Debug.Fail($"Failed to open {filePath} after 5 attempts.");
- }
-
public static IServiceProvider? GetServiceProvider(TimeSpan delay = default)
{
if (Environment.OSVersion.Platform != PlatformID.Win32NT)