diff --git a/DeployClient.Tests/DeployClient.Tests.csproj b/DeployClient.Tests/DeployClient.Tests.csproj
new file mode 100644
index 0000000..902ec85
--- /dev/null
+++ b/DeployClient.Tests/DeployClient.Tests.csproj
@@ -0,0 +1,87 @@
+
+
+
+
+
+ Debug
+ AnyCPU
+ {2F81EBF7-A395-4716-8B1C-23FE9EE8B7CD}
+ Library
+ Properties
+ DeployClient.Tests
+ DeployClient.Tests
+ v4.8
+ 512
+ {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ 15.0
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
+ $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages
+ False
+ UnitTest
+
+
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\FluentAssertions.5.10.3\lib\net47\FluentAssertions.dll
+
+
+ ..\packages\MSTest.TestFramework.2.1.1\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll
+
+
+ ..\packages\MSTest.TestFramework.2.1.1\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll
+
+
+
+
+
+ ..\packages\System.IO.Abstractions.11.0.7\lib\net461\System.IO.Abstractions.dll
+
+
+ ..\packages\System.IO.Abstractions.TestingHelpers.11.0.7\lib\net461\System.IO.Abstractions.TestingHelpers.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {b6122ccd-75f9-4def-8daa-e11789d6d6d8}
+ DeployClient
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DeployClient.Tests/PackageCrawlerTests.cs b/DeployClient.Tests/PackageCrawlerTests.cs
new file mode 100644
index 0000000..c9d8345
--- /dev/null
+++ b/DeployClient.Tests/PackageCrawlerTests.cs
@@ -0,0 +1,245 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.IO.Abstractions;
+using System.IO.Abstractions.TestingHelpers;
+using FluentAssertions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace DeployClient.Tests
+{
+ [TestClass]
+ public class PackageCrawlerTests
+ {
+ private string _currentExecutionPath;
+
+
+ [TestInitialize]
+ public void Initialize()
+ {
+ _currentExecutionPath = $@"{Environment.CurrentDirectory}\DeployClient";
+ }
+
+
+ #region constructor tests
+
+ [TestMethod]
+ public void FileCrawler_Should_Use_Execution_Directory_When_Null_Argument()
+ {
+ // Arrange
+ var mockFileSystem = GetBasicPreparedMockFileSystem(_currentExecutionPath);
+
+ // Act
+ var fileCrawler = new PackageCrawler(mockFileSystem, null);
+
+ // Assert
+ fileCrawler.PackageDirectoryPath.Should().Be(_currentExecutionPath);
+ }
+
+ [TestMethod]
+ public void FileCrawler_Should_Use_Execution_Directory_When_Empty_String_Argument()
+ {
+ // Arrange
+ var mockFileSystem = GetBasicPreparedMockFileSystem(_currentExecutionPath);
+
+ // Act
+ var fileCrawler = new PackageCrawler(mockFileSystem, string.Empty);
+
+ // Assert
+ fileCrawler.PackageDirectoryPath.Should().Be(_currentExecutionPath);
+ }
+
+ [TestMethod]
+ public void FileCrawler_Should_Use_Execution_Directory_When_Whitespaces_Argument()
+ {
+ // Arrange
+ var mockFileSystem = GetBasicPreparedMockFileSystem(_currentExecutionPath);
+
+ // Act
+ var fileCrawler = new PackageCrawler(mockFileSystem, " ");
+
+ // Assert
+ fileCrawler.PackageDirectoryPath.Should().Be(_currentExecutionPath);
+ }
+
+ [TestMethod]
+ public void FileCrawler_Should_Throw_Exception_When_Directory_Not_Exist()
+ {
+ // Arrange
+ var mockFileSystem = GetBasicPreparedMockFileSystem(_currentExecutionPath);
+
+ // Act
+ // ReSharper disable once ObjectCreationAsStatement
+ Action initialization = () => new PackageCrawler(mockFileSystem, "FooBar");
+
+ // Assert
+ initialization.Should().Throw();
+ }
+
+ [TestMethod]
+ public void FileCrawler_Should_Initialize_With_Provided_Directory_When_Directory_Exist()
+ {
+ // Arrange
+ const string directoryName = "Packages";
+
+ var mockFileSystem = GetBasicPreparedMockFileSystem(_currentExecutionPath);
+ mockFileSystem.Directory.CreateDirectory(directoryName);
+
+ // Act
+ var fileCrawler = new PackageCrawler(mockFileSystem, directoryName);
+
+ // Assert
+ fileCrawler.PackageDirectoryPath.Should().Be($@"{_currentExecutionPath}\{directoryName}");
+ }
+
+
+
+ [TestMethod]
+ public void FileCrawler_Should_Initialize_With_Provided_Directory_When_Directory_Exist_And_Full_Path()
+ {
+ // Arrange
+ const string directoryName = "Packages";
+
+ var mockFileSystem = GetBasicPreparedMockFileSystem(_currentExecutionPath);
+ var directory = mockFileSystem.Directory.CreateDirectory(directoryName);
+
+ var packageDirectoryPath = directory.FullName;
+
+ // Act
+ var fileCrawler = new PackageCrawler(mockFileSystem, packageDirectoryPath);
+
+ // Assert
+ fileCrawler.PackageDirectoryPath.Should().Be(packageDirectoryPath);
+ }
+
+ #endregion
+
+ #region GetPackagesFullPaths tests
+
+ [TestMethod]
+ public void GetPackagesFullPaths_Should_Return_Empty_Enumerable_When_Directory_Empty()
+ {
+ // Arrange
+ const string directoryName = "Packages";
+
+ var mockFileSystem = GetBasicPreparedMockFileSystem(_currentExecutionPath);
+ mockFileSystem.Directory.CreateDirectory(directoryName);
+
+ var packageCrawler = new PackageCrawler(mockFileSystem, directoryName);
+
+ // Act
+ var packages = packageCrawler.GetPackagesFullPaths();
+
+ // Assert
+ packages.Should().BeEmpty();
+ }
+
+ [TestMethod]
+ public void GetPackagesFullPaths_Should_Return_Zip_Files_Full_Paths_When_Directory_Contains_Zip_Files_Only()
+ {
+ // Arrange
+ const string directoryName = "Packages";
+
+ var mockFiles = GetBasicMockFiles();
+ mockFiles.Add($@"{_currentExecutionPath}\Packages\TestPackage_1.zip", new MockFileData("#1 fake zip file."));
+ mockFiles.Add($@"{_currentExecutionPath}\Packages\TestPackage_2.zip", new MockFileData("#2 fake zip file."));
+ mockFiles.Add($@"{_currentExecutionPath}\Packages\TestPackage_3.zip", new MockFileData("#3 fake zip file."));
+
+ var mockFileSystem = new MockFileSystem(mockFiles, _currentExecutionPath);
+
+ var packageCrawler = new PackageCrawler(mockFileSystem, directoryName);
+
+ // Act
+ var packages = packageCrawler.GetPackagesFullPaths();
+
+ // Assert
+ packages.Should().HaveCount(3);
+ }
+
+ [TestMethod]
+ public void GetPackagesFullPaths_Should_Return_Only_Zip_Files_Full_Paths_When_Directory_Contains_Different_File_Kinds()
+ {
+ // Arrange
+ const string directoryName = "Packages";
+
+ var mockFiles = GetBasicMockFiles();
+ mockFiles.Add($@"{_currentExecutionPath}\Packages\TestPackage.zip", new MockFileData("A fake zip file."));
+ mockFiles.Add($@"{_currentExecutionPath}\Packages\TestTextFile.txt", new MockFileData("Just a text file."));
+
+ var mockFileSystem = new MockFileSystem(mockFiles, _currentExecutionPath);
+
+ var packageCrawler = new PackageCrawler(mockFileSystem, directoryName);
+
+ // Act
+ var packages = packageCrawler.GetPackagesFullPaths();
+
+ // Assert
+ packages.Should().HaveCount(1);
+ }
+
+ [TestMethod]
+ public void GetPackagesFullPaths_Should_Return_Zip_Files_Full_Paths_When_Directory_Contains_Different_File_Kinds_And_Full_Path_Initialization()
+ {
+ // Arrange
+ var packageDirectoryPath = $@"{_currentExecutionPath}\Packages";
+
+ var mockFiles = GetBasicMockFiles();
+ mockFiles.Add($@"{packageDirectoryPath}\TestPackage.zip", new MockFileData("A fake zip file."));
+ mockFiles.Add($@"{packageDirectoryPath}\TestTextFile.txt", new MockFileData("Just a text file."));
+
+ var mockFileSystem = new MockFileSystem(mockFiles, _currentExecutionPath);
+
+ var packageCrawler = new PackageCrawler(mockFileSystem, packageDirectoryPath);
+
+ // Act
+ var packages = packageCrawler.GetPackagesFullPaths();
+
+ // Assert
+ packages.Should().HaveCount(1);
+ }
+
+ [TestMethod]
+ public void GetPackagesFullPaths_Should_Return_Zip_Files_Of_Top_Directory_Only_When_Sub_Directory_Exists_With_Zip_Files()
+ {
+ // Arrange
+ const string directoryName = "Packages";
+
+ var mockFiles = GetBasicMockFiles();
+ mockFiles.Add($@"{_currentExecutionPath}\Packages\TestPackage.zip", new MockFileData("A fake zip file."));
+ mockFiles.Add($@"{_currentExecutionPath}\Packages\SubDirectory\SubDir_TestPackage.zip", new MockFileData("A fake zip file from sub-directory."));
+
+ var mockFileSystem = new MockFileSystem(mockFiles, _currentExecutionPath);
+
+ var packageCrawler = new PackageCrawler(mockFileSystem, directoryName);
+
+ // Act
+ var packages = packageCrawler.GetPackagesFullPaths();
+
+ // Assert
+ packages.Should().HaveCount(1);
+ }
+
+ #endregion
+
+
+ #region helper methods
+
+ private IFileSystem GetBasicPreparedMockFileSystem(string currentDirectoryPath)
+ {
+ return new MockFileSystem(GetBasicMockFiles(), currentDirectoryPath);
+ }
+
+ private IDictionary GetBasicMockFiles()
+ {
+ return new Dictionary
+ {
+ {
+ $@"{_currentExecutionPath}\DeployClient_dummy.txt",
+ new MockFileData("Represents the executable to know where we are.")
+ }
+ };
+ }
+
+ #endregion
+ }
+}
diff --git a/DeployClient.Tests/Properties/AssemblyInfo.cs b/DeployClient.Tests/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..42d1e25
--- /dev/null
+++ b/DeployClient.Tests/Properties/AssemblyInfo.cs
@@ -0,0 +1,20 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("DeployClient.Tests")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("DeployClient.Tests")]
+[assembly: AssemblyCopyright("Copyright © 2020")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+[assembly: ComVisible(false)]
+
+[assembly: Guid("2f81ebf7-a395-4716-8b1c-23fe9ee8b7cd")]
+
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/DeployClient.Tests/packages.config b/DeployClient.Tests/packages.config
new file mode 100644
index 0000000..8b45c61
--- /dev/null
+++ b/DeployClient.Tests/packages.config
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DeployClient/App.config b/DeployClient/App.config
index 42b2580..9091ff8 100644
--- a/DeployClient/App.config
+++ b/DeployClient/App.config
@@ -1,12 +1,12 @@
-
-
+
+
-
+
@@ -19,6 +19,9 @@
+
+
+
diff --git a/DeployClient/CommandlineOptions.cs b/DeployClient/CommandlineOptions.cs
index 095133f..0337703 100644
--- a/DeployClient/CommandlineOptions.cs
+++ b/DeployClient/CommandlineOptions.cs
@@ -1,44 +1,52 @@
using CommandLine;
using CommandLine.Text;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace DeployClient
{
internal class CommandLineOptions
{
- [Option("silent",
+ [Option('s',
+ "silent",
DefaultValue = false,
HelpText = "Whether to not print any output")]
public bool IsSilent { get; set; }
- [Option("no-prompt",
+ [Option('n',
+ "no-prompt",
DefaultValue = false,
HelpText = "Whether to prompt the user for confirmation")]
public bool NoPrompt { get; set; }
- [Option("target-uri",
+ [Option('u',
+ "target-uri",
Required = false,
HelpText = "The URL to deploy the packages to.",
DefaultValue = null)]
public string TargetUri { get; set; }
- [Option("api-key",
+ [Option('a',
+ "api-key",
Required = false,
HelpText = "The API Key to use",
DefaultValue = null)]
public string APIKey { get; set; }
- [Option("encryption-key",
+ [Option('e',
+ "encryption-key",
Required = false,
HelpText = "The Encryption Key to use",
DefaultValue = null)]
public string EncryptionKey { get; set; }
- [Option("installation-status-timeout",
+ [Option('d',
+ "packages-directory",
+ Required = false,
+ HelpText = "Defines the directory that contains the to install packages.",
+ DefaultValue = null)]
+ public string PackagesDirectoryPath { get; set; }
+
+ [Option('t',
+ "installation-status-timeout",
Required = false,
HelpText = "The number of seconds to ignore 404 errors when checking installation status",
DefaultValue = 60)]
diff --git a/DeployClient/DeployClient.csproj b/DeployClient/DeployClient.csproj
index db85a3a..3f2b03e 100644
--- a/DeployClient/DeployClient.csproj
+++ b/DeployClient/DeployClient.csproj
@@ -8,7 +8,7 @@
Exe
DeployClient
DeployClient
- v4.5
+ v4.8
512
true
@@ -41,6 +41,9 @@
+
+ ..\packages\System.IO.Abstractions.11.0.7\lib\net461\System.IO.Abstractions.dll
+
..\packages\System.ValueTuple.4.3.0\lib\netstandard1.0\System.ValueTuple.dll
@@ -56,6 +59,7 @@
+
diff --git a/DeployClient/PackageCrawler.cs b/DeployClient/PackageCrawler.cs
new file mode 100644
index 0000000..8c2e573
--- /dev/null
+++ b/DeployClient/PackageCrawler.cs
@@ -0,0 +1,63 @@
+using System.Collections.Generic;
+using System.IO;
+using System.IO.Abstractions;
+using System.Linq;
+
+namespace DeployClient
+{
+ internal class PackageCrawler
+ {
+ private readonly IFileSystem _fileSystem;
+ private readonly IDirectoryInfo _packageDirectoryInfo;
+
+
+
+ ///
+ /// The directory that contains to installing files.
+ ///
+ public string PackageDirectoryPath => _packageDirectoryInfo.FullName;
+
+
+
+ public PackageCrawler(string packageDirectoryPath) : this(new FileSystem(), packageDirectoryPath)
+ {
+ }
+
+ public PackageCrawler(IFileSystem fileSystem, string packageDirectoryPath)
+ {
+ _fileSystem = fileSystem;
+
+ _packageDirectoryInfo = GetPackageDirectory(packageDirectoryPath);
+ }
+
+
+
+ private IDirectoryInfo GetPackageDirectory(string packageDirectoryPath)
+ {
+ var path = string.IsNullOrWhiteSpace(packageDirectoryPath)
+ ? _fileSystem.Directory.GetCurrentDirectory()
+ : packageDirectoryPath;
+
+ var directoryInfo = _fileSystem.DirectoryInfo.FromDirectoryName(path);
+
+ if (!directoryInfo.Exists)
+ {
+ throw new DirectoryNotFoundException($"Directory \"{directoryInfo.FullName}\" not found.");
+ }
+
+ return directoryInfo;
+ }
+
+ ///
+ /// Returns all installation packages (*.zip files) full file paths which were found in defined .
+ ///
+ /// Enumerable of full file paths.
+ internal IEnumerable GetPackagesFullPaths()
+ {
+ const string searchPattern = "*.zip";
+
+ return _packageDirectoryInfo.GetFiles(searchPattern, SearchOption.TopDirectoryOnly).Select(f => f.FullName);
+
+ }
+ }
+}
diff --git a/DeployClient/Program.cs b/DeployClient/Program.cs
index 8329565..0e8b688 100644
--- a/DeployClient/Program.cs
+++ b/DeployClient/Program.cs
@@ -1,8 +1,6 @@
using Cantarus.Libraries.Encryption;
using System;
-using System.Collections;
using System.Collections.Generic;
-using System.Configuration;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
@@ -11,11 +9,11 @@
namespace DeployClient
{
- class Program
+ internal static class Program
{
- internal static CommandLineOptions Options = new CommandLineOptions();
+ internal static readonly CommandLineOptions Options = new CommandLineOptions();
- enum ExitCode : int
+ private enum ExitCode
{
Success = 0,
Error = 1,
@@ -24,7 +22,7 @@ enum ExitCode : int
InstallFailure = 4
}
- static async Task Main(string[] args)
+ private static async Task Main(string[] args)
{
try
{
@@ -55,29 +53,12 @@ static async Task Main(string[] args)
// Output identifying module archives.
WriteLine("Identifying module archives...");
- // Read zip files in current directory.
- string currentDirectory = Directory.GetCurrentDirectory();
- List zipFiles = new List(Directory.GetFiles(currentDirectory, "*.zip"));
-
- // Is there something to do?
- if (zipFiles.Count <= 0)
- {
- // No, exit.
- WriteLine("No module archives found.");
- WriteLine("Exiting.");
- ReadLine();
- Environment.Exit((int)ExitCode.NoModulesFound);
- }
-
- // Inform user of modules found.
- WriteLine(string.Format("Found {0} module archives in {1}:", zipFiles.Count, currentDirectory));
-
- foreach (string zipFile in zipFiles)
- {
- WriteLine(string.Format("\t{0}. {1}", zipFiles.IndexOf(zipFile) + 1, Path.GetFileName(zipFile)));
- }
- WriteLine();
+ // Read zip files from packages directory if provided, otherwise from current directory
+ var packageCrawler = new PackageCrawler(Options.PackagesDirectoryPath);
+ var zipFiles = packageCrawler.GetPackagesFullPaths().ToArray();
+ ValidateFoundPackages(zipFiles, packageCrawler.PackageDirectoryPath);
+
if (!Options.NoPrompt)
{
// Prompt to continue.
@@ -269,6 +250,11 @@ private static void GetSettings(string[] args)
{
Options.EncryptionKey = Properties.Settings.Default.EncryptionKey;
}
+
+ if (string.IsNullOrWhiteSpace(Options.PackagesDirectoryPath))
+ {
+ Options.PackagesDirectoryPath = Properties.Settings.Default.PackagesDirectory;
+ }
}
}
@@ -352,6 +338,31 @@ private static void WriteLine(string message = "")
Console.WriteLine(message);
}
+ private static void ValidateFoundPackages(IEnumerable zipFiles, string directory)
+ {
+ var packages = zipFiles?.ToArray() ?? new string[0];
+
+ // Is there something to do?
+ if (!packages.Any())
+ {
+ // No, exit.
+ WriteLine("No module archives found.");
+ WriteLine("Exiting.");
+ ReadLine();
+ Environment.Exit((int)ExitCode.NoModulesFound);
+ }
+
+ // Inform user of modules found.
+ WriteLine($"Found {packages.Length} module archives in {directory}:");
+
+ var fileCounter = 1;
+ foreach (var package in packages)
+ {
+ WriteLine($"\t{fileCounter++}. {Path.GetFileName(package)}");
+ }
+ WriteLine();
+ }
+
private static string ReadLine()
{
if (Options.IsSilent || Options.NoPrompt)
diff --git a/DeployClient/Properties/AssemblyInfo.cs b/DeployClient/Properties/AssemblyInfo.cs
index e01bff9..aed9b94 100644
--- a/DeployClient/Properties/AssemblyInfo.cs
+++ b/DeployClient/Properties/AssemblyInfo.cs
@@ -34,3 +34,5 @@
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.9.3.0")]
[assembly: AssemblyFileVersion("0.9.3.0")]
+
+[assembly: InternalsVisibleTo("DeployClient.Tests")]
diff --git a/DeployClient/Properties/Settings.Designer.cs b/DeployClient/Properties/Settings.Designer.cs
index 6ca4571..bae2571 100644
--- a/DeployClient/Properties/Settings.Designer.cs
+++ b/DeployClient/Properties/Settings.Designer.cs
@@ -12,7 +12,7 @@ namespace DeployClient.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.1.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.6.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
@@ -49,5 +49,14 @@ public string EncryptionKey {
return ((string)(this["EncryptionKey"]));
}
}
+
+ [global::System.Configuration.ApplicationScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("")]
+ public string PackagesDirectory {
+ get {
+ return ((string)(this["PackagesDirectory"]));
+ }
+ }
}
}
diff --git a/DeployClient/Properties/Settings.settings b/DeployClient/Properties/Settings.settings
index a23e404..eee132b 100644
--- a/DeployClient/Properties/Settings.settings
+++ b/DeployClient/Properties/Settings.settings
@@ -11,5 +11,8 @@
+
+
+
\ No newline at end of file
diff --git a/DeployClient/packages.config b/DeployClient/packages.config
index 9c3293f..5c2cb18 100644
--- a/DeployClient/packages.config
+++ b/DeployClient/packages.config
@@ -1,5 +1,6 @@
+
\ No newline at end of file
diff --git a/PolyDeploy.sln b/PolyDeploy.sln
index 8561afc..a695c2e 100644
--- a/PolyDeploy.sln
+++ b/PolyDeploy.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.26403.7
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30128.74
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PolyDeploy", "PolyDeploy\PolyDeploy.csproj", "{B15D41DD-2D1A-490C-977F-2F14E56447D5}"
EndProject
@@ -11,6 +11,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeployClient", "DeployClien
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EncryptionTests", "EncryptionTests\EncryptionTests.csproj", "{566818D4-11AE-4C96-821E-91C1C616D19B}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeployClient.Tests", "DeployClient.Tests\DeployClient.Tests.csproj", "{2F81EBF7-A395-4716-8B1C-23FE9EE8B7CD}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Clients|Any CPU = Clients|Any CPU
@@ -42,6 +44,12 @@ Global
{566818D4-11AE-4C96-821E-91C1C616D19B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{566818D4-11AE-4C96-821E-91C1C616D19B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{566818D4-11AE-4C96-821E-91C1C616D19B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2F81EBF7-A395-4716-8B1C-23FE9EE8B7CD}.Clients|Any CPU.ActiveCfg = Release|Any CPU
+ {2F81EBF7-A395-4716-8B1C-23FE9EE8B7CD}.Clients|Any CPU.Build.0 = Release|Any CPU
+ {2F81EBF7-A395-4716-8B1C-23FE9EE8B7CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F81EBF7-A395-4716-8B1C-23FE9EE8B7CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2F81EBF7-A395-4716-8B1C-23FE9EE8B7CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2F81EBF7-A395-4716-8B1C-23FE9EE8B7CD}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE