mirror of https://github.com/winsw/winsw
Increase code coverage
parent
4414e36f6b
commit
b85593eb11
|
@ -4,6 +4,15 @@
|
|||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<DebugType>full</DebugType>
|
||||
<ArtifactsDir>$(MSBuildThisFileDirectory)artifacts\</ArtifactsDir>
|
||||
<ArtifactsBinDir>$(ArtifactsDir)bin\</ArtifactsBinDir>
|
||||
<ArtifactsObjDir>$(ArtifactsDir)obj\</ArtifactsObjDir>
|
||||
<ArtifactsPublishDir>$(ArtifactsDir)publish\</ArtifactsPublishDir>
|
||||
<RunSettingsFilePath>$(MSBuildThisFileDirectory)src\.runsettings</RunSettingsFilePath>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<BaseOutputPath>$(ArtifactsBinDir)$(MSBuildProjectName)\</BaseOutputPath>
|
||||
<BaseIntermediateOutputPath>$(ArtifactsObjDir)$(MSBuildProjectName)\</BaseIntermediateOutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -25,7 +25,7 @@ More info about the wrapper is available in the projects GitHub repository.
|
|||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="artifacts\WinSW.NET461.exe" target="lib\net461\WinSW.NET461.exe" />
|
||||
<file src="artifacts\publish\WinSW.NET461.exe" target="lib\net461\WinSW.NET461.exe" />
|
||||
<file src="samples\sample-complete.xml" target="lib\net461\WinSW.NET461.xml" />
|
||||
</files>
|
||||
</package>
|
||||
|
|
|
@ -50,7 +50,7 @@ jobs:
|
|||
inputs:
|
||||
command: test
|
||||
projects: src\WinSW.Tests\WinSW.Tests.csproj
|
||||
arguments: -c $(BuildConfiguration) --no-build
|
||||
arguments: -c $(BuildConfiguration) --collect "XPlat Code Coverage" --no-build
|
||||
- task: NuGetToolInstaller@1
|
||||
displayName: Install Nuget
|
||||
inputs:
|
||||
|
@ -62,19 +62,19 @@ jobs:
|
|||
packagesToPack: WinSW.nuspec
|
||||
versioningScheme: byEnvVar
|
||||
versionEnvVar: BuildVersion
|
||||
- publish: artifacts\WinSW.NET461.exe
|
||||
- publish: artifacts\publish\WinSW.NET461.exe
|
||||
artifact: WinSW.NET461.exe_$(BuildConfiguration)
|
||||
displayName: Publish .NET 4.6.1
|
||||
- publish: artifacts\WinSW.NETCore.x64.zip
|
||||
- publish: artifacts\publish\WinSW.NETCore.x64.zip
|
||||
artifact: WinSW.NETCore.x64.zip_$(BuildConfiguration)
|
||||
displayName: Publish .NET Core x64 .zip
|
||||
- publish: artifacts\WinSW.NETCore.x86.zip
|
||||
- publish: artifacts\publish\WinSW.NETCore.x86.zip
|
||||
artifact: WinSW.NETCore.x86.zip_$(BuildConfiguration)
|
||||
displayName: Publish .NET Core x86 .zip
|
||||
- publish: artifacts\WinSW.NETCore.x64.exe
|
||||
- publish: artifacts\publish\WinSW.NETCore.x64.exe
|
||||
artifact: WinSW.NETCore.x64.exe_$(BuildConfiguration)
|
||||
displayName: Publish .NET Core x64 .exe
|
||||
- publish: artifacts\WinSW.NETCore.x86.exe
|
||||
- publish: artifacts\publish\WinSW.NETCore.x86.exe
|
||||
artifact: WinSW.NETCore.x86.exe_$(BuildConfiguration)
|
||||
displayName: Publish .NET Core x86 .exe
|
||||
- publish: $(Build.ArtifactStagingDirectory)\WinSW.$(BuildVersion).nupkg
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RunSettings>
|
||||
<RunConfiguration>
|
||||
<TargetPlatform>x64</TargetPlatform>
|
||||
</RunConfiguration>
|
||||
</RunSettings>
|
|
@ -22,7 +22,7 @@ namespace WinSW.Configuration
|
|||
|
||||
public abstract string Executable { get; }
|
||||
|
||||
public string ExecutablePath => Process.GetCurrentProcess().MainModule.FileName;
|
||||
public virtual string ExecutablePath => Process.GetCurrentProcess().MainModule.FileName;
|
||||
|
||||
public virtual bool HideWindow => false;
|
||||
|
||||
|
|
|
@ -30,14 +30,14 @@ namespace WinSW
|
|||
///
|
||||
/// This string is "c:\abc\def\ghi" when the configuration XML is "c:\abc\def\ghi.xml"
|
||||
/// </summary>
|
||||
public string BasePath { get; set; }
|
||||
public virtual string BasePath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The file name portion of the configuration file.
|
||||
///
|
||||
/// In the above example, this would be "ghi".
|
||||
/// </summary>
|
||||
public string BaseName { get; set; }
|
||||
public virtual string BaseName { get; set; }
|
||||
|
||||
/// <exception cref="FileNotFoundException" />
|
||||
public XmlServiceConfig(string path)
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.ServiceProcess;
|
||||
using WinSW.Tests.Util;
|
||||
using Xunit;
|
||||
using Helper = WinSW.Tests.Util.CommandLineTestHelper;
|
||||
|
||||
namespace WinSW.Tests
|
||||
{
|
||||
public class CommandLineTests
|
||||
{
|
||||
[ElevatedFact]
|
||||
public void Install_Start_Stop_Uninstall_Console_App()
|
||||
{
|
||||
using var config = Helper.TestXmlServiceConfig.FromXml(Helper.SeedXml);
|
||||
|
||||
try
|
||||
{
|
||||
_ = Helper.Test(new[] { "install", config.FullPath }, config);
|
||||
|
||||
using var controller = new ServiceController(Helper.Name);
|
||||
Assert.Equal(Helper.DisplayName, controller.DisplayName);
|
||||
Assert.False(controller.CanStop);
|
||||
Assert.False(controller.CanShutdown);
|
||||
Assert.False(controller.CanPauseAndContinue);
|
||||
Assert.Equal(ServiceControllerStatus.Stopped, controller.Status);
|
||||
Assert.Equal(ServiceType.Win32OwnProcess, controller.ServiceType);
|
||||
|
||||
#if NETFRAMEWORK
|
||||
InterProcessCodeCoverageSession session = null;
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
_ = Helper.Test(new[] { "start", config.FullPath }, config);
|
||||
controller.Refresh();
|
||||
Assert.Equal(ServiceControllerStatus.Running, controller.Status);
|
||||
Assert.True(controller.CanStop);
|
||||
|
||||
if (Environment.GetEnvironmentVariable("System.DefinitionId") != null)
|
||||
{
|
||||
session = new InterProcessCodeCoverageSession(Helper.Name);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_ = Helper.Test(new[] { "stop", config.FullPath }, config);
|
||||
controller.Refresh();
|
||||
Assert.Equal(ServiceControllerStatus.Stopped, controller.Status);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
session?.Wait();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
finally
|
||||
{
|
||||
_ = Helper.Test(new[] { "uninstall", config.FullPath }, config);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FailOnUnknownCommand()
|
||||
{
|
||||
const string commandName = "unknown";
|
||||
|
||||
CommandLineTestResult result = Helper.ErrorTest(new[] { commandName });
|
||||
|
||||
Assert.Equal($"Unrecognized command or argument '{commandName}'\r\n\r\n", result.Error);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// https://github.com/kohsuke/winsw/issues/206
|
||||
/// </summary>
|
||||
[Fact(Skip = "unknown")]
|
||||
public void ShouldNotPrintLogsForStatusCommand()
|
||||
{
|
||||
string cliOut = Helper.Test(new[] { "status" });
|
||||
Assert.Equal("NonExistent" + Environment.NewLine, cliOut);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Customize()
|
||||
{
|
||||
const string OldCompanyName = "CloudBees, Inc.";
|
||||
const string NewCompanyName = "CLOUDBEES, INC.";
|
||||
|
||||
string inputPath = Layout.WinSWExe;
|
||||
|
||||
Assert.Equal(OldCompanyName, FileVersionInfo.GetVersionInfo(inputPath).CompanyName);
|
||||
|
||||
// deny write access
|
||||
using FileStream file = File.OpenRead(inputPath);
|
||||
|
||||
string outputPath = Path.GetTempFileName();
|
||||
Program.TestExecutablePath = inputPath;
|
||||
try
|
||||
{
|
||||
_ = Helper.Test(new[] { "customize", "-o", outputPath, "--manufacturer", NewCompanyName });
|
||||
|
||||
Assert.Equal(NewCompanyName, FileVersionInfo.GetVersionInfo(outputPath).CompanyName);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Program.TestExecutablePath = null;
|
||||
File.Delete(outputPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.ServiceProcess;
|
||||
using WinSW.Tests.Util;
|
||||
using Xunit;
|
||||
|
||||
namespace WinSW.Tests
|
||||
{
|
||||
public class MainTest
|
||||
{
|
||||
[ElevatedFact]
|
||||
public void TestInstall()
|
||||
{
|
||||
try
|
||||
{
|
||||
_ = CommandLineTestHelper.Test(new[] { "install" });
|
||||
|
||||
using ServiceController controller = new ServiceController(CommandLineTestHelper.Id);
|
||||
Assert.Equal(CommandLineTestHelper.Name, controller.DisplayName);
|
||||
Assert.False(controller.CanStop);
|
||||
Assert.False(controller.CanShutdown);
|
||||
Assert.False(controller.CanPauseAndContinue);
|
||||
Assert.Equal(ServiceControllerStatus.Stopped, controller.Status);
|
||||
Assert.Equal(ServiceType.Win32OwnProcess, controller.ServiceType);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_ = CommandLineTestHelper.Test(new[] { "uninstall" });
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FailOnUnknownCommand()
|
||||
{
|
||||
const string commandName = "unknown";
|
||||
|
||||
CommandLineTestResult result = CommandLineTestHelper.ErrorTest(new[] { commandName });
|
||||
|
||||
Assert.Equal($"Unrecognized command or argument '{commandName}'\r\n\r\n", result.Error);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// https://github.com/kohsuke/winsw/issues/206
|
||||
/// </summary>
|
||||
[Fact(Skip = "unknown")]
|
||||
public void ShouldNotPrintLogsForStatusCommand()
|
||||
{
|
||||
string cliOut = CommandLineTestHelper.Test(new[] { "status" });
|
||||
Assert.Equal("NonExistent" + Environment.NewLine, cliOut);
|
||||
}
|
||||
|
||||
#if NET461
|
||||
[Fact]
|
||||
public void Customize()
|
||||
{
|
||||
const string OldCompanyName = "CloudBees, Inc.";
|
||||
const string NewCompanyName = "CLOUDBEES, INC.";
|
||||
|
||||
string inputPath = Path.Combine(Layout.ArtifactsDirectory, "WinSW.NET461.exe");
|
||||
|
||||
Assert.Equal(OldCompanyName, FileVersionInfo.GetVersionInfo(inputPath).CompanyName);
|
||||
|
||||
// deny write access
|
||||
using FileStream file = File.OpenRead(inputPath);
|
||||
|
||||
string outputPath = Path.GetTempFileName();
|
||||
Program.TestExecutablePath = inputPath;
|
||||
try
|
||||
{
|
||||
_ = CommandLineTestHelper.Test(new[] { "customize", "-o", outputPath, "--manufacturer", NewCompanyName });
|
||||
|
||||
Assert.Equal(NewCompanyName, FileVersionInfo.GetVersionInfo(outputPath).CompanyName);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Program.TestExecutablePath = null;
|
||||
File.Delete(outputPath);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
#if NET461
|
||||
#if NETFRAMEWORK
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection.Metadata;
|
||||
|
@ -15,8 +15,7 @@ namespace WinSW.Tests
|
|||
{
|
||||
var version = new Version(4, 0, 0, 0);
|
||||
|
||||
using var file = File.OpenRead(Path.Combine(Layout.ArtifactsDirectory, "WinSW.NET461.exe"));
|
||||
using var peReader = new PEReader(file);
|
||||
using var peReader = new PEReader(File.OpenRead(Layout.NET461Exe));
|
||||
var metadataReader = peReader.GetMetadataReader();
|
||||
foreach (var handle in metadataReader.AssemblyReferences)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
using Xunit;
|
||||
|
||||
namespace WinSW.Tests.Util
|
||||
{
|
||||
internal static class AssertEx
|
||||
{
|
||||
internal static void Succeeded(int hr) => Assert.InRange(hr, 0, int.MaxValue);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Xml;
|
||||
using Xunit;
|
||||
|
||||
namespace WinSW.Tests.Util
|
||||
|
@ -9,22 +11,18 @@ namespace WinSW.Tests.Util
|
|||
/// </summary>
|
||||
public static class CommandLineTestHelper
|
||||
{
|
||||
public const string Id = "WinSW.Tests";
|
||||
public const string Name = "WinSW Test Service";
|
||||
public const string Name = "WinSW.Tests";
|
||||
public const string DisplayName = "WinSW Test Service";
|
||||
|
||||
private static readonly string SeedXml =
|
||||
internal static readonly string SeedXml =
|
||||
$@"<service>
|
||||
<id>{Id}</id>
|
||||
<name>{Name}</name>
|
||||
<description>The service.</description>
|
||||
<executable>node.exe</executable>
|
||||
<arguments>My Arguments</arguments>
|
||||
<log mode=""roll""></log>
|
||||
<workingdirectory>C:\winsw\workdir</workingdirectory>
|
||||
<logpath>C:\winsw\logs</logpath>
|
||||
<id>{Name}</id>
|
||||
<name>{DisplayName}</name>
|
||||
<executable>cmd.exe</executable>
|
||||
<arguments>/c timeout /t -1 /nobreak</arguments>
|
||||
</service>";
|
||||
|
||||
public static readonly XmlServiceConfig DefaultServiceConfig = XmlServiceConfig.FromXml(SeedXml);
|
||||
private static readonly XmlServiceConfig DefaultServiceConfig = XmlServiceConfig.FromXml(SeedXml);
|
||||
|
||||
/// <summary>
|
||||
/// Runs a simle test, which returns the output CLI
|
||||
|
@ -97,6 +95,69 @@ $@"<service>
|
|||
|
||||
return new CommandLineTestResult(swOut.ToString(), swError.ToString(), exception);
|
||||
}
|
||||
|
||||
internal sealed class TestXmlServiceConfig : XmlServiceConfig, IDisposable
|
||||
{
|
||||
private readonly string directory;
|
||||
|
||||
private bool disposed;
|
||||
|
||||
internal TestXmlServiceConfig(XmlDocument document, string name)
|
||||
: base(document)
|
||||
{
|
||||
string directory = this.directory = Path.Combine(Path.GetTempPath(), name);
|
||||
_ = Directory.CreateDirectory(directory);
|
||||
|
||||
try
|
||||
{
|
||||
string path = this.FullPath = Path.Combine(directory, "config.xml");
|
||||
using (var file = File.CreateText(path))
|
||||
{
|
||||
file.Write(SeedXml);
|
||||
}
|
||||
|
||||
this.BaseName = name;
|
||||
this.BasePath = Path.Combine(directory, name);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Directory.Delete(directory, true);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
~TestXmlServiceConfig() => this.Dispose(false);
|
||||
|
||||
public override string FullPath { get; }
|
||||
|
||||
public override string BasePath { get; }
|
||||
|
||||
public override string BaseName { get; set; }
|
||||
|
||||
public override string ExecutablePath => Layout.WinSWExe;
|
||||
|
||||
internal static TestXmlServiceConfig FromXml(string xml, [CallerMemberName] string name = null)
|
||||
{
|
||||
var document = new XmlDocument();
|
||||
document.LoadXml(xml);
|
||||
return new TestXmlServiceConfig(document, name);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
this.Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private void Dispose(bool _)
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
Directory.Delete(this.directory, true);
|
||||
disposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -0,0 +1,191 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using Microsoft.Diagnostics.Runtime;
|
||||
using Microsoft.Diagnostics.Runtime.Interop;
|
||||
using WinSW.Native;
|
||||
using Xunit;
|
||||
|
||||
namespace WinSW.Tests.Util
|
||||
{
|
||||
internal sealed class InterProcessCodeCoverageSession : IDebugEventCallbacks
|
||||
{
|
||||
private readonly Type trackerType;
|
||||
private readonly FieldInfo hitsField;
|
||||
|
||||
private readonly IDebugControl control;
|
||||
private readonly DataTarget target;
|
||||
private readonly Thread thread;
|
||||
|
||||
private List<Exception> exceptions;
|
||||
private bool exited;
|
||||
|
||||
internal InterProcessCodeCoverageSession(string serviceName)
|
||||
{
|
||||
var trackerType = this.trackerType = typeof(Program).Assembly.GetTypes().Single(type => type.Namespace == "Coverlet.Core.Instrumentation.Tracker");
|
||||
var hitsField = this.hitsField = trackerType.GetField("HitsArray", BindingFlags.Public | BindingFlags.Static);
|
||||
Assert.NotNull(hitsField);
|
||||
|
||||
using var scm = ServiceManager.Open();
|
||||
using var sc = scm.OpenService(serviceName, ServiceApis.ServiceAccess.QUERY_STATUS);
|
||||
|
||||
int processId = sc.ProcessId;
|
||||
Assert.True(processId >= 0);
|
||||
|
||||
var guid = new Guid("27fe5639-8407-4f47-8364-ee118fb08ac8");
|
||||
int hr = Native.DebugCreate(guid, out object unknown);
|
||||
AssertEx.Succeeded(hr);
|
||||
|
||||
var client = (IDebugClient)unknown;
|
||||
this.control = (IDebugControl)unknown;
|
||||
|
||||
hr = client.AttachProcess(0, (uint)processId, DEBUG_ATTACH.DEFAULT);
|
||||
AssertEx.Succeeded(hr);
|
||||
|
||||
hr = client.SetEventCallbacks(this);
|
||||
AssertEx.Succeeded(hr);
|
||||
|
||||
IntPtr pointer = Marshal.GetIUnknownForObject(client);
|
||||
Assert.Equal(1, Marshal.Release(pointer));
|
||||
|
||||
target = DataTarget.CreateFromDbgEng(pointer);
|
||||
|
||||
var thread = this.thread = new Thread(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
using (this.target)
|
||||
{
|
||||
do
|
||||
{
|
||||
int hr = this.control.WaitForEvent(DEBUG_WAIT.DEFAULT, 0xffffffff);
|
||||
AssertEx.Succeeded(hr);
|
||||
}
|
||||
while (!this.exited);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
(this.exceptions ??= new List<Exception>()).Add(e);
|
||||
}
|
||||
});
|
||||
thread.Start();
|
||||
}
|
||||
|
||||
/// <exception cref="AggregateException" />
|
||||
internal void Wait()
|
||||
{
|
||||
this.thread.Join();
|
||||
|
||||
if (this.exceptions != null)
|
||||
{
|
||||
throw new AggregateException(this.exceptions);
|
||||
}
|
||||
}
|
||||
|
||||
int IDebugEventCallbacks.GetInterestMask(out DEBUG_EVENT Mask)
|
||||
{
|
||||
Mask = DEBUG_EVENT.EXIT_PROCESS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int IDebugEventCallbacks.Breakpoint(IDebugBreakpoint Bp)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
int IDebugEventCallbacks.Exception(in EXCEPTION_RECORD64 Exception, uint FirstChance)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
int IDebugEventCallbacks.CreateThread(ulong Handle, ulong DataOffset, ulong StartOffset)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
int IDebugEventCallbacks.ExitThread(uint ExitCode)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
int IDebugEventCallbacks.CreateProcess(ulong ImageFileHandle, ulong Handle, ulong BaseOffset, uint ModuleSize, string ModuleName, string ImageName, uint CheckSum, uint TimeDateStamp, ulong InitialThreadHandle, ulong ThreadDataOffset, ulong StartOffset)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
int IDebugEventCallbacks.ExitProcess(uint ExitCode)
|
||||
{
|
||||
this.exited = true;
|
||||
|
||||
try
|
||||
{
|
||||
using var runtime = this.target.ClrVersions.Single().CreateRuntime();
|
||||
|
||||
var module = runtime.EnumerateModules().First(module => module.Name == typeof(Program).Assembly.Location);
|
||||
|
||||
var type = module.GetTypeByName(this.trackerType.FullName);
|
||||
var field = type.GetStaticFieldByName(this.hitsField.Name);
|
||||
var array = field.ReadObject(runtime.AppDomains.Single()).AsArray();
|
||||
|
||||
int[] hits = (int[])this.hitsField.GetValue(null);
|
||||
|
||||
int[] values = array.ReadValues<int>(0, hits.Length);
|
||||
for (int i = 0; i < hits.Length; i++)
|
||||
{
|
||||
hits[i] += values[i];
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
(this.exceptions ??= new List<Exception>()).Add(e);
|
||||
}
|
||||
|
||||
return (int)DEBUG_STATUS.BREAK;
|
||||
}
|
||||
|
||||
int IDebugEventCallbacks.LoadModule(ulong ImageFileHandle, ulong BaseOffset, uint ModuleSize, string ModuleName, string ImageName, uint CheckSum, uint TimeDateStamp)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
int IDebugEventCallbacks.UnloadModule(string ImageBaseName, ulong BaseOffset)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
int IDebugEventCallbacks.SystemError(uint Error, uint Level)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
int IDebugEventCallbacks.SessionStatus(DEBUG_SESSION Status)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
int IDebugEventCallbacks.ChangeDebuggeeState(DEBUG_CDS Flags, ulong Argument)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
int IDebugEventCallbacks.ChangeEngineState(DEBUG_CES Flags, ulong Argument)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
int IDebugEventCallbacks.ChangeSymbolState(DEBUG_CSS Flags, ulong Argument)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private static class Native
|
||||
{
|
||||
[DllImport("dbgeng.dll")]
|
||||
internal static extern int DebugCreate(in Guid InterfaceId, [MarshalAs(UnmanagedType.IUnknown)] out object Interface);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -35,5 +35,14 @@ namespace WinSW.Tests.Util
|
|||
}
|
||||
|
||||
internal static string ArtifactsDirectory => artifactsDirectory ??= Path.Combine(RepositoryRoot, "artifacts");
|
||||
|
||||
internal static string NET461Exe => Path.Combine(ArtifactsDirectory, "publish", "WinSW.NET461.exe");
|
||||
|
||||
internal static string WinSWExe =>
|
||||
#if NETCOREAPP
|
||||
Path.ChangeExtension(typeof(Program).Assembly.Location, ".exe");
|
||||
#else
|
||||
typeof(Program).Assembly.Location;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net461;netcoreapp5.0</TargetFrameworks>
|
||||
<TargetFrameworks>net471;netcoreapp5.0</TargetFrameworks>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
|
@ -10,6 +10,8 @@
|
|||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Diagnostics.Runtime" Version="2.0.137201" />
|
||||
<PackageReference Include="Microsoft.Diagnostics.Runtime.Utilities" Version="2.0.0-rc.20303.3" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.2">
|
||||
|
@ -29,4 +31,24 @@
|
|||
<ProjectReference Include="..\WinSW.Plugins\WinSW.Plugins.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="xunit.runner.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="Copy" BeforeTargets="AfterBuild">
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp5.0'">
|
||||
<_FilesToCopy Include="$(ArtifactsBinDir)WinSW\$(Configuration)\netcoreapp3.1\WinSW.runtimeconfig*.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' != 'netcoreapp5.0'">
|
||||
<_FilesToCopy Include="$(ArtifactsBinDir)WinSW\$(Configuration)\net461\System.ValueTuple.dll" />
|
||||
</ItemGroup>
|
||||
|
||||
<Copy SourceFiles="@(_FilesToCopy)" DestinationFolder="$(OutputPath)" />
|
||||
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"$schema": "https://xunit.net/schema/current/xunit.runner.schema.json",
|
||||
"shadowCopy": false
|
||||
}
|
|
@ -16,6 +16,7 @@ EndProject
|
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{4975DCF4-C32C-43ED-A731-8FCC1F7E6746}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.editorconfig = .editorconfig
|
||||
.runsettings = .runsettings
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
|
|
|
@ -991,16 +991,16 @@ namespace WinSW
|
|||
/// <exception cref="FileNotFoundException" />
|
||||
private static XmlServiceConfig CreateConfig(string? path)
|
||||
{
|
||||
if (path != null)
|
||||
{
|
||||
return new XmlServiceConfig(path);
|
||||
}
|
||||
|
||||
if (TestConfig != null)
|
||||
{
|
||||
return TestConfig;
|
||||
}
|
||||
|
||||
if (path != null)
|
||||
{
|
||||
return new XmlServiceConfig(path);
|
||||
}
|
||||
|
||||
path = Path.ChangeExtension(ExecutablePath, ".xml");
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
|
|
|
@ -38,20 +38,22 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' != 'netcoreapp3.1'">
|
||||
<ProjectReference Include="..\WinSW.Tasks\WinSW.Tasks.csproj" />
|
||||
<ProjectReference Include="..\WinSW.Tasks\WinSW.Tasks.csproj">
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="PublishCoreZip" AfterTargets="Publish" Condition="'$(TargetFramework)' == 'netcoreapp3.1' and '$(PublishSingleFile)' != 'true'">
|
||||
|
||||
<MakeDir Directories="$(ArtifactsDir)" />
|
||||
<ZipDirectory SourceDirectory="$(PublishDir)" DestinationFile="$(ArtifactsDir)WinSW.NETCore.$(PlatformTarget).zip" Overwrite="true" />
|
||||
<MakeDir Directories="$(ArtifactsPublishDir)" />
|
||||
<ZipDirectory SourceDirectory="$(PublishDir)" DestinationFile="$(ArtifactsPublishDir)WinSW.NETCore.$(PlatformTarget).zip" Overwrite="true" />
|
||||
|
||||
</Target>
|
||||
|
||||
<Target Name="PublishCoreExe" AfterTargets="Publish" Condition="'$(TargetFramework)' == 'netcoreapp3.1' and '$(PublishSingleFile)' == 'true'">
|
||||
|
||||
<MakeDir Directories="$(ArtifactsDir)" />
|
||||
<Copy SourceFiles="$(PublishDir)$(TargetName).exe" DestinationFiles="$(ArtifactsDir)WinSW.NETCore.$(PlatformTarget).exe" />
|
||||
<MakeDir Directories="$(ArtifactsPublishDir)" />
|
||||
<Copy SourceFiles="$(PublishDir)$(TargetName).exe" DestinationFiles="$(ArtifactsPublishDir)WinSW.NETCore.$(PlatformTarget).exe" />
|
||||
|
||||
</Target>
|
||||
|
||||
|
@ -73,7 +75,7 @@
|
|||
<InputAssemblies>$(InputAssemblies) "$(OutDir)System.Numerics.Vectors.dll"</InputAssemblies>
|
||||
<InputAssemblies>$(InputAssemblies) "$(OutDir)System.Runtime.CompilerServices.Unsafe.dll"</InputAssemblies>
|
||||
<InputAssemblies>$(InputAssemblies) "$(OutDir)System.ValueTuple.dll"</InputAssemblies>
|
||||
<OutputAssembly>"$(ArtifactsDir)WinSW.$(TargetFrameworkSuffix).exe"</OutputAssembly>
|
||||
<OutputAssembly>"$(ArtifactsPublishDir)WinSW.$(TargetFrameworkSuffix).exe"</OutputAssembly>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
@ -82,14 +84,14 @@
|
|||
<ILMergeCommand>"$(ILMerge)" $(ILMergeArgs)</ILMergeCommand>
|
||||
</PropertyGroup>
|
||||
|
||||
<MakeDir Directories="$(ArtifactsDir)" />
|
||||
<MakeDir Directories="$(ArtifactsPublishDir)" />
|
||||
<Exec Command="$(ILMergeCommand)" />
|
||||
|
||||
</Target>
|
||||
|
||||
<UsingTask TaskName="WinSW.Tasks.Trim" AssemblyFile="..\WinSW.Tasks\bin\$(Configuration)\net461\WinSW.Tasks.dll" />
|
||||
<UsingTask TaskName="WinSW.Tasks.Trim" AssemblyFile="$(ArtifactsBinDir)WinSW.Tasks\$(Configuration)\net461\WinSW.Tasks.dll" />
|
||||
<Target Name="Trim" AfterTargets="Merge" Condition="'$(TargetFramework)' != 'netcoreapp3.1'">
|
||||
<Trim Path="$(ArtifactsDir)WinSW.$(TargetFrameworkSuffix).exe" />
|
||||
<Trim Path="$(ArtifactsPublishDir)WinSW.$(TargetFrameworkSuffix).exe" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
Loading…
Reference in New Issue