mirror of https://github.com/winsw/winsw
Merge shared directory mapping into core
parent
4b00bba644
commit
3c5d67e287
|
@ -77,13 +77,15 @@ namespace WinSW.Configuration
|
|||
public virtual string ErrFilePattern => ".err.log";
|
||||
|
||||
// Environment
|
||||
public virtual List<Download> Downloads => new List<Download>(0);
|
||||
public virtual List<Download> Downloads => new(0);
|
||||
|
||||
public virtual Dictionary<string, string> EnvironmentVariables => new Dictionary<string, string>(0);
|
||||
public virtual Dictionary<string, string> EnvironmentVariables => new(0);
|
||||
|
||||
// Misc
|
||||
public virtual bool BeepOnShutdown => false;
|
||||
|
||||
public virtual List<SharedDirectoryMapperConfig> SharedDirectories => new(0);
|
||||
|
||||
// Extensions
|
||||
public virtual XmlNode? ExtensionsConfiguration => null;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace WinSW
|
|||
/// </summary>
|
||||
public class XmlServiceConfig : ServiceConfig
|
||||
{
|
||||
protected readonly XmlDocument dom = new XmlDocument();
|
||||
protected readonly XmlDocument dom = new();
|
||||
|
||||
private readonly XmlNode root;
|
||||
private readonly Dictionary<string, string> environmentVariables;
|
||||
|
@ -145,7 +145,7 @@ namespace WinSW
|
|||
return value is null ? defaultValue : ParseTimeSpan(value);
|
||||
}
|
||||
|
||||
private static readonly Dictionary<string, long> Suffix = new Dictionary<string, long>
|
||||
private static readonly Dictionary<string, long> Suffix = new()
|
||||
{
|
||||
{ "ms", 1 },
|
||||
{ "sec", 1000L },
|
||||
|
@ -581,6 +581,31 @@ namespace WinSW
|
|||
|
||||
public bool AutoRefresh => this.SingleBoolElementOrDefault("autoRefresh", true);
|
||||
|
||||
public override List<SharedDirectoryMapperConfig> SharedDirectories
|
||||
{
|
||||
get
|
||||
{
|
||||
var mapNodes = this.root.SelectSingleNode("sharedDirectoryMapping")?.SelectNodes("map");
|
||||
if (mapNodes is null)
|
||||
{
|
||||
return new();
|
||||
}
|
||||
|
||||
var result = new List<SharedDirectoryMapperConfig>(mapNodes.Count);
|
||||
for (int i = 0; i < mapNodes.Count; i++)
|
||||
{
|
||||
if (mapNodes[i] is XmlElement mapElement)
|
||||
{
|
||||
string label = XmlHelper.SingleAttribute<string>(mapElement, "label");
|
||||
string uncPath = XmlHelper.SingleAttribute<string>(mapElement, "uncpath");
|
||||
result.Add(new(label, uncPath));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<string, string> LoadEnvironmentVariables()
|
||||
{
|
||||
var nodeList = this.root.SelectNodes("env")!;
|
||||
|
|
|
@ -419,7 +419,7 @@ namespace WinSW
|
|||
private async Task CopyStreamWithRotationAsync(StreamReader reader, string extension)
|
||||
{
|
||||
// lock required as the timer thread and the thread that will write to the stream could try and access the file stream at the same time
|
||||
object? fileLock = new object();
|
||||
object? fileLock = new();
|
||||
|
||||
string? baseDirectory = Path.GetDirectoryName(this.BaseLogFileName)!;
|
||||
string? baseFileName = Path.GetFileName(this.BaseLogFileName);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
internal const string Advapi32 = "advapi32.dll";
|
||||
internal const string CredUI = "credui.dll";
|
||||
internal const string Kernel32 = "kernel32.dll";
|
||||
internal const string Mpr = "mpr.dll";
|
||||
internal const string NtDll = "ntdll.dll";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
#pragma warning disable SA1310 // Field names should not contain underscore
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using static WinSW.Native.Libraries;
|
||||
|
||||
namespace WinSW.Native
|
||||
{
|
||||
internal static class NetworkApis
|
||||
{
|
||||
internal const uint RESOURCETYPE_DISK = 0x00000001;
|
||||
|
||||
[DllImport(Mpr, SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
internal static extern int WNetAddConnection2W(in NETRESOURCEW netResource, string? password = null, string? userName = null, uint flags = 0);
|
||||
|
||||
[DllImport(Mpr, SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
internal static extern int WNetCancelConnection2W(string name, uint flags = 0, bool force = false);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
internal struct NETRESOURCEW
|
||||
{
|
||||
public uint Scope;
|
||||
public uint Type;
|
||||
public uint DisplayType;
|
||||
public uint Usage;
|
||||
public string LocalName;
|
||||
public string RemoteName;
|
||||
public string Comment;
|
||||
public string Provider;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,9 +7,9 @@ namespace WinSW.Native
|
|||
{
|
||||
internal static class ResourceApis
|
||||
{
|
||||
internal static readonly IntPtr VS_VERSION_INFO = new IntPtr(1);
|
||||
internal static readonly IntPtr VS_VERSION_INFO = new(1);
|
||||
|
||||
internal static readonly IntPtr RT_VERSION = new IntPtr(16);
|
||||
internal static readonly IntPtr RT_VERSION = new(16);
|
||||
|
||||
[DllImport(Libraries.Kernel32, SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
internal static extern IntPtr BeginUpdateResourceW(string fileName, bool deleteExistingResources);
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
using System.Collections.Generic;
|
||||
using WinSW.Native;
|
||||
using static WinSW.Native.NetworkApis;
|
||||
|
||||
namespace WinSW
|
||||
{
|
||||
public sealed class SharedDirectoryMapper
|
||||
{
|
||||
private readonly List<SharedDirectoryMapperConfig> entries;
|
||||
|
||||
public SharedDirectoryMapper(List<SharedDirectoryMapperConfig> entries)
|
||||
{
|
||||
this.entries = entries;
|
||||
}
|
||||
|
||||
public void Map()
|
||||
{
|
||||
foreach (var config in this.entries)
|
||||
{
|
||||
string label = config.Label;
|
||||
string uncPath = config.UncPath;
|
||||
|
||||
int error = WNetAddConnection2W(new()
|
||||
{
|
||||
Type = RESOURCETYPE_DISK,
|
||||
LocalName = label,
|
||||
RemoteName = uncPath,
|
||||
});
|
||||
if (error != 0)
|
||||
{
|
||||
Throw.Command.Win32Exception(error, $"Failed to map {label}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Unmap()
|
||||
{
|
||||
foreach (var config in this.entries)
|
||||
{
|
||||
string label = config.Label;
|
||||
|
||||
int error = WNetCancelConnection2W(label);
|
||||
if (error != 0)
|
||||
{
|
||||
Throw.Command.Win32Exception(error, $"Failed to unmap {label}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
namespace WinSW
|
||||
{
|
||||
public sealed class SharedDirectoryMapperConfig
|
||||
{
|
||||
public string Label { get; }
|
||||
|
||||
public string UncPath { get; }
|
||||
|
||||
public SharedDirectoryMapperConfig(string driveLabel, string directoryUncPath)
|
||||
{
|
||||
this.Label = driveLabel;
|
||||
this.UncPath = directoryUncPath;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,9 +17,9 @@ namespace WinSW
|
|||
{
|
||||
public sealed class WrapperService : ServiceBase, IEventLogger, IServiceEventLog
|
||||
{
|
||||
internal static readonly WrapperServiceEventLogProvider eventLogProvider = new WrapperServiceEventLogProvider();
|
||||
internal static readonly WrapperServiceEventLogProvider EventLogProvider = new();
|
||||
|
||||
private static readonly int additionalStopTimeout = 1_000;
|
||||
private static readonly int AdditionalStopTimeout = 1_000;
|
||||
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(WrapperService));
|
||||
|
||||
|
@ -31,6 +31,8 @@ namespace WinSW
|
|||
|
||||
internal WinSWExtensionManager ExtensionManager { get; }
|
||||
|
||||
private SharedDirectoryMapper? sharedDirectoryMapper;
|
||||
|
||||
private bool shuttingdown;
|
||||
|
||||
/// <summary>
|
||||
|
@ -51,7 +53,7 @@ namespace WinSW
|
|||
this.ExtensionManager = new WinSWExtensionManager(config);
|
||||
|
||||
// Register the event log provider
|
||||
eventLogProvider.Service = this;
|
||||
EventLogProvider.Service = this;
|
||||
|
||||
if (config.Preshutdown)
|
||||
{
|
||||
|
@ -297,6 +299,13 @@ namespace WinSW
|
|||
throw new AggregateException(exceptions);
|
||||
}
|
||||
|
||||
var sharedDirectories = this.config.SharedDirectories;
|
||||
if (sharedDirectories.Count > 0)
|
||||
{
|
||||
this.sharedDirectoryMapper = new(sharedDirectories);
|
||||
this.sharedDirectoryMapper.Map();
|
||||
}
|
||||
|
||||
var prestart = this.config.Prestart;
|
||||
string? prestartExecutable = prestart.Executable;
|
||||
if (prestartExecutable != null)
|
||||
|
@ -306,7 +315,7 @@ namespace WinSW
|
|||
using var process = this.StartProcess(prestartExecutable, prestart.Arguments, prestart.CreateLogHandler());
|
||||
this.WaitForProcessToExit(process);
|
||||
this.LogExited($"Pre-start process '{process.Format()}' exited with code {process.ExitCode}.", process.ExitCode);
|
||||
process.StopDescendants(additionalStopTimeout);
|
||||
process.StopDescendants(AdditionalStopTimeout);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -335,7 +344,7 @@ namespace WinSW
|
|||
using var process = StartProcessLocked();
|
||||
this.WaitForProcessToExit(process);
|
||||
this.LogExited($"Post-start process '{process.Format()}' exited with code {process.ExitCode}.", process.ExitCode);
|
||||
process.StopDescendants(additionalStopTimeout);
|
||||
process.StopDescendants(AdditionalStopTimeout);
|
||||
this.startingProcess = null;
|
||||
|
||||
Process StartProcessLocked()
|
||||
|
@ -367,7 +376,7 @@ namespace WinSW
|
|||
using var process = StartProcessLocked(prestopExecutable, prestop.Arguments, prestop.CreateLogHandler());
|
||||
this.WaitForProcessToExit(process);
|
||||
this.LogExited($"Pre-stop process '{process.Format()}' exited with code {process.ExitCode}.", process.ExitCode);
|
||||
process.StopDescendants(additionalStopTimeout);
|
||||
process.StopDescendants(AdditionalStopTimeout);
|
||||
this.stoppingProcess = null;
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -408,7 +417,7 @@ namespace WinSW
|
|||
|
||||
Log.Debug("WaitForProcessToExit " + this.process.Id + "+" + stopProcess.Id);
|
||||
this.WaitForProcessToExit(stopProcess);
|
||||
stopProcess.StopDescendants(additionalStopTimeout);
|
||||
stopProcess.StopDescendants(AdditionalStopTimeout);
|
||||
this.stoppingProcess = null;
|
||||
|
||||
this.WaitForProcessToExit(this.process);
|
||||
|
@ -429,8 +438,8 @@ namespace WinSW
|
|||
{
|
||||
using var process = StartProcessLocked(poststopExecutable, poststop.Arguments, poststop.CreateLogHandler());
|
||||
this.WaitForProcessToExit(process);
|
||||
this.LogExited($"Post-Stop process '{process.Format()}' exited with code {process.ExitCode}.", process.ExitCode);
|
||||
process.StopDescendants(additionalStopTimeout);
|
||||
this.LogExited($"Post-stop process '{process.Format()}' exited with code {process.ExitCode}.", process.ExitCode);
|
||||
process.StopDescendants(AdditionalStopTimeout);
|
||||
this.stoppingProcess = null;
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -439,6 +448,15 @@ namespace WinSW
|
|||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
this.sharedDirectoryMapper?.Unmap();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e);
|
||||
}
|
||||
|
||||
// Stop extensions
|
||||
this.ExtensionManager.FireBeforeWrapperStopped();
|
||||
|
||||
|
@ -513,8 +531,8 @@ namespace WinSW
|
|||
|
||||
process.StopDescendants(this.config.StopTimeoutInMs);
|
||||
|
||||
this.startingProcess?.StopTree(additionalStopTimeout);
|
||||
this.stoppingProcess?.StopTree(additionalStopTimeout);
|
||||
this.startingProcess?.StopTree(AdditionalStopTimeout);
|
||||
this.stoppingProcess?.StopTree(AdditionalStopTimeout);
|
||||
|
||||
// if we finished orderly, report that to SCM.
|
||||
// by not reporting unclean shutdown, we let Windows SCM to decide if it wants to
|
|
@ -1,121 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Xml;
|
||||
using log4net;
|
||||
using WinSW.Extensions;
|
||||
using WinSW.Util;
|
||||
using static WinSW.Plugins.SharedDirectoryMapper.SharedDirectoryMapper.Native;
|
||||
|
||||
namespace WinSW.Plugins.SharedDirectoryMapper
|
||||
{
|
||||
public class SharedDirectoryMapper : AbstractWinSWExtension
|
||||
{
|
||||
private readonly List<SharedDirectoryMapperConfig> entries = new List<SharedDirectoryMapperConfig>();
|
||||
|
||||
public override string DisplayName => "Shared Directory Mapper";
|
||||
|
||||
private static readonly ILog Logger = LogManager.GetLogger(typeof(SharedDirectoryMapper));
|
||||
|
||||
public SharedDirectoryMapper()
|
||||
{
|
||||
}
|
||||
|
||||
public SharedDirectoryMapper(bool enableMapping, string directoryUNC, string driveLabel)
|
||||
{
|
||||
var config = new SharedDirectoryMapperConfig(enableMapping, driveLabel, directoryUNC);
|
||||
this.entries.Add(config);
|
||||
}
|
||||
|
||||
public override void Configure(XmlServiceConfig config, XmlNode node)
|
||||
{
|
||||
var mapNodes = XmlHelper.SingleNode(node, "mapping", false)!.SelectNodes("map");
|
||||
if (mapNodes != null)
|
||||
{
|
||||
for (int i = 0; i < mapNodes.Count; i++)
|
||||
{
|
||||
if (mapNodes[i] is XmlElement mapElement)
|
||||
{
|
||||
this.entries.Add(SharedDirectoryMapperConfig.FromXml(mapElement));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnWrapperStarted()
|
||||
{
|
||||
foreach (var config in this.entries)
|
||||
{
|
||||
string label = config.Label;
|
||||
string uncPath = config.UNCPath;
|
||||
if (config.EnableMapping)
|
||||
{
|
||||
Logger.Info(this.DisplayName + ": Mapping shared directory " + uncPath + " to " + label);
|
||||
|
||||
int error = WNetAddConnection2(new NETRESOURCE
|
||||
{
|
||||
Type = RESOURCETYPE_DISK,
|
||||
LocalName = label,
|
||||
RemoteName = uncPath,
|
||||
});
|
||||
if (error != 0)
|
||||
{
|
||||
this.ThrowExtensionException(error, $"Mapping of {label} failed.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Warn(this.DisplayName + ": Mapping of " + label + " is disabled");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void BeforeWrapperStopped()
|
||||
{
|
||||
foreach (var config in this.entries)
|
||||
{
|
||||
string label = config.Label;
|
||||
if (config.EnableMapping)
|
||||
{
|
||||
int error = WNetCancelConnection2(label);
|
||||
if (error != 0)
|
||||
{
|
||||
this.ThrowExtensionException(error, $"Unmapping of {label} failed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ThrowExtensionException(int error, string message)
|
||||
{
|
||||
var inner = new Win32Exception(error);
|
||||
throw new ExtensionException(this.Descriptor.Id, $"{this.DisplayName}: {message} {inner.Message}", inner);
|
||||
}
|
||||
|
||||
internal static class Native
|
||||
{
|
||||
internal const uint RESOURCETYPE_DISK = 0x00000001;
|
||||
|
||||
private const string MprLibraryName = "mpr.dll";
|
||||
|
||||
[DllImport(MprLibraryName, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "WNetAddConnection2W")]
|
||||
internal static extern int WNetAddConnection2(in NETRESOURCE netResource, string? password = null, string? userName = null, uint flags = 0);
|
||||
|
||||
[DllImport(MprLibraryName, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "WNetCancelConnection2W")]
|
||||
internal static extern int WNetCancelConnection2(string name, uint flags = 0, bool force = false);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
internal struct NETRESOURCE
|
||||
{
|
||||
public uint Scope;
|
||||
public uint Type;
|
||||
public uint DisplayType;
|
||||
public uint Usage;
|
||||
public string LocalName;
|
||||
public string RemoteName;
|
||||
public string Comment;
|
||||
public string Provider;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
using System.Xml;
|
||||
using WinSW.Util;
|
||||
|
||||
namespace WinSW.Plugins.SharedDirectoryMapper
|
||||
{
|
||||
/// <summary>
|
||||
/// Stores configuration entries for SharedDirectoryMapper extension.
|
||||
/// </summary>
|
||||
public class SharedDirectoryMapperConfig
|
||||
{
|
||||
public bool EnableMapping { get; }
|
||||
|
||||
public string Label { get; }
|
||||
|
||||
public string UNCPath { get; }
|
||||
|
||||
public SharedDirectoryMapperConfig(bool enableMapping, string label, string uncPath)
|
||||
{
|
||||
this.EnableMapping = enableMapping;
|
||||
this.Label = label;
|
||||
this.UNCPath = uncPath;
|
||||
}
|
||||
|
||||
public static SharedDirectoryMapperConfig FromXml(XmlElement node)
|
||||
{
|
||||
bool enableMapping = XmlHelper.SingleAttribute(node, "enabled", true);
|
||||
string label = XmlHelper.SingleAttribute<string>(node, "label");
|
||||
string uncPath = XmlHelper.SingleAttribute<string>(node, "uncpath");
|
||||
return new SharedDirectoryMapperConfig(enableMapping, label, uncPath);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,7 +11,7 @@ namespace WinSW.Tests
|
|||
{
|
||||
public class DownloadTests : IDisposable
|
||||
{
|
||||
private readonly HttpListener globalListener = new HttpListener();
|
||||
private readonly HttpListener globalListener = new();
|
||||
|
||||
private readonly byte[] contents = { 0x57, 0x69, 0x6e, 0x53, 0x57 };
|
||||
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace WinSW.Tests.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for testing of WinSW Extensions.
|
||||
/// </summary>
|
||||
public class ExtensionTestBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the name of the extension to be passed in the configuration.
|
||||
/// This name should point to assembly in tests, because we do not merge extension DLLs for testing purposes.
|
||||
/// </summary>
|
||||
/// <param name="type">Type of the extension</param>
|
||||
/// <returns>String for Type locator, which includes class and assembly names</returns>
|
||||
public static string GetExtensionClassNameWithAssembly(Type type)
|
||||
{
|
||||
return type.ToString() + ", " + type.Assembly;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
using WinSW.Extensions;
|
||||
using WinSW.Plugins.SharedDirectoryMapper;
|
||||
using Xunit;
|
||||
|
||||
namespace WinSW.Tests.Extensions
|
||||
{
|
||||
public class SharedDirectoryMapperConfigTest : ExtensionTestBase
|
||||
{
|
||||
private readonly XmlServiceConfig serviceConfig;
|
||||
|
||||
private readonly string testExtension = GetExtensionClassNameWithAssembly(typeof(SharedDirectoryMapper));
|
||||
|
||||
public SharedDirectoryMapperConfigTest()
|
||||
{
|
||||
string seedXml =
|
||||
$@"<service>
|
||||
<id>SERVICE_NAME</id>
|
||||
<name>Jenkins Slave</name>
|
||||
<description>This service runs a slave for Jenkins continuous integration system.</description>
|
||||
<executable>C:\Program Files\Java\jre7\bin\java.exe</executable>
|
||||
<arguments>-Xrs -jar \""%BASE%\slave.jar\"" -jnlpUrl ...</arguments>
|
||||
<log mode=""roll""></log>
|
||||
<extensions>
|
||||
<extension enabled=""true"" className=""{this.testExtension}"" id=""mapNetworDirs"">
|
||||
<mapping>
|
||||
<map enabled=""false"" label=""N:"" uncpath=""\\UNC""/>
|
||||
<map enabled=""false"" label=""M:"" uncpath=""\\UNC2""/>
|
||||
</mapping>
|
||||
</extension>
|
||||
<extension enabled=""true"" className=""{this.testExtension}"" id=""mapNetworDirs2"">
|
||||
<mapping>
|
||||
<map enabled=""false"" label=""X:"" uncpath=""\\UNC""/>
|
||||
<map enabled=""false"" label=""Y:"" uncpath=""\\UNC2""/>
|
||||
</mapping>
|
||||
</extension>
|
||||
</extensions>
|
||||
</service>";
|
||||
this.serviceConfig = XmlServiceConfig.FromXml(seedXml);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LoadExtensions()
|
||||
{
|
||||
var manager = new WinSWExtensionManager(this.serviceConfig);
|
||||
manager.LoadExtensions();
|
||||
Assert.Equal(2, manager.Extensions.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StartStopExtension()
|
||||
{
|
||||
var manager = new WinSWExtensionManager(this.serviceConfig);
|
||||
manager.LoadExtensions();
|
||||
manager.FireOnWrapperStarted();
|
||||
manager.FireBeforeWrapperStopped();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -420,5 +420,26 @@ $@"<service>
|
|||
Assert.Equal(expected.StderrPath, actual.StderrPath);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SharedDirectoryMapping()
|
||||
{
|
||||
string seedXml =
|
||||
@"<service>
|
||||
<sharedDirectoryMapping>
|
||||
<map label=""N:"" uncpath=""\\UNC"" />
|
||||
<map label=""M:"" uncpath=""\\UNC2"" />
|
||||
</sharedDirectoryMapping>
|
||||
</service>";
|
||||
|
||||
var config = XmlServiceConfig.FromXml(seedXml);
|
||||
|
||||
var sharedDirectories = config.SharedDirectories;
|
||||
Assert.Equal(2, sharedDirectories.Count);
|
||||
Assert.Equal("N:", sharedDirectories[0].Label);
|
||||
Assert.Equal(@"\\UNC", sharedDirectories[0].UncPath);
|
||||
Assert.Equal("M:", sharedDirectories[1].Label);
|
||||
Assert.Equal(@"\\UNC2", sharedDirectories[1].UncPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,52 +3,45 @@ using System;
|
|||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using WinSW.Plugins.SharedDirectoryMapper;
|
||||
using Xunit;
|
||||
|
||||
namespace WinSW.Tests.Extensions
|
||||
{
|
||||
// TODO: Assert.Throws<ExtensionException>
|
||||
public class SharedDirectoryMapperTests
|
||||
{
|
||||
private static SharedDirectoryMapper CreateMapper(string driveLabel, string directoryUncPath)
|
||||
{
|
||||
return new(new(1)
|
||||
{
|
||||
new(driveLabel, directoryUncPath),
|
||||
});
|
||||
}
|
||||
|
||||
[ElevatedFact]
|
||||
public void TestMap()
|
||||
{
|
||||
using var data = TestData.Create();
|
||||
|
||||
const string label = "W:";
|
||||
var mapper = new SharedDirectoryMapper(true, $@"\\{Environment.MachineName}\{data.name}", label);
|
||||
var mapper = CreateMapper(label, $@"\\{Environment.MachineName}\{data.name}");
|
||||
|
||||
mapper.OnWrapperStarted();
|
||||
mapper.Map();
|
||||
Assert.True(Directory.Exists($@"{label}\"));
|
||||
mapper.BeforeWrapperStopped();
|
||||
mapper.Unmap();
|
||||
Assert.False(Directory.Exists($@"{label}\"));
|
||||
}
|
||||
|
||||
[ElevatedFact]
|
||||
public void TestDisableMapping()
|
||||
{
|
||||
using var data = TestData.Create();
|
||||
|
||||
const string label = "W:";
|
||||
var mapper = new SharedDirectoryMapper(enableMapping: false, $@"\\{Environment.MachineName}\{data.name}", label);
|
||||
|
||||
mapper.OnWrapperStarted();
|
||||
Assert.False(Directory.Exists($@"{label}\"));
|
||||
mapper.BeforeWrapperStopped();
|
||||
}
|
||||
|
||||
[ElevatedFact]
|
||||
public void TestMap_PathEndsWithSlash_Throws()
|
||||
{
|
||||
using var data = TestData.Create();
|
||||
|
||||
const string label = "W:";
|
||||
var mapper = new SharedDirectoryMapper(true, $@"\\{Environment.MachineName}\{data.name}\", label);
|
||||
var mapper = CreateMapper(label, $@"\\{Environment.MachineName}\{data.name}\");
|
||||
|
||||
_ = Assert.ThrowsAny<Exception>(() => mapper.OnWrapperStarted());
|
||||
_ = Assert.ThrowsAny<Exception>(() => mapper.Map());
|
||||
Assert.False(Directory.Exists($@"{label}\"));
|
||||
_ = Assert.ThrowsAny<Exception>(() => mapper.BeforeWrapperStopped());
|
||||
_ = Assert.ThrowsAny<Exception>(() => mapper.Unmap());
|
||||
}
|
||||
|
||||
[ElevatedFact]
|
||||
|
@ -57,11 +50,11 @@ namespace WinSW.Tests.Extensions
|
|||
using var data = TestData.Create();
|
||||
|
||||
const string label = "W";
|
||||
var mapper = new SharedDirectoryMapper(true, $@"\\{Environment.MachineName}\{data.name}", label);
|
||||
var mapper = CreateMapper(label, $@"\\{Environment.MachineName}\{data.name}");
|
||||
|
||||
_ = Assert.ThrowsAny<Exception>(() => mapper.OnWrapperStarted());
|
||||
_ = Assert.ThrowsAny<Exception>(() => mapper.Map());
|
||||
Assert.False(Directory.Exists($@"{label}\"));
|
||||
_ = Assert.ThrowsAny<Exception>(() => mapper.BeforeWrapperStopped());
|
||||
_ = Assert.ThrowsAny<Exception>(() => mapper.Unmap());
|
||||
}
|
||||
|
||||
private readonly ref struct TestData
|
|
@ -23,7 +23,7 @@ namespace WinSW.Tests.Util
|
|||
|
||||
public List<string> ExtensionXmls { get; } = new List<string>();
|
||||
|
||||
private readonly List<string> configEntries = new List<string>();
|
||||
private readonly List<string> configEntries = new();
|
||||
|
||||
private readonly ITestOutputHelper output;
|
||||
|
||||
|
|
|
@ -1099,7 +1099,7 @@ namespace WinSW
|
|||
}
|
||||
else
|
||||
{
|
||||
var eventLogAppender = new ServiceEventLogAppender(WrapperService.eventLogProvider)
|
||||
var eventLogAppender = new ServiceEventLogAppender(WrapperService.EventLogProvider)
|
||||
{
|
||||
Name = "Wrapper event log",
|
||||
Threshold = eventLogLevel,
|
||||
|
|
Loading…
Reference in New Issue