diff --git a/WindowsAgent/Tools/NuGet.exe b/WindowsAgent/Tools/NuGet.exe new file mode 100644 index 000000000..4645f4b35 Binary files /dev/null and b/WindowsAgent/Tools/NuGet.exe differ diff --git a/WindowsAgent/WindowsAgent.sln b/WindowsAgent/WindowsAgent.sln new file mode 100644 index 000000000..71a494b06 --- /dev/null +++ b/WindowsAgent/WindowsAgent.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsAgent", "WindowsAgent\WindowsAgent.csproj", "{F7E2A8D5-6D24-4651-A4BC-1024D59F4903}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F7E2A8D5-6D24-4651-A4BC-1024D59F4903}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F7E2A8D5-6D24-4651-A4BC-1024D59F4903}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F7E2A8D5-6D24-4651-A4BC-1024D59F4903}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F7E2A8D5-6D24-4651-A4BC-1024D59F4903}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/WindowsAgent/WindowsAgent/App.config b/WindowsAgent/WindowsAgent/App.config new file mode 100644 index 000000000..2c1d90691 --- /dev/null +++ b/WindowsAgent/WindowsAgent/App.config @@ -0,0 +1,21 @@ + + + +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/WindowsAgent/WindowsAgent/ExecutionPlan.cs b/WindowsAgent/WindowsAgent/ExecutionPlan.cs new file mode 100644 index 000000000..9c0be86bf --- /dev/null +++ b/WindowsAgent/WindowsAgent/ExecutionPlan.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Mirantis.Keero.WindowsAgent +{ + class ExecutionPlan + { + public class Command + { + public string Name { get; set; } + public Dictionary Arguments { get; set; } + } + + public string[] Scripts { get; set; } + public LinkedList Commands { get; set; } + } +} diff --git a/WindowsAgent/WindowsAgent/MqMessage.cs b/WindowsAgent/WindowsAgent/MqMessage.cs new file mode 100644 index 000000000..d77ab79fd --- /dev/null +++ b/WindowsAgent/WindowsAgent/MqMessage.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Mirantis.Keero.WindowsAgent +{ + class MqMessage + { + private readonly Action ackFunc; + + public MqMessage(Action ackFunc) + { + this.ackFunc = ackFunc; + } + + public string Body { get; set; } + + public void Ack() + { + ackFunc(); + } + } +} diff --git a/WindowsAgent/WindowsAgent/PlanExecutor.cs b/WindowsAgent/WindowsAgent/PlanExecutor.cs new file mode 100644 index 000000000..7baab0bd4 --- /dev/null +++ b/WindowsAgent/WindowsAgent/PlanExecutor.cs @@ -0,0 +1,139 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Management.Automation; +using System.Management.Automation.Runspaces; +using System.Text; +using Newtonsoft.Json; + +namespace Mirantis.Keero.WindowsAgent +{ + class PlanExecutor + { + class ExecutionResult + { + public bool IsException { get; set; } + public object Result { get; set; } + } + + private readonly string path; + + public PlanExecutor(string path) + { + this.path = path; + } + + public string Execute() + { + try + { + var plan = JsonConvert.DeserializeObject(File.ReadAllText(this.path)); + var resultPath = this.path + ".result"; + List currentResults = null; + try + { + currentResults = JsonConvert.DeserializeObject>(File.ReadAllText(resultPath)); + } + catch + { + currentResults = new List(); + } + + + var runSpace = RunspaceFactory.CreateRunspace(); + runSpace.Open(); + + var runSpaceInvoker = new RunspaceInvoke(runSpace); + runSpaceInvoker.Invoke("Set-ExecutionPolicy Unrestricted"); + if (plan.Scripts != null) + { + foreach (var script in plan.Scripts) + { + runSpaceInvoker.Invoke(Encoding.UTF8.GetString(Convert.FromBase64String(script))); + } + } + + while (plan.Commands != null && plan.Commands.Any()) + { + var command = plan.Commands.First(); + + var pipeline = runSpace.CreatePipeline(); + var psCommand = new Command(command.Name); + if (command.Arguments != null) + { + foreach (var kvp in command.Arguments) + { + psCommand.Parameters.Add(kvp.Key, kvp.Value); + } + } + pipeline.Commands.Add(psCommand); + try + { + var result = pipeline.Invoke(); + if (result != null) + { + currentResults.Add(new ExecutionResult { + IsException = false, + Result = result.Select(SerializePsObject).Where(obj => obj != null).ToList() + }); + } + } + catch (Exception exception) + { + currentResults.Add(new ExecutionResult { + IsException = true, + Result = new[] { + exception.GetType().FullName, exception.Message + } + }); + } + finally + { + plan.Commands.RemoveFirst(); + File.WriteAllText(path, JsonConvert.SerializeObject(plan)); + File.WriteAllText(resultPath, JsonConvert.SerializeObject(currentResults)); + } + } + runSpace.Close(); + var executionResult = JsonConvert.SerializeObject(new ExecutionResult { + IsException = false, + Result = currentResults + }, Formatting.Indented); + File.Delete(resultPath); + return executionResult; + } + catch (Exception ex) + { + return JsonConvert.SerializeObject(new ExecutionResult { + IsException = true, + Result = ex.Message + }, Formatting.Indented); + } + } + + private static object SerializePsObject(PSObject obj) + { + if (obj.BaseObject is PSCustomObject) + { + var result = new Dictionary(); + foreach (var property in obj.Properties.Where(p => p.IsGettable)) + { + try + { + result[property.Name] = property.Value.ToString(); + } + catch + { + } + } + return result; + } + else + { + return obj.BaseObject; + } + } + } + +} diff --git a/WindowsAgent/WindowsAgent/Program.cs b/WindowsAgent/WindowsAgent/Program.cs new file mode 100644 index 000000000..8bb49423b --- /dev/null +++ b/WindowsAgent/WindowsAgent/Program.cs @@ -0,0 +1,78 @@ +using System; +using System.ComponentModel; +using System.IO; +using System.Threading; +using NLog; + +namespace Mirantis.Keero.WindowsAgent +{ + [DisplayName("Keero Agent")] + sealed public class Program : WindowsService + { + private static readonly Logger Log = LogManager.GetCurrentClassLogger(); + private volatile bool stop; + private Thread thread; + private RabbitMqClient rabbitMqClient; + + static void Main(string[] args) + { + Start(new Program(), args); + } + + protected override void OnStart(string[] args) + { + base.OnStart(args); + this.rabbitMqClient = new RabbitMqClient(); + this.thread = new Thread(Loop); + this.thread.Start(); + } + + void Loop() + { + const string filePath = "data.json"; + while (!stop) + { + try + { + if (!File.Exists(filePath)) + { + var message = rabbitMqClient.GetMessage(); + File.WriteAllText(filePath, message.Body); + message.Ack(); + } + var result = new PlanExecutor(filePath).Execute(); + if(stop) break; + rabbitMqClient.SendResult(result); + File.Delete(filePath); + } + catch (Exception exception) + { + WaitOnException(exception); + } + + } + + } + + private void WaitOnException(Exception exception) + { + if (stop) return; + Log.WarnException("Exception in main loop", exception); + var i = 0; + while (!stop && i < 10) + { + Thread.Sleep(100); + i++; + } + } + + protected override void OnStop() + { + stop = true; + this.rabbitMqClient.Dispose(); + Console.WriteLine("Stop"); + base.OnStop(); + } + + } +} diff --git a/WindowsAgent/WindowsAgent/Properties/AssemblyInfo.cs b/WindowsAgent/WindowsAgent/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..f7d169bb0 --- /dev/null +++ b/WindowsAgent/WindowsAgent/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("WindowsAgent")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("WindowsAgent")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("9591bf2c-f38b-47e0-a39d-ea9849356371")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/WindowsAgent/WindowsAgent/RabbitMqClient.cs b/WindowsAgent/WindowsAgent/RabbitMqClient.cs new file mode 100644 index 000000000..18a5bc23a --- /dev/null +++ b/WindowsAgent/WindowsAgent/RabbitMqClient.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using RabbitMQ.Client; + +namespace Mirantis.Keero.WindowsAgent +{ + class RabbitMqClient : IDisposable + { + private static readonly ConnectionFactory connectionFactory; + private IConnection currentConnecton; + + static RabbitMqClient() + { + connectionFactory = new ConnectionFactory { + HostName = ConfigurationManager.AppSettings["rabbitmq.host"] ?? "localhost", + UserName = ConfigurationManager.AppSettings["rabbitmq.user"] ?? "guest", + Password = ConfigurationManager.AppSettings["rabbitmq.password"] ??"guest", + Protocol = Protocols.FromEnvironment(), + VirtualHost = ConfigurationManager.AppSettings["rabbitmq.vhost"] ?? "/", + RequestedHeartbeat = 10 + }; + } + + public RabbitMqClient() + { + + } + + public MqMessage GetMessage() + { + var queueName = ConfigurationManager.AppSettings["rabbitmq.inputQueue"] ?? Environment.MachineName.ToLower(); + try + { + IConnection connection = null; + lock (this) + { + connection = this.currentConnecton = this.currentConnecton ?? connectionFactory.CreateConnection(); + } + var session = connection.CreateModel(); + session.BasicQos(0, 1, false); + session.QueueDeclare(queueName, true, false, false, null); + var consumer = new QueueingBasicConsumer(session); + var consumeTag = session.BasicConsume(queueName, false, consumer); + Console.WriteLine("Deq"); + var e = (RabbitMQ.Client.Events.BasicDeliverEventArgs)consumer.Queue.Dequeue(); + Console.WriteLine("Message received"); + Action ackFunc = delegate { + session.BasicAck(e.DeliveryTag, false); + session.BasicCancel(consumeTag); + session.Close(); + }; + + return new MqMessage(ackFunc) { + Body = Encoding.UTF8.GetString(e.Body) + }; + } + catch (Exception) + { + + Dispose(); + throw; + } + } + + public void SendResult(string text) + { + var exchangeName = ConfigurationManager.AppSettings["rabbitmq.resultExchange"] ?? ""; + var resultQueue = ConfigurationManager.AppSettings["rabbitmq.resultQueue"] ?? "-execution-results"; + + try + { + IConnection connection = null; + lock (this) + { + connection = this.currentConnecton = this.currentConnecton ?? connectionFactory.CreateConnection(); + } + var session = connection.CreateModel(); + if (!string.IsNullOrEmpty(resultQueue)) + { + session.QueueDeclare(resultQueue, true, false, false, null); + if (!string.IsNullOrEmpty(exchangeName)) + { + session.ExchangeBind(exchangeName, resultQueue, resultQueue); + } + } + var basicProperties = session.CreateBasicProperties(); + basicProperties.SetPersistent(true); + basicProperties.ContentType = "application/json"; + session.BasicPublish(exchangeName, resultQueue, basicProperties, Encoding.UTF8.GetBytes(text)); + session.Close(); + } + catch (Exception) + { + Dispose(); + throw; + } + } + + public void Dispose() + { + lock (this) + { + try + { + if (this.currentConnecton != null) + { + this.currentConnecton.Close(); + } + } + catch + { + } + finally + { + this.currentConnecton = null; + } + } + } + } +} diff --git a/WindowsAgent/WindowsAgent/SampleExecutionPlan.json b/WindowsAgent/WindowsAgent/SampleExecutionPlan.json new file mode 100644 index 000000000..333ec85ec --- /dev/null +++ b/WindowsAgent/WindowsAgent/SampleExecutionPlan.json @@ -0,0 +1,36 @@ +{ + "Scripts": + [ + "ZnVuY3Rpb24gdDMgeyAxMjsgcmV0dXJuICJ0ZXN0IiB9", + "ZnVuY3Rpb24gTmV3LVBlcnNvbigpDQp7DQogIHBhcmFtICgkRmlyc3ROYW1lLCAkTGFzdE5hbWUsICRQaG9uZSkNCg0KICAkcGVyc29uID0gbmV3LW9iamVjdCBQU09iamVjdA0KDQogICRwZXJzb24gfCBhZGQtbWVtYmVyIC10eXBlIE5vdGVQcm9wZXJ0eSAtTmFtZSBGaXJzdCAtVmFsdWUgJEZpcnN0TmFtZQ0KICAkcGVyc29uIHwgYWRkLW1lbWJlciAtdHlwZSBOb3RlUHJvcGVydHkgLU5hbWUgTGFzdCAtVmFsdWUgJExhc3ROYW1lDQogICRwZXJzb24gfCBhZGQtbWVtYmVyIC10eXBlIE5vdGVQcm9wZXJ0eSAtTmFtZSBQaG9uZSAtVmFsdWUgJFBob25lDQoNCiAgcmV0dXJuICRwZXJzb24NCn0=", + "ZnVuY3Rpb24gVGVzdFRocm93KCkNCnsNCglUaHJvdyBbc3lzdGVtLkluZGV4T3V0T2ZSYW5nZUV4Y2VwdGlvbl0gDQp9" + ], + "Commands" : + [ + { + "Name": "New-Person", + "Arguments" : + { + "FirstName": "MyFirstName", + "LastName": "MyLastName", + "Phone": "123-456" + } + + }, + { + "Name": "t3", + "Arguments" : + { + } + + }, + { + "Name": "Get-Date", + + }, + { + "Name": "TestThrow", + + } + ] +} \ No newline at end of file diff --git a/WindowsAgent/WindowsAgent/ServiceManager.cs b/WindowsAgent/WindowsAgent/ServiceManager.cs new file mode 100644 index 000000000..2bcf227cc --- /dev/null +++ b/WindowsAgent/WindowsAgent/ServiceManager.cs @@ -0,0 +1,111 @@ +using System; +using System.Configuration.Install; +using System.Reflection; +using System.ServiceProcess; +using NLog; + +namespace Mirantis.Keero.WindowsAgent +{ + public class ServiceManager + { + private readonly string serviceName; + + public ServiceManager(string serviceName) + { + this.serviceName = serviceName; + } + + private static readonly Logger Log = LogManager.GetCurrentClassLogger(); + + public bool Restart(string[] args, TimeSpan timeout) + { + var service = new ServiceController(serviceName); + try + { + var millisec1 = TimeSpan.FromMilliseconds(Environment.TickCount); + + service.Stop(); + service.WaitForStatus(ServiceControllerStatus.Stopped, timeout); + Log.Info("Service is stopped"); + + // count the rest of the timeout + var millisec2 = TimeSpan.FromMilliseconds(Environment.TickCount); + timeout = timeout - (millisec2 - millisec1); + + service.Start(args); + service.WaitForStatus(ServiceControllerStatus.Running, timeout); + Log.Info("Service has started"); + return true; + } + catch (Exception ex) + { + Log.ErrorException("Cannot restart service " + serviceName, ex); + return false; + } + } + + public bool Stop(TimeSpan timeout) + { + var service = new ServiceController(serviceName); + try + { + service.Stop(); + service.WaitForStatus(ServiceControllerStatus.Stopped, timeout); + return true; + } + catch (Exception ex) + { + Log.ErrorException("Cannot stop service " + serviceName, ex); + return false; + } + } + + public bool Start(string[] args, TimeSpan timeout) + { + var service = new ServiceController(serviceName); + try + { + service.Start(args); + service.WaitForStatus(ServiceControllerStatus.Running, timeout); + return true; + } + catch (Exception ex) + { + Log.ErrorException("Cannot start service " + serviceName, ex); + return false; + } + } + + public bool Install() + { + try + { + ManagedInstallerClass.InstallHelper( + new string[] { Assembly.GetEntryAssembly().Location }); + } + catch(Exception ex) + { + Log.ErrorException("Cannot install service " + serviceName, ex); + return false; + } + return true; + } + + public bool Uninstall() + { + try + { + ManagedInstallerClass.InstallHelper( + new string[] { "/u", Assembly.GetEntryAssembly().Location }); + } + catch (Exception ex) + { + Log.ErrorException("Cannot uninstall service " + serviceName, ex); + return false; + } + return true; + } + + } + +} diff --git a/WindowsAgent/WindowsAgent/WindowsAgent.csproj b/WindowsAgent/WindowsAgent/WindowsAgent.csproj new file mode 100644 index 000000000..60247a26a --- /dev/null +++ b/WindowsAgent/WindowsAgent/WindowsAgent.csproj @@ -0,0 +1,92 @@ + + + + + Debug + AnyCPU + {F7E2A8D5-6D24-4651-A4BC-1024D59F4903} + Exe + Properties + Mirantis.Keero.WindowsAgent + WindowsAgent + v4.5 + 512 + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll + + + ..\packages\NLog.2.0.0.2000\lib\net40\NLog.dll + + + ..\packages\RabbitMQ.Client.3.0.2\lib\net30\RabbitMQ.Client.dll + + + + + + + False + C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\3.0\System.Management.Automation.dll + + + + + + + + + + + + + + Component + + + + + + Component + + + Component + + + + + + + + + + $(SolutionDir)Tools\nuget install $(ProjectDir)packages.config -o $(SolutionDir)Packages + + + \ No newline at end of file diff --git a/WindowsAgent/WindowsAgent/WindowsService.cs b/WindowsAgent/WindowsAgent/WindowsService.cs new file mode 100644 index 000000000..1ad2d0d55 --- /dev/null +++ b/WindowsAgent/WindowsAgent/WindowsService.cs @@ -0,0 +1,95 @@ +using System; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Reflection; +using System.ServiceProcess; +using NLog; + +namespace Mirantis.Keero.WindowsAgent +{ + public abstract class WindowsService : ServiceBase + { + private static readonly Logger Log = LogManager.GetCurrentClassLogger(); + public bool RunningAsService { get; private set; } + + protected static void Start(WindowsService service, string[] arguments) + { + Directory.SetCurrentDirectory(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)); + + if (arguments.Contains("/install", StringComparer.OrdinalIgnoreCase)) + { + new ServiceManager(service.ServiceName).Install(); + } + else if (arguments.Contains("/uninstall", StringComparer.OrdinalIgnoreCase)) + { + new ServiceManager(service.ServiceName).Uninstall(); + } + else if (arguments.Contains("/start", StringComparer.OrdinalIgnoreCase)) + { + new ServiceManager(service.ServiceName).Start(Environment.GetCommandLineArgs(), TimeSpan.FromMinutes(1)); + } + else if (arguments.Contains("/stop", StringComparer.OrdinalIgnoreCase)) + { + new ServiceManager(service.ServiceName).Stop(TimeSpan.FromMinutes(1)); + } + else if (arguments.Contains("/restart", StringComparer.OrdinalIgnoreCase)) + { + new ServiceManager(service.ServiceName).Restart(Environment.GetCommandLineArgs(), TimeSpan.FromMinutes(1)); + } + else if (!arguments.Contains("/console", StringComparer.OrdinalIgnoreCase)) + { + service.RunningAsService = true; + Run(service); + } + else + { + try + { + service.RunningAsService = false; + Console.Title = service.ServiceName; + service.OnStart(Environment.GetCommandLineArgs()); + service.WaitForExitSignal(); + } + finally + { + service.OnStop(); + service.Dispose(); + } + } + } + + protected WindowsService() + { + var displayNameAttribute = + this.GetType().GetCustomAttributes(typeof (DisplayNameAttribute), false).Cast(). + FirstOrDefault(); + if(displayNameAttribute != null) + { + ServiceName = displayNameAttribute.DisplayName; + } + } + + + protected virtual void WaitForExitSignal() + { + Console.WriteLine("Press ESC to exit"); + while (Console.ReadKey(true).Key != ConsoleKey.Escape) + { + } + } + + protected override void OnStart(string[] args) + { + Log.Info("Service {0} started", ServiceName); + + base.OnStart(args); + } + + protected override void OnStop() + { + Log.Info("Service {0} exited", ServiceName); + base.OnStop(); + } + } +} diff --git a/WindowsAgent/WindowsAgent/WindowsServiceInstaller.cs b/WindowsAgent/WindowsAgent/WindowsServiceInstaller.cs new file mode 100644 index 000000000..ca6e4c246 --- /dev/null +++ b/WindowsAgent/WindowsAgent/WindowsServiceInstaller.cs @@ -0,0 +1,39 @@ +using System.ComponentModel; +using System.Configuration.Install; +using System.Linq; +using System.Reflection; +using System.ServiceProcess; + +namespace Mirantis.Keero.WindowsAgent +{ + [RunInstaller(true)] + public class WindowsServiceInstaller : Installer + { + public WindowsServiceInstaller() + { + var processInstaller = new ServiceProcessInstaller { Account = ServiceAccount.LocalSystem }; + foreach (var type in Assembly.GetEntryAssembly().GetExportedTypes().Where(t => t.IsSubclassOf(typeof(ServiceBase)))) + { + var nameAttribute = type.GetCustomAttributes(typeof (DisplayNameAttribute), false) + .Cast().FirstOrDefault(); + if(nameAttribute == null) continue; + var serviceInstaller = new ServiceInstaller { + StartType = ServiceStartMode.Automatic, + ServiceName = nameAttribute.DisplayName, + DisplayName = nameAttribute.DisplayName + }; + var descriptionAttribute = type.GetCustomAttributes(typeof(DescriptionAttribute), false) + .Cast().FirstOrDefault(); + if(descriptionAttribute != null) + { + serviceInstaller.Description = descriptionAttribute.Description; + } + + Installers.Add(serviceInstaller); + } + + Installers.Add(processInstaller); + + } + } +} diff --git a/WindowsAgent/WindowsAgent/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs b/WindowsAgent/WindowsAgent/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs new file mode 100644 index 000000000..e69de29bb diff --git a/WindowsAgent/WindowsAgent/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs b/WindowsAgent/WindowsAgent/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs new file mode 100644 index 000000000..e69de29bb diff --git a/WindowsAgent/WindowsAgent/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs b/WindowsAgent/WindowsAgent/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs new file mode 100644 index 000000000..e69de29bb diff --git a/WindowsAgent/WindowsAgent/packages.config b/WindowsAgent/WindowsAgent/packages.config new file mode 100644 index 000000000..7aabef8e8 --- /dev/null +++ b/WindowsAgent/WindowsAgent/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/WindowsAgent/packages/repositories.config b/WindowsAgent/packages/repositories.config new file mode 100644 index 000000000..7753eee4a --- /dev/null +++ b/WindowsAgent/packages/repositories.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file