From fb0b505bf42781c0f21c8e32f7aec5337b11f204 Mon Sep 17 00:00:00 2001
From: "kay.one" <kay.one@gmail.com>
Date: Sat, 22 Oct 2011 22:26:43 -0700
Subject: [PATCH] Added NzbDrone.Update, refactored some common wrappers to
 NzbDrone.Common

---
 NzbDrone.App.Test/ConfigProviderTest.cs       |   1 +
 NzbDrone.App.Test/EnviromentProviderTest.cs   |   1 +
 NzbDrone.App.Test/IISProviderTest.cs          |   4 +-
 NzbDrone.App.Test/MonitoringProviderTest.cs   |   2 +
 NzbDrone.App.Test/NzbDrone.App.Test.csproj    |   4 +
 NzbDrone.App.Test/ProcessProviderTests.cs     |   8 +-
 NzbDrone.App.Test/RouterTest.cs               |   2 +-
 NzbDrone.App.Test/ServiceControllerTests.cs   |   1 +
 .../ConsoleProvider.cs                        |   7 +-
 .../EnviromentProvider.cs                     |  10 +-
 .../Model/ProcessInfo.cs                      |   2 +-
 NzbDrone.Common/NzbDrone.Common.csproj        |  67 +++++++
 .../ProcessProvider.cs                        |   4 +-
 NzbDrone.Common/Properties/AssemblyInfo.cs    |  36 ++++
 NzbDrone.Common/ServiceProvider.cs            | 136 +++++++++++++
 .../WebClientProvider.cs                      |   2 +-
 NzbDrone.Common/packages.config               |   4 +
 NzbDrone.Update.Test/AutoMoq/AutoMoqer.cs     | 166 ++++++++++++++++
 NzbDrone.Update.Test/AutoMoq/AutoMoqerTest.cs | 187 ++++++++++++++++++
 NzbDrone.Update.Test/AutoMoq/License.txt      |  22 +++
 .../Unity/AutoMockingBuilderStrategy.cs       |  84 ++++++++
 .../Unity/AutoMockingContainerExtension.cs    |  40 ++++
 .../NzbDrone.Update.Test.csproj               | 105 ++++++++++
 .../Properties/AssemblyInfo.cs                |  36 ++++
 NzbDrone.Update.Test/UpdateProviderTest.cs    |  65 ++++++
 NzbDrone.Update.Test/packages.config          |   8 +
 NzbDrone.Update/NzbDrone.Update.csproj        |  71 +++++++
 NzbDrone.Update/Program.cs                    |  15 ++
 NzbDrone.Update/Properties/AssemblyInfo.cs    |  36 ++++
 NzbDrone.Update/Providers/DiskProvider.cs     |  87 ++++++++
 NzbDrone.Update/Providers/UpdateProvider.cs   |  56 ++++++
 NzbDrone.Update/packages.config               |   4 +
 NzbDrone.sln                                  |  43 ++++
 NzbDrone/ApplicationServer.cs                 |   1 +
 NzbDrone/CentralDispatch.cs                   |   1 +
 NzbDrone/NzbDrone.csproj                      |  13 +-
 NzbDrone/Providers/ConfigProvider.cs          |   1 +
 NzbDrone/Providers/IISProvider.cs             |   2 +
 NzbDrone/Providers/MonitoringProvider.cs      |   1 +
 NzbDrone/Providers/ServiceProvider.cs         |  73 -------
 NzbDrone/Router.cs                            |   2 +-
 packages/repositories.config                  |   3 +
 42 files changed, 1316 insertions(+), 97 deletions(-)
 rename {NzbDrone/Providers => NzbDrone.Common}/ConsoleProvider.cs (86%)
 rename {NzbDrone/Providers => NzbDrone.Common}/EnviromentProvider.cs (84%)
 rename {NzbDrone => NzbDrone.Common}/Model/ProcessInfo.cs (86%)
 create mode 100644 NzbDrone.Common/NzbDrone.Common.csproj
 rename {NzbDrone/Providers => NzbDrone.Common}/ProcessProvider.cs (97%)
 create mode 100644 NzbDrone.Common/Properties/AssemblyInfo.cs
 create mode 100644 NzbDrone.Common/ServiceProvider.cs
 rename {NzbDrone/Providers => NzbDrone.Common}/WebClientProvider.cs (87%)
 create mode 100644 NzbDrone.Common/packages.config
 create mode 100644 NzbDrone.Update.Test/AutoMoq/AutoMoqer.cs
 create mode 100644 NzbDrone.Update.Test/AutoMoq/AutoMoqerTest.cs
 create mode 100644 NzbDrone.Update.Test/AutoMoq/License.txt
 create mode 100644 NzbDrone.Update.Test/AutoMoq/Unity/AutoMockingBuilderStrategy.cs
 create mode 100644 NzbDrone.Update.Test/AutoMoq/Unity/AutoMockingContainerExtension.cs
 create mode 100644 NzbDrone.Update.Test/NzbDrone.Update.Test.csproj
 create mode 100644 NzbDrone.Update.Test/Properties/AssemblyInfo.cs
 create mode 100644 NzbDrone.Update.Test/UpdateProviderTest.cs
 create mode 100644 NzbDrone.Update.Test/packages.config
 create mode 100644 NzbDrone.Update/NzbDrone.Update.csproj
 create mode 100644 NzbDrone.Update/Program.cs
 create mode 100644 NzbDrone.Update/Properties/AssemblyInfo.cs
 create mode 100644 NzbDrone.Update/Providers/DiskProvider.cs
 create mode 100644 NzbDrone.Update/Providers/UpdateProvider.cs
 create mode 100644 NzbDrone.Update/packages.config
 delete mode 100644 NzbDrone/Providers/ServiceProvider.cs

diff --git a/NzbDrone.App.Test/ConfigProviderTest.cs b/NzbDrone.App.Test/ConfigProviderTest.cs
index 9bed9a381..87f133ee7 100644
--- a/NzbDrone.App.Test/ConfigProviderTest.cs
+++ b/NzbDrone.App.Test/ConfigProviderTest.cs
@@ -1,6 +1,7 @@
 using FluentAssertions;
 using Moq;
 using NUnit.Framework;
+using NzbDrone.Common;
 using NzbDrone.Providers;
 
 namespace NzbDrone.App.Test
diff --git a/NzbDrone.App.Test/EnviromentProviderTest.cs b/NzbDrone.App.Test/EnviromentProviderTest.cs
index 919be960d..3340a11d7 100644
--- a/NzbDrone.App.Test/EnviromentProviderTest.cs
+++ b/NzbDrone.App.Test/EnviromentProviderTest.cs
@@ -1,5 +1,6 @@
 using FluentAssertions;
 using NUnit.Framework;
+using NzbDrone.Common;
 using NzbDrone.Providers;
 
 namespace NzbDrone.App.Test
diff --git a/NzbDrone.App.Test/IISProviderTest.cs b/NzbDrone.App.Test/IISProviderTest.cs
index 29de777be..00c3e548b 100644
--- a/NzbDrone.App.Test/IISProviderTest.cs
+++ b/NzbDrone.App.Test/IISProviderTest.cs
@@ -7,6 +7,7 @@ using AutoMoq;
 using FluentAssertions;
 using Moq;
 using NUnit.Framework;
+using NzbDrone.Common;
 using NzbDrone.Providers;
 
 namespace NzbDrone.App.Test
@@ -14,9 +15,6 @@ namespace NzbDrone.App.Test
     [TestFixture]
     public class IISProviderTest
     {
-
-
-
         [Test]
         public void start_should_set_IISProccessId_property()
         {
diff --git a/NzbDrone.App.Test/MonitoringProviderTest.cs b/NzbDrone.App.Test/MonitoringProviderTest.cs
index f2439d9d4..7b3bd0807 100644
--- a/NzbDrone.App.Test/MonitoringProviderTest.cs
+++ b/NzbDrone.App.Test/MonitoringProviderTest.cs
@@ -8,6 +8,8 @@ using FizzWare.NBuilder;
 using FluentAssertions;
 using Moq;
 using NUnit.Framework;
+using NzbDrone.Common;
+using NzbDrone.Common.Model;
 using NzbDrone.Model;
 using NzbDrone.Providers;
 
diff --git a/NzbDrone.App.Test/NzbDrone.App.Test.csproj b/NzbDrone.App.Test/NzbDrone.App.Test.csproj
index 59728b4ca..df95ddc4e 100644
--- a/NzbDrone.App.Test/NzbDrone.App.Test.csproj
+++ b/NzbDrone.App.Test/NzbDrone.App.Test.csproj
@@ -90,6 +90,10 @@
     <None Include="packages.config" />
   </ItemGroup>
   <ItemGroup>
+    <ProjectReference Include="..\NzbDrone.Common\NzbDrone.Common.csproj">
+      <Project>{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}</Project>
+      <Name>NzbDrone.Common</Name>
+    </ProjectReference>
     <ProjectReference Include="..\NzbDrone.Test.Dummy\NzbDrone.Test.Dummy.csproj">
       <Project>{FAFB5948-A222-4CF6-AD14-026BE7564802}</Project>
       <Name>NzbDrone.Test.Dummy</Name>
diff --git a/NzbDrone.App.Test/ProcessProviderTests.cs b/NzbDrone.App.Test/ProcessProviderTests.cs
index 35aea670c..d22a86bf9 100644
--- a/NzbDrone.App.Test/ProcessProviderTests.cs
+++ b/NzbDrone.App.Test/ProcessProviderTests.cs
@@ -1,11 +1,7 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
-using System.Text;
+using System.Diagnostics;
 using FluentAssertions;
 using NUnit.Framework;
-using NzbDrone.Providers;
+using NzbDrone.Common;
 
 namespace NzbDrone.App.Test
 {
diff --git a/NzbDrone.App.Test/RouterTest.cs b/NzbDrone.App.Test/RouterTest.cs
index 264277990..f48082ff9 100644
--- a/NzbDrone.App.Test/RouterTest.cs
+++ b/NzbDrone.App.Test/RouterTest.cs
@@ -3,8 +3,8 @@ using AutoMoq;
 using FluentAssertions;
 using Moq;
 using NUnit.Framework;
+using NzbDrone.Common;
 using NzbDrone.Model;
-using NzbDrone.Providers;
 
 namespace NzbDrone.App.Test
 {
diff --git a/NzbDrone.App.Test/ServiceControllerTests.cs b/NzbDrone.App.Test/ServiceControllerTests.cs
index 05cab1154..73f24cb35 100644
--- a/NzbDrone.App.Test/ServiceControllerTests.cs
+++ b/NzbDrone.App.Test/ServiceControllerTests.cs
@@ -4,6 +4,7 @@ using System.Linq;
 using System.Text;
 using FluentAssertions;
 using NUnit.Framework;
+using NzbDrone.Common;
 using NzbDrone.Providers;
 
 namespace NzbDrone.App.Test
diff --git a/NzbDrone/Providers/ConsoleProvider.cs b/NzbDrone.Common/ConsoleProvider.cs
similarity index 86%
rename from NzbDrone/Providers/ConsoleProvider.cs
rename to NzbDrone.Common/ConsoleProvider.cs
index cd45ce4f4..aaf72a702 100644
--- a/NzbDrone/Providers/ConsoleProvider.cs
+++ b/NzbDrone.Common/ConsoleProvider.cs
@@ -1,7 +1,7 @@
 using System;
 using System.Diagnostics;
 
-namespace NzbDrone.Providers
+namespace NzbDrone.Common
 {
     public class ConsoleProvider
     {
@@ -32,5 +32,10 @@ namespace NzbDrone.Providers
         {
             Console.WriteLine("Can't find service ({0})", ServiceProvider.NzbDroneServiceName);
         }
+
+        public virtual void UpdateFolderDoestExist(string path)
+        {
+            Console.WriteLine("Unable to find update package in '{0}'", path);
+        }
     }
 }
\ No newline at end of file
diff --git a/NzbDrone/Providers/EnviromentProvider.cs b/NzbDrone.Common/EnviromentProvider.cs
similarity index 84%
rename from NzbDrone/Providers/EnviromentProvider.cs
rename to NzbDrone.Common/EnviromentProvider.cs
index 3373d37ae..fa1fdb9ae 100644
--- a/NzbDrone/Providers/EnviromentProvider.cs
+++ b/NzbDrone.Common/EnviromentProvider.cs
@@ -2,7 +2,7 @@
 using System.IO;
 using System.Reflection;
 
-namespace NzbDrone.Providers
+namespace NzbDrone.Common
 {
     public class EnviromentProvider
     {
@@ -42,6 +42,14 @@ namespace NzbDrone.Providers
             }
         }
 
+        public virtual string StartUpPath
+        {
+            get
+            {
+                return new FileInfo(Assembly.GetExecutingAssembly().Location).Directory.FullName;
+            }
+        }
+
         private static bool ContainsIIS(DirectoryInfo dir)
         {
             return dir.GetDirectories("iisexpress").Length != 0;
diff --git a/NzbDrone/Model/ProcessInfo.cs b/NzbDrone.Common/Model/ProcessInfo.cs
similarity index 86%
rename from NzbDrone/Model/ProcessInfo.cs
rename to NzbDrone.Common/Model/ProcessInfo.cs
index f1086c2ab..3bcd2b39b 100644
--- a/NzbDrone/Model/ProcessInfo.cs
+++ b/NzbDrone.Common/Model/ProcessInfo.cs
@@ -1,6 +1,6 @@
 using System.Diagnostics;
 
-namespace NzbDrone.Model
+namespace NzbDrone.Common.Model
 {
     public class ProcessInfo
     {
diff --git a/NzbDrone.Common/NzbDrone.Common.csproj b/NzbDrone.Common/NzbDrone.Common.csproj
new file mode 100644
index 000000000..f978fa966
--- /dev/null
+++ b/NzbDrone.Common/NzbDrone.Common.csproj
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>NzbDrone.Common</RootNamespace>
+    <AssemblyName>NzbDrone.Common</AssemblyName>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="NLog">
+      <HintPath>..\packages\NLog.2.0.0.2000\lib\net40\NLog.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Configuration.Install" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.ServiceProcess" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="ConsoleProvider.cs" />
+    <Compile Include="EnviromentProvider.cs" />
+    <Compile Include="Model\ProcessInfo.cs" />
+    <Compile Include="ProcessProvider.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="ServiceProvider.cs" />
+    <Compile Include="WebClientProvider.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/NzbDrone/Providers/ProcessProvider.cs b/NzbDrone.Common/ProcessProvider.cs
similarity index 97%
rename from NzbDrone/Providers/ProcessProvider.cs
rename to NzbDrone.Common/ProcessProvider.cs
index da8822155..94fded59f 100644
--- a/NzbDrone/Providers/ProcessProvider.cs
+++ b/NzbDrone.Common/ProcessProvider.cs
@@ -2,9 +2,9 @@
 using System.Diagnostics;
 using System.Linq;
 using NLog;
-using NzbDrone.Model;
+using NzbDrone.Common.Model;
 
-namespace NzbDrone.Providers
+namespace NzbDrone.Common
 {
     public class ProcessProvider
     {
diff --git a/NzbDrone.Common/Properties/AssemblyInfo.cs b/NzbDrone.Common/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..182f9300e
--- /dev/null
+++ b/NzbDrone.Common/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("NzbDrone.Common")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("NzbDrone.Common")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[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("b6eaa144-e13b-42e5-a738-c60d89c0f728")]
+
+// 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/NzbDrone.Common/ServiceProvider.cs b/NzbDrone.Common/ServiceProvider.cs
new file mode 100644
index 000000000..da14867d1
--- /dev/null
+++ b/NzbDrone.Common/ServiceProvider.cs
@@ -0,0 +1,136 @@
+using System;
+using System.Collections.Specialized;
+using System.Configuration.Install;
+using System.Linq;
+using System.Reflection;
+using System.ServiceProcess;
+using NLog;
+using TimeoutException = System.TimeoutException;
+
+namespace NzbDrone.Common
+{
+    public class ServiceProvider
+    {
+        public const string NzbDroneServiceName = "NzbDrone";
+
+        private static readonly Logger Logger = LogManager.GetLogger("Host.ServiceManager");
+
+        public virtual bool ServiceExist(string name)
+        {
+            Logger.Debug("Checking if service {0} exists.", name);
+            return
+                ServiceController.GetServices().Any(
+                    s => String.Equals(s.ServiceName, name, StringComparison.InvariantCultureIgnoreCase));
+        }
+
+
+        public virtual void Install()
+        {
+            Logger.Info("Installing service '{0}'", NzbDroneServiceName);
+
+
+            var installer = new ServiceProcessInstaller
+                                {
+                                    Account = ServiceAccount.LocalSystem
+                                };
+
+            var serviceInstaller = new ServiceInstaller();
+
+
+            String[] cmdline = { @"/assemblypath=" + Assembly.GetExecutingAssembly().Location };
+
+            var context = new InstallContext("service_install.log", cmdline);
+            serviceInstaller.Context = context;
+            serviceInstaller.DisplayName = NzbDroneServiceName;
+            serviceInstaller.ServiceName = NzbDroneServiceName;
+            serviceInstaller.Description = "NzbDrone Application Server";
+            serviceInstaller.StartType = ServiceStartMode.Automatic;
+
+            serviceInstaller.Parent = installer;
+
+            serviceInstaller.Install(new ListDictionary());
+
+            Logger.Info("Service Has installed successfully.");
+        }
+
+        public virtual void UnInstall()
+        {
+            Logger.Info("Uninstalling NzbDrone service");
+            var serviceInstaller = new ServiceInstaller();
+
+            var context = new InstallContext("service_uninstall.log", null);
+            serviceInstaller.Context = context;
+            serviceInstaller.ServiceName = NzbDroneServiceName;
+            serviceInstaller.Uninstall(null);
+
+            Logger.Info("NzbDrone successfully uninstalled");
+        }
+
+
+        public virtual void Run(ServiceBase service)
+        {
+            ServiceBase.Run(service);
+        }
+
+        public virtual ServiceController GetService(string serviceName)
+        {
+            return ServiceController.GetServices().Where(
+                    c => String.Equals(c.ServiceName, serviceName, StringComparison.InvariantCultureIgnoreCase))
+                    .FirstOrDefault();
+        }
+
+        public virtual void Stop(string serviceName)
+        {
+            Logger.Info("Stopping {0} Service...");
+            var service = GetService(serviceName);
+            if (service == null)
+            {
+                Logger.Warn("Unable to stop {0}. no service with that name exists.", serviceName);
+            }
+
+            Logger.Info("Service is currently {0}", service.Status);
+
+            service.Stop();
+            service.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(60));
+
+            service.Refresh();
+            if (service.Status == ServiceControllerStatus.Stopped)
+            {
+                Logger.Info("{0} has stopped successfully.");
+            }
+            else
+            {
+                Logger.Error("Service stop request has timed out. {0}", service.Status);
+            }
+        }
+
+        public virtual void Start(string serviceName)
+        {
+            Logger.Info("Starting {0} Service...");
+            var service = GetService(serviceName);
+            if (service == null)
+            {
+                Logger.Warn("Unable to start '{0}' no service with that name exists.", serviceName);
+            }
+
+            if (service.Status != ServiceControllerStatus.Paused || service.Status != ServiceControllerStatus.Stopped)
+            {
+                Logger.Warn("Service is in a state that can't be started {0}", service.Status);
+            }
+
+            service.Start();
+
+            service.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(60));
+            service.Refresh();
+
+            if (service.Status == ServiceControllerStatus.Running)
+            {
+                Logger.Info("{0} has started successfully.");
+            }
+            else
+            {
+                Logger.Error("Service start request has timed out. {0}", service.Status);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/NzbDrone/Providers/WebClientProvider.cs b/NzbDrone.Common/WebClientProvider.cs
similarity index 87%
rename from NzbDrone/Providers/WebClientProvider.cs
rename to NzbDrone.Common/WebClientProvider.cs
index 3ffa1e920..baf0f0d64 100644
--- a/NzbDrone/Providers/WebClientProvider.cs
+++ b/NzbDrone.Common/WebClientProvider.cs
@@ -1,6 +1,6 @@
 using System.Net;
 
-namespace NzbDrone.Providers
+namespace NzbDrone.Common
 {
     public class WebClientProvider
     {
diff --git a/NzbDrone.Common/packages.config b/NzbDrone.Common/packages.config
new file mode 100644
index 000000000..4f6876419
--- /dev/null
+++ b/NzbDrone.Common/packages.config
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="NLog" version="2.0.0.2000" />
+</packages>
\ No newline at end of file
diff --git a/NzbDrone.Update.Test/AutoMoq/AutoMoqer.cs b/NzbDrone.Update.Test/AutoMoq/AutoMoqer.cs
new file mode 100644
index 000000000..27b2eee78
--- /dev/null
+++ b/NzbDrone.Update.Test/AutoMoq/AutoMoqer.cs
@@ -0,0 +1,166 @@
+// ReSharper disable RedundantUsingDirective
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Runtime.CompilerServices;
+using AutoMoq.Unity;
+using Microsoft.Practices.Unity;
+using Moq;
+using Moq.Language.Flow;
+
+[assembly: InternalsVisibleTo("AutoMoq.Tests")]
+
+namespace AutoMoq
+{
+    public class AutoMoqer
+    {
+        internal readonly MockBehavior DefaultBehavior = MockBehavior.Default;
+        internal Type ResolveType;
+        private IUnityContainer container;
+        private IDictionary<Type, object> registeredMocks;
+
+        public AutoMoqer()
+        {
+            SetupAutoMoqer(new UnityContainer());
+        }
+
+        public AutoMoqer(MockBehavior defaultBehavior)
+        {
+            DefaultBehavior = defaultBehavior;
+            SetupAutoMoqer(new UnityContainer());
+
+        }
+
+        internal AutoMoqer(IUnityContainer container)
+        {
+            SetupAutoMoqer(container);
+        }
+
+        public virtual T Resolve<T>()
+        {
+            ResolveType = typeof(T);
+            var result = container.Resolve<T>();
+            SetConstant(result);
+            ResolveType = null;
+            return result;
+        }
+
+        public virtual Mock<T> GetMock<T>() where T : class
+        {
+            return GetMock<T>(DefaultBehavior);
+        }
+
+        public virtual Mock<T> GetMock<T>(MockBehavior behavior) where T : class
+        {
+            ResolveType = null;
+            var type = GetTheMockType<T>();
+            if (GetMockHasNotBeenCalledForThisType(type))
+            {
+                CreateANewMockAndRegisterIt<T>(type, behavior);
+            }
+
+            var mock = TheRegisteredMockForThisType<T>(type);
+
+            if (behavior != MockBehavior.Default && mock.Behavior == MockBehavior.Default)
+            {
+                throw new InvalidOperationException("Unable to change be behaviour of a an existing mock.");
+            }
+
+            return mock;
+        }
+
+        internal virtual void SetMock(Type type, Mock mock)
+        {
+            if (registeredMocks.ContainsKey(type) == false)
+                registeredMocks.Add(type, mock);
+        }
+
+        public virtual void SetConstant<T>(T instance)
+        {
+            container.RegisterInstance(instance);
+            SetMock(instance.GetType(), null);
+        }
+
+        public ISetup<T> Setup<T>(Expression<Action<T>> expression) where T : class
+        {
+            return GetMock<T>().Setup(expression);
+        }
+
+        public ISetup<T, TResult> Setup<T, TResult>(Expression<Func<T, TResult>> expression) where T : class
+        {
+            return GetMock<T>().Setup(expression);
+        }
+
+        public void Verify<T>(Expression<Action<T>> expression) where T : class
+        {
+            GetMock<T>().Verify(expression);
+        }
+
+        public void Verify<T>(Expression<Action<T>> expression, string failMessage) where T : class
+        {
+            GetMock<T>().Verify(expression, failMessage);
+        }
+
+        public void Verify<T>(Expression<Action<T>> expression, Times times) where T : class
+        {
+            GetMock<T>().Verify(expression, times);
+        }
+
+        public void Verify<T>(Expression<Action<T>> expression, Times times, string failMessage) where T : class
+        {
+            GetMock<T>().Verify(expression, times, failMessage);
+        }
+
+        public void VerifyAllMocks()
+        {
+            foreach (var registeredMock in registeredMocks)
+            {
+                var mock = registeredMock.Value as Mock;
+                if (mock != null)
+                    mock.VerifyAll();
+            }
+        }
+
+        #region private methods
+
+        private void SetupAutoMoqer(IUnityContainer container)
+        {
+            this.container = container;
+            container.RegisterInstance(this);
+
+            registeredMocks = new Dictionary<Type, object>();
+            AddTheAutoMockingContainerExtensionToTheContainer(container);
+        }
+
+        private static void AddTheAutoMockingContainerExtensionToTheContainer(IUnityContainer container)
+        {
+            container.AddNewExtension<AutoMockingContainerExtension>();
+            return;
+        }
+
+        private Mock<T> TheRegisteredMockForThisType<T>(Type type) where T : class
+        {
+            return (Mock<T>)registeredMocks.Where(x => x.Key == type).First().Value;
+        }
+
+        private void CreateANewMockAndRegisterIt<T>(Type type, MockBehavior behavior) where T : class
+        {
+            var mock = new Mock<T>(behavior);
+            container.RegisterInstance(mock.Object);
+            SetMock(type, mock);
+        }
+
+        private bool GetMockHasNotBeenCalledForThisType(Type type)
+        {
+            return registeredMocks.ContainsKey(type) == false;
+        }
+
+        private static Type GetTheMockType<T>() where T : class
+        {
+            return typeof(T);
+        }
+
+        #endregion
+    }
+}
\ No newline at end of file
diff --git a/NzbDrone.Update.Test/AutoMoq/AutoMoqerTest.cs b/NzbDrone.Update.Test/AutoMoq/AutoMoqerTest.cs
new file mode 100644
index 000000000..da0677763
--- /dev/null
+++ b/NzbDrone.Update.Test/AutoMoq/AutoMoqerTest.cs
@@ -0,0 +1,187 @@
+// ReSharper disable RedundantUsingDirective
+using System;
+using AutoMoq;
+using Moq;
+using NUnit.Framework;
+
+namespace NzbDrone.App.Test
+{
+    [TestFixture]
+    // ReSharper disable InconsistentNaming
+    public class AutoMoqerTest
+    {
+        [Test]
+        public void GetMock_on_interface_returns_mock()
+        {
+            //Arrange
+            var mocker = new AutoMoqer();
+
+            //Act
+            var mock = mocker.GetMock<IDependency>();
+
+            //Assert
+            Assert.IsNotNull(mock);
+        }
+
+        [Test]
+        public void GetMock_on_concrete_returns_mock()
+        {
+            //Arrange
+            var mocker = new AutoMoqer();
+
+            //Act
+            var mock = mocker.GetMock<ConcreteClass>();
+
+            //Assert
+            Assert.IsNotNull(mock);
+        }
+
+
+        [Test]
+        public void Resolve_doesnt_return_mock()
+        {
+            //Arrange
+            var mocker = new AutoMoqer();
+
+            //Act
+            var result = mocker.Resolve<ConcreteClass>().Do();
+
+            //Assert
+            Assert.AreEqual("hello", result);
+        }
+
+        [Test]
+        public void Resolve_with_dependency_doesnt_return_mock()
+        {
+            //Arrange
+            var mocker = new AutoMoqer();
+
+            //Act
+            var result = mocker.Resolve<VirtualDependency>().VirtualMethod();
+
+            //Assert
+            Assert.AreEqual("hello", result);
+        }
+
+        [Test]
+        public void Resolve_with_mocked_dependency_uses_mock()
+        {
+            //Arrange
+            var mocker = new AutoMoqer();
+
+            mocker.GetMock<VirtualDependency>()
+                .Setup(m => m.VirtualMethod())
+                .Returns("mocked");
+
+            //Act
+            var result = mocker.Resolve<ClassWithVirtualDependencies>().CallVirtualChild();
+
+            //Assert
+            Assert.AreEqual("mocked", result);
+        }
+
+
+        [Test]
+        public void Resolve_with_unbound_concerete_dependency_uses_mock()
+        {
+            //Arrange
+            var mocker = new AutoMoqer();
+
+            //Act
+            var result = mocker.Resolve<ClassWithVirtualDependencies>().CallVirtualChild();
+
+            var mockedResult = new Mock<VirtualDependency>().Object.VirtualMethod();
+
+            //Assert
+            Assert.AreEqual(mockedResult, result);
+        }
+
+
+        [Test]
+        public void Resolve_with_constant_concerete_dependency_uses_constant()
+        {
+            //Arrange
+            var mocker = new AutoMoqer();
+
+            var constant = new VirtualDependency { PropValue = Guid.NewGuid().ToString() };
+
+            mocker.SetConstant(constant);
+
+            //Act
+            var result = mocker.Resolve<ClassWithVirtualDependencies>().GetVirtualProperty();
+
+            //Assert
+            Assert.AreEqual(constant.PropValue, result);
+        }
+    }
+
+    public class ConcreteClass
+    {
+        public string Do()
+        {
+            return "hello";
+        }
+    }
+
+    public class Dependency : IDependency
+    {
+    }
+
+    public interface IDependency
+    {
+    }
+
+    public class ClassWithDependencies
+    {
+        public ClassWithDependencies(IDependency dependency)
+        {
+            Dependency = dependency;
+        }
+
+        public IDependency Dependency { get; set; }
+    }
+
+    public class ClassWithVirtualDependencies
+    {
+        private readonly VirtualDependency _virtualDependency;
+
+        public ClassWithVirtualDependencies(IDependency dependency, VirtualDependency virtualDependency)
+        {
+            _virtualDependency = virtualDependency;
+            Dependency = dependency;
+        }
+
+        public IDependency Dependency { get; set; }
+
+        public string CallVirtualChild()
+        {
+            return _virtualDependency.VirtualMethod();
+        }
+
+        public string GetVirtualProperty()
+        {
+            return _virtualDependency.PropValue;
+        }
+    }
+
+    public class VirtualDependency
+    {
+        private readonly IDependency _dependency;
+
+        public VirtualDependency()
+        {
+        }
+
+        public VirtualDependency(IDependency dependency)
+        {
+            _dependency = dependency;
+        }
+
+        public string PropValue { get; set; }
+
+        public virtual string VirtualMethod()
+        {
+            return "hello";
+        }
+    }
+}
\ No newline at end of file
diff --git a/NzbDrone.Update.Test/AutoMoq/License.txt b/NzbDrone.Update.Test/AutoMoq/License.txt
new file mode 100644
index 000000000..5ead6991a
--- /dev/null
+++ b/NzbDrone.Update.Test/AutoMoq/License.txt
@@ -0,0 +1,22 @@
+ Copyright (c) 2010 Darren Cauthon
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without
+ restriction, including without limitation the rights to use,
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following
+ conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ OTHER DEALINGS IN THE SOFTWARE.
diff --git a/NzbDrone.Update.Test/AutoMoq/Unity/AutoMockingBuilderStrategy.cs b/NzbDrone.Update.Test/AutoMoq/Unity/AutoMockingBuilderStrategy.cs
new file mode 100644
index 000000000..af393fbee
--- /dev/null
+++ b/NzbDrone.Update.Test/AutoMoq/Unity/AutoMockingBuilderStrategy.cs
@@ -0,0 +1,84 @@
+// ReSharper disable RedundantUsingDirective
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using Microsoft.Practices.ObjectBuilder2;
+using Microsoft.Practices.Unity;
+using Moq;
+
+namespace AutoMoq.Unity
+{
+    internal class AutoMockingBuilderStrategy : BuilderStrategy
+    {
+        private readonly IUnityContainer _container;
+        private readonly MockRepository _mockFactory;
+        private readonly IEnumerable<Type> _registeredTypes;
+
+        public AutoMockingBuilderStrategy(IEnumerable<Type> registeredTypes, IUnityContainer container)
+        {
+            var autoMoqer = container.Resolve<AutoMoqer>();
+            _mockFactory = new MockRepository(autoMoqer.DefaultBehavior);
+            _registeredTypes = registeredTypes;
+            _container = container;
+        }
+
+        public override void PreBuildUp(IBuilderContext context)
+        {
+            var autoMoqer = _container.Resolve<AutoMoqer>();
+
+            var type = GetTheTypeFromTheBuilderContext(context);
+            if (AMockObjectShouldBeCreatedForThisType(type))
+            {
+                var mock = CreateAMockObject(type);
+                context.Existing = mock.Object;
+                autoMoqer.SetMock(type, mock);
+            }
+        }
+
+        #region private methods
+
+        private bool AMockObjectShouldBeCreatedForThisType(Type type)
+        {
+            var mocker = _container.Resolve<AutoMoqer>();
+            return TypeIsNotRegistered(type) && (mocker.ResolveType == null || mocker.ResolveType != type);
+            //return TypeIsNotRegistered(type) && type.IsInterface;
+        }
+
+        private static Type GetTheTypeFromTheBuilderContext(IBuilderContext context)
+        {
+            return (context.OriginalBuildKey).Type;
+        }
+
+        private bool TypeIsNotRegistered(Type type)
+        {
+            return _registeredTypes.Any(x => x.Equals(type)) == false;
+        }
+
+        private Mock CreateAMockObject(Type type)
+        {
+            var createMethod = GenerateAnInterfaceMockCreationMethod(type);
+
+            return InvokeTheMockCreationMethod(createMethod);
+        }
+
+        private Mock InvokeTheMockCreationMethod(MethodInfo createMethod)
+        {
+            return (Mock)createMethod.Invoke(_mockFactory, new object[] { new List<object>().ToArray() });
+        }
+
+        private MethodInfo GenerateAnInterfaceMockCreationMethod(Type type)
+        {
+            var createMethodWithNoParameters = _mockFactory.GetType().GetMethod("Create", EmptyArgumentList());
+
+            return createMethodWithNoParameters.MakeGenericMethod(new[] { type });
+        }
+
+        private static Type[] EmptyArgumentList()
+        {
+            return new[] { typeof(object[]) };
+        }
+
+        #endregion
+    }
+}
\ No newline at end of file
diff --git a/NzbDrone.Update.Test/AutoMoq/Unity/AutoMockingContainerExtension.cs b/NzbDrone.Update.Test/AutoMoq/Unity/AutoMockingContainerExtension.cs
new file mode 100644
index 000000000..d9979df32
--- /dev/null
+++ b/NzbDrone.Update.Test/AutoMoq/Unity/AutoMockingContainerExtension.cs
@@ -0,0 +1,40 @@
+// ReSharper disable RedundantUsingDirective
+using System;
+using System.Collections.Generic;
+using Microsoft.Practices.Unity;
+using Microsoft.Practices.Unity.ObjectBuilder;
+
+namespace AutoMoq.Unity
+{
+    internal class AutoMockingContainerExtension : UnityContainerExtension
+    {
+        private readonly IList<Type> registeredTypes = new List<Type>();
+
+        protected override void Initialize()
+        {
+            SetEventsOnContainerToTrackAllRegisteredTypes();
+            SetBuildingStrategyForBuildingUnregisteredTypes();
+        }
+
+        #region private methods
+
+        private void SetEventsOnContainerToTrackAllRegisteredTypes()
+        {
+            Context.Registering += ((sender, e) => RegisterType(e.TypeFrom));
+            Context.RegisteringInstance += ((sender, e) => RegisterType(e.RegisteredType));
+        }
+
+        private void RegisterType(Type typeToRegister)
+        {
+            registeredTypes.Add(typeToRegister);
+        }
+
+        private void SetBuildingStrategyForBuildingUnregisteredTypes()
+        {
+            var strategy = new AutoMockingBuilderStrategy(registeredTypes, Container);
+            Context.Strategies.Add(strategy, UnityBuildStage.PreCreation);
+        }
+
+        #endregion
+    }
+}
\ No newline at end of file
diff --git a/NzbDrone.Update.Test/NzbDrone.Update.Test.csproj b/NzbDrone.Update.Test/NzbDrone.Update.Test.csproj
new file mode 100644
index 000000000..1f4961b90
--- /dev/null
+++ b/NzbDrone.Update.Test/NzbDrone.Update.Test.csproj
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>NzbDrone.Update.Test</RootNamespace>
+    <AssemblyName>NzbDrone.Update.Test</AssemblyName>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <TargetFrameworkProfile>
+    </TargetFrameworkProfile>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+    <PlatformTarget>x86</PlatformTarget>
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+    <PlatformTarget>x86</PlatformTarget>
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup>
+    <StartupObject />
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="FluentAssertions">
+      <HintPath>..\packages\FluentAssertions.1.5.0.0\Lib\.NetFramework 4.0\FluentAssertions.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Practices.ServiceLocation">
+      <HintPath>..\packages\CommonServiceLocator.1.0\lib\NET35\Microsoft.Practices.ServiceLocation.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Practices.Unity">
+      <HintPath>..\packages\Unity.2.1.505.0\lib\NET35\Microsoft.Practices.Unity.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Practices.Unity.Configuration">
+      <HintPath>..\packages\Unity.2.1.505.0\lib\NET35\Microsoft.Practices.Unity.Configuration.dll</HintPath>
+    </Reference>
+    <Reference Include="Moq">
+      <HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath>
+    </Reference>
+    <Reference Include="nunit.framework">
+      <HintPath>..\packages\NUnit.2.5.10.11092\lib\nunit.framework.dll</HintPath>
+    </Reference>
+    <Reference Include="nunit.mocks">
+      <HintPath>..\packages\NUnit.2.5.10.11092\lib\nunit.mocks.dll</HintPath>
+    </Reference>
+    <Reference Include="pnunit.framework">
+      <HintPath>..\packages\NUnit.2.5.10.11092\lib\pnunit.framework.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="AutoMoq\AutoMoqer.cs" />
+    <Compile Include="AutoMoq\AutoMoqerTest.cs" />
+    <Compile Include="AutoMoq\Unity\AutoMockingBuilderStrategy.cs" />
+    <Compile Include="AutoMoq\Unity\AutoMockingContainerExtension.cs" />
+    <Compile Include="UpdateProviderTest.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\NzbDrone.Common\NzbDrone.Common.csproj">
+      <Project>{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}</Project>
+      <Name>NzbDrone.Common</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\NzbDrone.Update\NzbDrone.Update.csproj">
+      <Project>{4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}</Project>
+      <Name>NzbDrone.Update</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="AutoMoq\License.txt" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/NzbDrone.Update.Test/Properties/AssemblyInfo.cs b/NzbDrone.Update.Test/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..14909adac
--- /dev/null
+++ b/NzbDrone.Update.Test/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("NzbDrone.Update.Test")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("NzbDrone.Update.Test")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[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("b323e212-2d04-4c7f-9097-c356749ace4d")]
+
+// 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/NzbDrone.Update.Test/UpdateProviderTest.cs b/NzbDrone.Update.Test/UpdateProviderTest.cs
new file mode 100644
index 000000000..5bb4e84aa
--- /dev/null
+++ b/NzbDrone.Update.Test/UpdateProviderTest.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using AutoMoq;
+using Moq;
+using NUnit.Framework;
+using NzbDrone.Common;
+using NzbDrone.Update.Providers;
+
+namespace NzbDrone.Update.Test
+{
+    [TestFixture]
+    class UpdateProviderTest
+    {
+        AutoMoqer mocker = new AutoMoqer();
+
+        [SetUp]
+        public void Setup()
+        {
+            mocker = new AutoMoqer();
+
+            mocker.GetMock<EnviromentProvider>()
+                .Setup(c => c.StartUpPath).Returns(@"C:\Temp\NzbDrone_update\");
+        }
+
+
+        [Test]
+        public void update_should_abort_with_message_if_update_package_isnt_in_current_folder()
+        {
+           string sandboxFolder = @"C:\Temp\NzbDrone_update\nzbdrone_update";
+            mocker.GetMock<DiskProvider>()
+                .Setup(c => c.FolderExists(sandboxFolder)).
+                Returns(false);
+
+            mocker.GetMock<ServiceProvider>(MockBehavior.Strict);
+
+            //Act
+            mocker.Resolve<UpdateProvider>().Start();
+
+            //Assert
+            mocker.GetMock<ConsoleProvider>().Verify(c => c.UpdateFolderDoestExist(sandboxFolder), Times.Once());
+            mocker.VerifyAllMocks();
+        }
+
+        [Test]
+        public void should_stop_nzbdrone_service_if_installed()
+        {
+            mocker.GetMock<DiskProvider>()
+                 .Setup(c => c.FolderExists(It.IsAny<string>())).
+                 Returns(true);
+
+            mocker.GetMock<ServiceProvider>()
+                .Setup(c => c.ServiceExist(ServiceProvider.NzbDroneServiceName))
+                .Returns(true);
+            
+            //Act
+            mocker.Resolve<UpdateProvider>().Start();
+
+            //Assert
+            mocker.GetMock<ServiceProvider>().Verify(c => c.Stop(ServiceProvider.NzbDroneServiceName), Times.Once());
+            mocker.VerifyAllMocks();
+        }
+    }
+}
diff --git a/NzbDrone.Update.Test/packages.config b/NzbDrone.Update.Test/packages.config
new file mode 100644
index 000000000..6617e506c
--- /dev/null
+++ b/NzbDrone.Update.Test/packages.config
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="CommonServiceLocator" version="1.0" />
+  <package id="FluentAssertions" version="1.5.0.0" />
+  <package id="Moq" version="4.0.10827" />
+  <package id="NUnit" version="2.5.10.11092" />
+  <package id="Unity" version="2.1.505.0" />
+</packages>
\ No newline at end of file
diff --git a/NzbDrone.Update/NzbDrone.Update.csproj b/NzbDrone.Update/NzbDrone.Update.csproj
new file mode 100644
index 000000000..683cef1b4
--- /dev/null
+++ b/NzbDrone.Update/NzbDrone.Update.csproj
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>NzbDrone.Update</RootNamespace>
+    <AssemblyName>NzbDrone.Update</AssemblyName>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+    <PlatformTarget>x86</PlatformTarget>
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+    <PlatformTarget>x86</PlatformTarget>
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="NLog">
+      <HintPath>..\packages\NLog.2.0.0.2000\lib\net40\NLog.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Providers\DiskProvider.cs" />
+    <Compile Include="Providers\UpdateProvider.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\NzbDrone.Common\NzbDrone.Common.csproj">
+      <Project>{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}</Project>
+      <Name>NzbDrone.Common</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/NzbDrone.Update/Program.cs b/NzbDrone.Update/Program.cs
new file mode 100644
index 000000000..01701488b
--- /dev/null
+++ b/NzbDrone.Update/Program.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace NzbDrone.Update
+{
+    class Program
+    {
+        static void Main(string[] args)
+        {
+            
+        }
+    }
+}
diff --git a/NzbDrone.Update/Properties/AssemblyInfo.cs b/NzbDrone.Update/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..2039adee8
--- /dev/null
+++ b/NzbDrone.Update/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("NzbDrone.Update")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("NzbDrone.Update")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[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("e4560a3d-8053-4d57-a260-bfe52f4cc357")]
+
+// 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/NzbDrone.Update/Providers/DiskProvider.cs b/NzbDrone.Update/Providers/DiskProvider.cs
new file mode 100644
index 000000000..b5b5b85a4
--- /dev/null
+++ b/NzbDrone.Update/Providers/DiskProvider.cs
@@ -0,0 +1,87 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using NLog;
+
+namespace NzbDrone.Update.Providers
+{
+    public class DiskProvider
+    {
+        private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
+
+        public virtual bool FolderExists(string path)
+        {
+            return Directory.Exists(path);
+        }
+
+        public virtual bool FileExists(string path)
+        {
+            return File.Exists(path);
+        }
+
+        public virtual string[] GetDirectories(string path)
+        {
+            return Directory.GetDirectories(path);
+        }
+
+        public virtual string[] GetFiles(string path, SearchOption searchOption)
+        {
+            return Directory.GetFiles(path, "*.*", searchOption);
+        }
+
+        public virtual long GetDirectorySize(string path)
+        {
+            return GetFiles(path, SearchOption.AllDirectories).Sum(e => new FileInfo(e).Length);
+        }
+
+        public virtual long GetSize(string path)
+        {
+            var fi = new FileInfo(path);
+            return fi.Length;
+            //return new FileInfo(path).Length;
+        }
+
+        public virtual String CreateDirectory(string path)
+        {
+            return Directory.CreateDirectory(path).FullName;
+        }
+
+        public virtual void DeleteFile(string path)
+        {
+            File.Delete(path);
+        }
+
+        public virtual void MoveFile(string sourcePath, string destinationPath)
+        {
+            File.Move(sourcePath, destinationPath);
+        }
+
+        public virtual void DeleteFolder(string path, bool recursive)
+        {
+            Directory.Delete(path, recursive);
+        }
+
+        public virtual DateTime DirectoryDateCreated(string path)
+        {
+            return Directory.GetCreationTime(path);
+        }
+
+        public virtual IEnumerable<FileInfo> GetFileInfos(string path, string pattern, SearchOption searchOption)
+        {
+            return new DirectoryInfo(path).GetFiles(pattern, searchOption);
+        }
+
+        public virtual void MoveDirectory(string source, string destination)
+        {
+            Directory.Move(source, destination);
+        }
+
+        public virtual void InheritFolderPermissions(string filename)
+        {
+            var fs = File.GetAccessControl(filename);
+            fs.SetAccessRuleProtection(false, false);
+            File.SetAccessControl(filename, fs);
+        }
+    }
+}
diff --git a/NzbDrone.Update/Providers/UpdateProvider.cs b/NzbDrone.Update/Providers/UpdateProvider.cs
new file mode 100644
index 000000000..6dbec1410
--- /dev/null
+++ b/NzbDrone.Update/Providers/UpdateProvider.cs
@@ -0,0 +1,56 @@
+using System.IO;
+using NLog;
+using NzbDrone.Common;
+
+namespace NzbDrone.Update.Providers
+{
+    public class UpdateProvider
+    {
+        private readonly DiskProvider _diskProvider;
+        private readonly EnviromentProvider _enviromentProvider;
+        private readonly ConsoleProvider _consoleProvider;
+        private readonly ServiceProvider _serviceProvider;
+        private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
+
+        public UpdateProvider(DiskProvider diskProvider, EnviromentProvider enviromentProvider, ConsoleProvider consoleProvider,
+            ServiceProvider serviceProvider)
+        {
+            _diskProvider = diskProvider;
+            _enviromentProvider = enviromentProvider;
+            _consoleProvider = consoleProvider;
+            _serviceProvider = serviceProvider;
+        }
+
+        public void Start()
+        {
+            var sandboxFolder = Path.Combine(_enviromentProvider.StartUpPath, "nzbdrone_update");
+            Logger.Info("Looking for update package at {0}", sandboxFolder);
+
+            Logger.Info("Verifying Update Folder");
+            if (!_diskProvider.FolderExists(sandboxFolder))
+            {
+                Logger.Error("Update folder doesn't exist {0}", sandboxFolder);
+                _consoleProvider.UpdateFolderDoestExist(sandboxFolder);
+                return;
+            }
+
+            if (_serviceProvider.ServiceExist(ServiceProvider.NzbDroneServiceName))
+            {
+                _serviceProvider.Stop(ServiceProvider.NzbDroneServiceName);
+            }
+
+            //Stop NzbDrone Process
+
+            //Create backup of current folder
+
+            //Copy update folder on top of the existing folder
+
+            //Happy: Start Service, Process?
+            //Happy: Cleanup
+
+            //Sad: delete fucked up folder
+            //Sad: restore backup
+            //Sad: start service, process
+        }
+    }
+}
diff --git a/NzbDrone.Update/packages.config b/NzbDrone.Update/packages.config
new file mode 100644
index 000000000..4f6876419
--- /dev/null
+++ b/NzbDrone.Update/packages.config
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="NLog" version="2.0.0.2000" />
+</packages>
\ No newline at end of file
diff --git a/NzbDrone.sln b/NzbDrone.sln
index 86479c451..7551226fe 100644
--- a/NzbDrone.sln
+++ b/NzbDrone.sln
@@ -15,6 +15,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NzbDrone.App.Test", "NzbDro
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NzbDrone.Test.Dummy", "NzbDrone.Test.Dummy\NzbDrone.Test.Dummy.csproj", "{FAFB5948-A222-4CF6-AD14-026BE7564802}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NzbDrone.Update", "NzbDrone.Update\NzbDrone.Update.csproj", "{4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NzbDrone.Update.Test", "NzbDrone.Update.Test\NzbDrone.Update.Test.csproj", "{35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NzbDrone.Common", "NzbDrone.Common\NzbDrone.Common.csproj", "{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -105,6 +111,42 @@ Global
 		{FAFB5948-A222-4CF6-AD14-026BE7564802}.Release|x64.ActiveCfg = Release|x86
 		{FAFB5948-A222-4CF6-AD14-026BE7564802}.Release|x86.ActiveCfg = Release|x86
 		{FAFB5948-A222-4CF6-AD14-026BE7564802}.Release|x86.Build.0 = Release|x86
+		{4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Debug|Any CPU.ActiveCfg = Debug|x86
+		{4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+		{4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Debug|Mixed Platforms.Build.0 = Debug|x86
+		{4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Debug|x64.ActiveCfg = Debug|x86
+		{4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Debug|x86.ActiveCfg = Debug|x86
+		{4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Debug|x86.Build.0 = Debug|x86
+		{4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Release|Any CPU.ActiveCfg = Release|x86
+		{4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Release|Mixed Platforms.ActiveCfg = Release|x86
+		{4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Release|Mixed Platforms.Build.0 = Release|x86
+		{4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Release|x64.ActiveCfg = Release|x86
+		{4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Release|x86.ActiveCfg = Release|x86
+		{4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Release|x86.Build.0 = Release|x86
+		{35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Debug|Any CPU.ActiveCfg = Debug|x86
+		{35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+		{35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Debug|Mixed Platforms.Build.0 = Debug|x86
+		{35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Debug|x64.ActiveCfg = Debug|x86
+		{35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Debug|x86.ActiveCfg = Debug|x86
+		{35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Debug|x86.Build.0 = Debug|x86
+		{35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Release|Any CPU.ActiveCfg = Release|x86
+		{35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Release|Mixed Platforms.ActiveCfg = Release|x86
+		{35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Release|Mixed Platforms.Build.0 = Release|x86
+		{35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Release|x64.ActiveCfg = Release|x86
+		{35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Release|x86.ActiveCfg = Release|x86
+		{35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Release|x86.Build.0 = Release|x86
+		{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Release|Any CPU.Build.0 = Release|Any CPU
+		{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Release|x64.ActiveCfg = Release|Any CPU
+		{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Release|x86.ActiveCfg = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -113,6 +155,7 @@ Global
 		{193ADD3B-792B-4173-8E4C-5A3F8F0237F0} = {57A04B72-8088-4F75-A582-1158CF8291F7}
 		{C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5} = {57A04B72-8088-4F75-A582-1158CF8291F7}
 		{FAFB5948-A222-4CF6-AD14-026BE7564802} = {57A04B72-8088-4F75-A582-1158CF8291F7}
+		{35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97} = {57A04B72-8088-4F75-A582-1158CF8291F7}
 	EndGlobalSection
 	GlobalSection(ExtensibilityGlobals) = postSolution
 		EnterpriseLibraryConfigurationToolBinariesPath = packages\Unity.2.1.505.0\lib\NET35
diff --git a/NzbDrone/ApplicationServer.cs b/NzbDrone/ApplicationServer.cs
index 3da83013c..145869b5c 100644
--- a/NzbDrone/ApplicationServer.cs
+++ b/NzbDrone/ApplicationServer.cs
@@ -3,6 +3,7 @@ using System.Net;
 using System.ServiceProcess;
 using NLog;
 using Ninject;
+using NzbDrone.Common;
 using NzbDrone.Providers;
 
 namespace NzbDrone
diff --git a/NzbDrone/CentralDispatch.cs b/NzbDrone/CentralDispatch.cs
index bff41dd9b..5cc627913 100644
--- a/NzbDrone/CentralDispatch.cs
+++ b/NzbDrone/CentralDispatch.cs
@@ -1,5 +1,6 @@
 using NLog;
 using Ninject;
+using NzbDrone.Common;
 using NzbDrone.Providers;
 
 namespace NzbDrone
diff --git a/NzbDrone/NzbDrone.csproj b/NzbDrone/NzbDrone.csproj
index 3388bedd5..110f99f34 100644
--- a/NzbDrone/NzbDrone.csproj
+++ b/NzbDrone/NzbDrone.csproj
@@ -93,19 +93,13 @@
     <Compile Include="CentralDispatch.cs" />
     <Compile Include="Model\ApplicationMode.cs" />
     <Compile Include="Model\AuthenticationType.cs" />
-    <Compile Include="Model\ProcessInfo.cs" />
-    <Compile Include="Providers\ConsoleProvider.cs" />
     <Compile Include="Providers\DebuggerProvider.cs" />
-    <Compile Include="Providers\EnviromentProvider.cs" />
     <Compile Include="ProcessAttacher.cs" />
     <Compile Include="Providers\ConfigProvider.cs" />
     <Compile Include="Providers\IISProvider.cs" />
     <Compile Include="AppMain.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Providers\MonitoringProvider.cs" />
-    <Compile Include="Providers\ProcessProvider.cs" />
-    <Compile Include="Providers\ServiceProvider.cs" />
-    <Compile Include="Providers\WebClientProvider.cs" />
     <Compile Include="Router.cs" />
   </ItemGroup>
   <ItemGroup>
@@ -137,7 +131,12 @@
       <Install>true</Install>
     </BootstrapperPackage>
   </ItemGroup>
-  <ItemGroup />
+  <ItemGroup>
+    <ProjectReference Include="..\NzbDrone.Common\NzbDrone.Common.csproj">
+      <Project>{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}</Project>
+      <Name>NzbDrone.Common</Name>
+    </ProjectReference>
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <PropertyGroup>
     <PreBuildEvent>
diff --git a/NzbDrone/Providers/ConfigProvider.cs b/NzbDrone/Providers/ConfigProvider.cs
index 3e4cf5dd6..42074d2fb 100644
--- a/NzbDrone/Providers/ConfigProvider.cs
+++ b/NzbDrone/Providers/ConfigProvider.cs
@@ -6,6 +6,7 @@ using System.Xml.XPath;
 using NLog;
 using NLog.Config;
 using Ninject;
+using NzbDrone.Common;
 using NzbDrone.Model;
 
 namespace NzbDrone.Providers
diff --git a/NzbDrone/Providers/IISProvider.cs b/NzbDrone/Providers/IISProvider.cs
index ce2478f7d..5f5bc5776 100644
--- a/NzbDrone/Providers/IISProvider.cs
+++ b/NzbDrone/Providers/IISProvider.cs
@@ -3,6 +3,8 @@ using System.Diagnostics;
 using System.IO;
 using NLog;
 using Ninject;
+using NzbDrone.Common;
+using NzbDrone.Common.Model;
 
 namespace NzbDrone.Providers
 {
diff --git a/NzbDrone/Providers/MonitoringProvider.cs b/NzbDrone/Providers/MonitoringProvider.cs
index 1ebd317e8..821408ea1 100644
--- a/NzbDrone/Providers/MonitoringProvider.cs
+++ b/NzbDrone/Providers/MonitoringProvider.cs
@@ -5,6 +5,7 @@ using System.Timers;
 using Exceptioneer.WindowsFormsClient;
 using NLog;
 using Ninject;
+using NzbDrone.Common;
 
 namespace NzbDrone.Providers
 {
diff --git a/NzbDrone/Providers/ServiceProvider.cs b/NzbDrone/Providers/ServiceProvider.cs
deleted file mode 100644
index 8667b28ad..000000000
--- a/NzbDrone/Providers/ServiceProvider.cs
+++ /dev/null
@@ -1,73 +0,0 @@
-using System;
-using System.Collections.Specialized;
-using System.Configuration.Install;
-using System.Linq;
-using System.Reflection;
-using System.ServiceProcess;
-using NLog;
-
-namespace NzbDrone.Providers
-{
-    public class ServiceProvider
-    {
-        public const string NzbDroneServiceName = "NzbDrone";
-
-        private static readonly Logger Logger = LogManager.GetLogger("Host.ServiceManager");
-
-
-
-
-        public virtual bool ServiceExist(string name)
-        {
-            return
-                ServiceController.GetServices().Any(
-                    s => String.Equals(s.ServiceName, name, StringComparison.InvariantCultureIgnoreCase));
-        }
-
-
-        public virtual void Install()
-        {
-            Logger.Info("Installing service '{0}'", NzbDroneServiceName);
-
-
-            var installer = new ServiceProcessInstaller
-                                {
-                                    Account = ServiceAccount.LocalSystem
-                                };
-
-            var serviceInstaller = new ServiceInstaller();
-
-
-            String[] cmdline = { @"/assemblypath=" + Assembly.GetExecutingAssembly().Location };
-
-            var context = new InstallContext("service_install.log", cmdline);
-            serviceInstaller.Context = context;
-            serviceInstaller.DisplayName = NzbDroneServiceName;
-            serviceInstaller.ServiceName = NzbDroneServiceName;
-            serviceInstaller.Description = "NzbDrone Application Server";
-            serviceInstaller.StartType = ServiceStartMode.Automatic;
-
-            serviceInstaller.Parent = installer;
-
-            serviceInstaller.Install(new ListDictionary());
-
-            Logger.Info("Service Has installed successfully.");
-        }
-
-        public virtual void UnInstall()
-        {
-            var serviceInstaller = new ServiceInstaller();
-
-            var context = new InstallContext("service_uninstall.log", null);
-            serviceInstaller.Context = context;
-            serviceInstaller.ServiceName = NzbDroneServiceName;
-            serviceInstaller.Uninstall(null);
-        }
-
-
-        public virtual void Run(ServiceBase service)
-        {
-            ServiceBase.Run(service);
-        }
-    }
-}
\ No newline at end of file
diff --git a/NzbDrone/Router.cs b/NzbDrone/Router.cs
index 7e72b3906..a61b818e4 100644
--- a/NzbDrone/Router.cs
+++ b/NzbDrone/Router.cs
@@ -2,8 +2,8 @@
 using System.Collections.Generic;
 using System.Linq;
 using NLog;
+using NzbDrone.Common;
 using NzbDrone.Model;
-using NzbDrone.Providers;
 
 namespace NzbDrone
 {
diff --git a/packages/repositories.config b/packages/repositories.config
index c3ebed446..5219697f0 100644
--- a/packages/repositories.config
+++ b/packages/repositories.config
@@ -5,4 +5,7 @@
   <repository path="..\NzbDrone.Core\packages.config" />
   <repository path="..\NzbDrone.App.Test\packages.config" />
   <repository path="..\NzbDrone\packages.config" />
+  <repository path="..\NzbDrone.Update.Test\packages.config" />
+  <repository path="..\NzbDrone.Update\packages.config" />
+  <repository path="..\NzbDrone.Common\packages.config" />
 </repositories>
\ No newline at end of file