More nzbdrone.exe refactoring.
This commit is contained in:
parent
69ba365cd3
commit
8bf4f81a04
|
@ -0,0 +1,39 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using AutoMoq;
|
||||||
|
using FizzWare.NBuilder;
|
||||||
|
using FluentAssertions;
|
||||||
|
using Moq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Providers;
|
||||||
|
|
||||||
|
namespace NzbDrone.App.Test
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class MonitoringProviderTest
|
||||||
|
{
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Ensure_priority_doesnt_fail_on_invalid_iis_proccess_id()
|
||||||
|
{
|
||||||
|
var mocker = new AutoMoqer();
|
||||||
|
|
||||||
|
var processMock = mocker.GetMock<ProcessProvider>();
|
||||||
|
processMock.Setup(c => c.GetCurrentProcess())
|
||||||
|
.Returns(Builder<ProcessInfo>.CreateNew().With(c => c.Priority == ProcessPriorityClass.Normal).Build());
|
||||||
|
|
||||||
|
processMock.Setup(c => c.GetProcessById(It.IsAny<int>())).Returns((ProcessInfo)null);
|
||||||
|
|
||||||
|
var subject = mocker.Resolve<MonitoringProvider>();
|
||||||
|
|
||||||
|
|
||||||
|
//Act
|
||||||
|
subject.EnsurePriority(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,187 @@
|
||||||
|
// ReSharper disable RedundantUsingDirective
|
||||||
|
using System;
|
||||||
|
using AutoMoq;
|
||||||
|
using Moq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.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";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using AutoMoq;
|
||||||
|
using FluentAssertions;
|
||||||
|
using Moq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Providers;
|
||||||
|
|
||||||
|
namespace NzbDrone.App.Test
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class IISProviderTest
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void start_should_set_IISProccessId_property()
|
||||||
|
{
|
||||||
|
var mocker = new AutoMoqer();
|
||||||
|
|
||||||
|
var configMock = mocker.GetMock<ConfigProvider>();
|
||||||
|
configMock.SetupGet(c => c.IISExePath).Returns("NzbDrone.Test.Dummy.exe");
|
||||||
|
|
||||||
|
mocker.Resolve<ProcessProvider>();
|
||||||
|
|
||||||
|
var iisProvider = mocker.Resolve<IISProvider>();
|
||||||
|
|
||||||
|
iisProvider.StartServer();
|
||||||
|
|
||||||
|
iisProvider.IISProcessId.Should().NotBe(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,9 +31,21 @@
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Reference Include="FizzWare.NBuilder">
|
||||||
|
<HintPath>..\packages\NBuilder.3.0.1\lib\FizzWare.NBuilder.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="FluentAssertions">
|
<Reference Include="FluentAssertions">
|
||||||
<HintPath>..\packages\FluentAssertions.1.5.0.0\Lib\.NetFramework 4.0\FluentAssertions.dll</HintPath>
|
<HintPath>..\packages\FluentAssertions.1.5.0.0\Lib\.NetFramework 4.0\FluentAssertions.dll</HintPath>
|
||||||
</Reference>
|
</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">
|
<Reference Include="Moq">
|
||||||
<HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath>
|
<HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
@ -56,6 +68,13 @@
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<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="ApplicationTest.cs" />
|
||||||
|
<Compile Include="IISProviderTest.cs" />
|
||||||
|
<Compile Include="ProcessProviderTests.cs" />
|
||||||
<Compile Include="EnviromentControllerTest.cs" />
|
<Compile Include="EnviromentControllerTest.cs" />
|
||||||
<Compile Include="ServiceControllerTests.cs" />
|
<Compile Include="ServiceControllerTests.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
@ -64,11 +83,18 @@
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\NzbDrone.Test.Dummy\NzbDrone.Test.Dummy.csproj">
|
||||||
|
<Project>{FAFB5948-A222-4CF6-AD14-026BE7564802}</Project>
|
||||||
|
<Name>NzbDrone.Test.Dummy</Name>
|
||||||
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\NzbDrone\NzbDrone.csproj">
|
<ProjectReference Include="..\NzbDrone\NzbDrone.csproj">
|
||||||
<Project>{D12F7F2F-8A3C-415F-88FA-6DD061A84869}</Project>
|
<Project>{D12F7F2F-8A3C-415F-88FA-6DD061A84869}</Project>
|
||||||
<Name>NzbDrone</Name>
|
<Name>NzbDrone</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="AutoMoq\License.txt" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
<!-- 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.
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using FluentAssertions;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Providers;
|
||||||
|
|
||||||
|
namespace NzbDrone.App.Test
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class ProcessProviderTests
|
||||||
|
{
|
||||||
|
ProcessProvider _processProvider;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
_processProvider = new ProcessProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(0)]
|
||||||
|
[TestCase(123332324)]
|
||||||
|
public void Kill_should_not_fail_on_invalid_process_is(int processId)
|
||||||
|
{
|
||||||
|
_processProvider.Kill(processId);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void GetById_should_return_null_if_process_doesnt_exist()
|
||||||
|
{
|
||||||
|
_processProvider.GetProcessById(1234567).Should().BeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Should_be_able_to_kill_procces()
|
||||||
|
{
|
||||||
|
var dummyProcess = StartDummyProcess();
|
||||||
|
_processProvider.Kill(dummyProcess.Id);
|
||||||
|
dummyProcess.HasExited.Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Process StartDummyProcess()
|
||||||
|
{
|
||||||
|
return Process.Start("NzbDrone.Test.Dummy.exe");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,9 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
|
<package id="CommonServiceLocator" version="1.0" />
|
||||||
<package id="FluentAssertions" version="1.5.0.0" />
|
<package id="FluentAssertions" version="1.5.0.0" />
|
||||||
<package id="Moq" version="4.0.10827" />
|
<package id="Moq" version="4.0.10827" />
|
||||||
|
<package id="NBuilder" version="3.0.1" />
|
||||||
<package id="NUnit" version="2.5.10.11092" />
|
<package id="NUnit" version="2.5.10.11092" />
|
||||||
|
<package id="Unity" version="2.1.505.0" />
|
||||||
</packages>
|
</packages>
|
|
@ -0,0 +1,57 @@
|
||||||
|
<?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>{FAFB5948-A222-4CF6-AD14-026BE7564802}</ProjectGuid>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>NzbDrone.Test.Dummy</RootNamespace>
|
||||||
|
<AssemblyName>NzbDrone.Test.Dummy</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="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" />
|
||||||
|
</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>
|
|
@ -0,0 +1,17 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace NzbDrone.Test.Dummy
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Dummy process. ID:{0} Path:{1}", Process.GetCurrentProcess().Id, Process.GetCurrentProcess().MainModule.FileName);
|
||||||
|
Console.ReadLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.Test.Dummy")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("Microsoft")]
|
||||||
|
[assembly: AssemblyProduct("NzbDrone.Test.Dummy")]
|
||||||
|
[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("7b773a86-574d-48c3-9e89-6f2e0dff714b")]
|
||||||
|
|
||||||
|
// 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")]
|
15
NzbDrone.sln
15
NzbDrone.sln
|
@ -13,6 +13,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{57A04B72
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NzbDrone.App.Test", "NzbDrone.App.Test\NzbDrone.App.Test.csproj", "{C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NzbDrone.App.Test", "NzbDrone.App.Test\NzbDrone.App.Test.csproj", "{C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NzbDrone.Test.Dummy", "NzbDrone.Test.Dummy\NzbDrone.Test.Dummy.csproj", "{FAFB5948-A222-4CF6-AD14-026BE7564802}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
@ -91,6 +93,18 @@ Global
|
||||||
{C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
{C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
{C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}.Release|x64.ActiveCfg = Release|Any CPU
|
{C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
{C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}.Release|x86.ActiveCfg = Release|Any CPU
|
{C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{FAFB5948-A222-4CF6-AD14-026BE7564802}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||||
|
{FAFB5948-A222-4CF6-AD14-026BE7564802}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
|
||||||
|
{FAFB5948-A222-4CF6-AD14-026BE7564802}.Debug|Mixed Platforms.Build.0 = Debug|x86
|
||||||
|
{FAFB5948-A222-4CF6-AD14-026BE7564802}.Debug|x64.ActiveCfg = Debug|x86
|
||||||
|
{FAFB5948-A222-4CF6-AD14-026BE7564802}.Debug|x86.ActiveCfg = Debug|x86
|
||||||
|
{FAFB5948-A222-4CF6-AD14-026BE7564802}.Debug|x86.Build.0 = Debug|x86
|
||||||
|
{FAFB5948-A222-4CF6-AD14-026BE7564802}.Release|Any CPU.ActiveCfg = Release|x86
|
||||||
|
{FAFB5948-A222-4CF6-AD14-026BE7564802}.Release|Mixed Platforms.ActiveCfg = Release|x86
|
||||||
|
{FAFB5948-A222-4CF6-AD14-026BE7564802}.Release|Mixed Platforms.Build.0 = Release|x86
|
||||||
|
{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
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
@ -98,6 +112,7 @@ Global
|
||||||
GlobalSection(NestedProjects) = preSolution
|
GlobalSection(NestedProjects) = preSolution
|
||||||
{193ADD3B-792B-4173-8E4C-5A3F8F0237F0} = {57A04B72-8088-4F75-A582-1158CF8291F7}
|
{193ADD3B-792B-4173-8E4C-5A3F8F0237F0} = {57A04B72-8088-4F75-A582-1158CF8291F7}
|
||||||
{C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5} = {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}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
EnterpriseLibraryConfigurationToolBinariesPath = packages\Unity.2.1.505.0\lib\NET35
|
EnterpriseLibraryConfigurationToolBinariesPath = packages\Unity.2.1.505.0\lib\NET35
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Timers;
|
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Providers;
|
using NzbDrone.Providers;
|
||||||
|
|
||||||
namespace NzbDrone
|
namespace NzbDrone
|
||||||
{
|
{
|
||||||
internal class Application
|
public class Application
|
||||||
{
|
{
|
||||||
private static readonly Logger Logger = LogManager.GetLogger("Application");
|
private static readonly Logger Logger = LogManager.GetLogger("Application");
|
||||||
|
|
||||||
|
@ -36,23 +34,15 @@ namespace NzbDrone
|
||||||
Logger.Info("Starting NZBDrone. Start-up Path:'{0}'", _configProvider.ApplicationRoot);
|
Logger.Info("Starting NZBDrone. Start-up Path:'{0}'", _configProvider.ApplicationRoot);
|
||||||
Thread.CurrentThread.Name = "Host";
|
Thread.CurrentThread.Name = "Host";
|
||||||
|
|
||||||
AppDomain.CurrentDomain.UnhandledException += ((s, e) => AppDomainException(e));
|
|
||||||
|
|
||||||
AppDomain.CurrentDomain.ProcessExit += ProgramExited;
|
|
||||||
AppDomain.CurrentDomain.DomainUnload += ProgramExited;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void Start()
|
public void Start()
|
||||||
{
|
{
|
||||||
_iisProvider.StopServer();
|
_iisProvider.StopServer();
|
||||||
_iisProvider.StartServer();
|
_iisProvider.StartServer();
|
||||||
|
|
||||||
_debuggerProvider.Attach();
|
_debuggerProvider.Attach();
|
||||||
|
|
||||||
var prioCheckTimer = new System.Timers.Timer(5000);
|
|
||||||
prioCheckTimer.Elapsed += EnsurePriority;
|
|
||||||
prioCheckTimer.Enabled = true;
|
|
||||||
|
|
||||||
if (_enviromentProvider.IsUserInteractive && _configProvider.LaunchBrowser)
|
if (_enviromentProvider.IsUserInteractive && _configProvider.LaunchBrowser)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -79,51 +69,10 @@ namespace NzbDrone
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void Stop()
|
public void Stop()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void AppDomainException(object excepion)
|
|
||||||
{
|
|
||||||
Console.WriteLine("EPIC FAIL: {0}", excepion);
|
|
||||||
Logger.Fatal("EPIC FAIL: {0}", excepion);
|
|
||||||
|
|
||||||
#if RELEASE
|
|
||||||
new Client
|
|
||||||
{
|
|
||||||
ApiKey = "43BBF60A-EB2A-4C1C-B09E-422ADF637265",
|
|
||||||
ApplicationName = "NZBDrone",
|
|
||||||
CurrentException = excepion as Exception
|
|
||||||
}.Submit();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal void EnsurePriority(object sender, ElapsedEventArgs e)
|
|
||||||
{
|
|
||||||
var currentProcessId = _processProvider.GetCurrentProcessId();
|
|
||||||
if (_processProvider.GetProcessPriority(currentProcessId) != ProcessPriorityClass.Normal)
|
|
||||||
{
|
|
||||||
_processProvider.SetPriority(_processProvider.GetCurrentProcessId(), ProcessPriorityClass.Normal);
|
|
||||||
}
|
|
||||||
|
|
||||||
var iisProcessPriority = _processProvider.GetProcessPriority(_iisProvider.IISProcessId);
|
|
||||||
if (iisProcessPriority != ProcessPriorityClass.Normal && iisProcessPriority != ProcessPriorityClass.AboveNormal)
|
|
||||||
{
|
|
||||||
_processProvider.SetPriority(_iisProvider.IISProcessId, ProcessPriorityClass.Normal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ProgramExited(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
_iisProvider.StopServer();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,6 +86,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Application.cs" />
|
<Compile Include="Application.cs" />
|
||||||
|
<Compile Include="ProcessInfo.cs" />
|
||||||
<Compile Include="Providers\ConsoleProvider.cs" />
|
<Compile Include="Providers\ConsoleProvider.cs" />
|
||||||
<Compile Include="Providers\DebuggerProvider.cs" />
|
<Compile Include="Providers\DebuggerProvider.cs" />
|
||||||
<Compile Include="Providers\EnviromentProvider.cs" />
|
<Compile Include="Providers\EnviromentProvider.cs" />
|
||||||
|
@ -97,6 +98,7 @@
|
||||||
<Compile Include="Providers\IISProvider.cs" />
|
<Compile Include="Providers\IISProvider.cs" />
|
||||||
<Compile Include="Program.cs" />
|
<Compile Include="Program.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="Providers\MonitoringProvider.cs" />
|
||||||
<Compile Include="Providers\ProcessProvider.cs" />
|
<Compile Include="Providers\ProcessProvider.cs" />
|
||||||
<Compile Include="Providers\ServiceProvider.cs" />
|
<Compile Include="Providers\ServiceProvider.cs" />
|
||||||
<Compile Include="Providers\WebClientProvider.cs" />
|
<Compile Include="Providers\WebClientProvider.cs" />
|
||||||
|
|
|
@ -10,17 +10,12 @@ using System.Collections.Generic;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using EnvDTE;
|
using EnvDTE;
|
||||||
using EnvDTE80;
|
using EnvDTE80;
|
||||||
using NLog;
|
|
||||||
using Thread = System.Threading.Thread;
|
using Thread = System.Threading.Thread;
|
||||||
|
|
||||||
namespace NzbDrone
|
namespace NzbDrone
|
||||||
{
|
{
|
||||||
public class ProcessAttacher
|
public class ProcessAttacher
|
||||||
{
|
{
|
||||||
|
|
||||||
private static readonly Logger Logger = LogManager.GetLogger("Application");
|
|
||||||
|
|
||||||
|
|
||||||
public static void Attach()
|
public static void Attach()
|
||||||
{
|
{
|
||||||
DTE2 dte2;
|
DTE2 dte2;
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace NzbDrone
|
||||||
|
{
|
||||||
|
public class ProcessInfo
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public ProcessPriorityClass Priority { get; set; }
|
||||||
|
public string StartPath { get; set; }
|
||||||
|
|
||||||
|
public bool HasExited { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,11 @@
|
||||||
using System;
|
using System;
|
||||||
using NLog;
|
using NLog;
|
||||||
using Ninject;
|
using Ninject;
|
||||||
|
using NzbDrone.Providers;
|
||||||
|
|
||||||
namespace NzbDrone
|
namespace NzbDrone
|
||||||
{
|
{
|
||||||
internal static class Program
|
public static class Program
|
||||||
{
|
{
|
||||||
public static readonly StandardKernel Kernel = new StandardKernel();
|
public static readonly StandardKernel Kernel = new StandardKernel();
|
||||||
|
|
||||||
|
@ -14,8 +15,20 @@ namespace NzbDrone
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
Kernel.Bind<ConfigProvider>().ToSelf().InSingletonScope();
|
||||||
|
Kernel.Bind<ConsoleProvider>().ToSelf().InSingletonScope();
|
||||||
|
Kernel.Bind<DebuggerProvider>().ToSelf().InSingletonScope();
|
||||||
|
Kernel.Bind<EnviromentProvider>().ToSelf().InSingletonScope();
|
||||||
|
Kernel.Bind<IISProvider>().ToSelf().InSingletonScope();
|
||||||
|
Kernel.Bind<MonitoringProvider>().ToSelf().InSingletonScope();
|
||||||
|
Kernel.Bind<ProcessProvider>().ToSelf().InSingletonScope();
|
||||||
|
Kernel.Bind<ServiceProvider>().ToSelf().InSingletonScope();
|
||||||
|
Kernel.Bind<WebClientProvider>().ToSelf().InSingletonScope();
|
||||||
|
|
||||||
Console.WriteLine("Starting Console.");
|
Console.WriteLine("Starting Console.");
|
||||||
|
Kernel.Get<MonitoringProvider>().Start();
|
||||||
Kernel.Get<Application>().Start();
|
Kernel.Get<Application>().Start();
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,15 +3,17 @@ using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
using System.Xml.XPath;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NLog.Config;
|
using NLog.Config;
|
||||||
|
|
||||||
namespace NzbDrone.Providers
|
namespace NzbDrone.Providers
|
||||||
{
|
{
|
||||||
internal class ConfigProvider
|
public class ConfigProvider
|
||||||
{
|
{
|
||||||
|
private static readonly Logger Logger = LogManager.GetLogger("ConfigProvider");
|
||||||
|
|
||||||
internal virtual string ApplicationRoot
|
public virtual string ApplicationRoot
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
@ -27,38 +29,74 @@ namespace NzbDrone.Providers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal virtual int Port
|
public virtual int Port
|
||||||
{
|
{
|
||||||
get { return GetValueInt("Port"); }
|
get { return GetValueInt("Port"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal virtual bool LaunchBrowser
|
public virtual bool LaunchBrowser
|
||||||
{
|
{
|
||||||
get { return GetValueBoolean("LaunchBrowser"); }
|
get { return GetValueBoolean("LaunchBrowser"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal virtual string AppDataDirectory
|
public virtual string AppDataDirectory
|
||||||
{
|
{
|
||||||
get { return Path.Combine(ApplicationRoot, "NzbDrone.Web", "App_Data"); }
|
get { return Path.Combine(ApplicationRoot, "NzbDrone.Web", "App_Data"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal virtual string ConfigFile
|
public virtual string ConfigFile
|
||||||
{
|
{
|
||||||
get { return Path.Combine(AppDataDirectory, "Config.xml"); }
|
get { return Path.Combine(AppDataDirectory, "Config.xml"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal virtual string IISFolder
|
public virtual string IISFolder
|
||||||
{
|
{
|
||||||
get { return Path.Combine(ApplicationRoot, @"IISExpress\"); }
|
get { return Path.Combine(ApplicationRoot, @"IISExpress\"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal virtual void ConfigureNlog()
|
public virtual string IISExePath
|
||||||
|
{
|
||||||
|
get { return IISFolder + @"iisexpress.exe"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual string IISConfigPath
|
||||||
|
{
|
||||||
|
get { return Path.Combine(IISFolder, "AppServer", "applicationhost.config"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void ConfigureNlog()
|
||||||
{
|
{
|
||||||
LogManager.Configuration = new XmlLoggingConfiguration(
|
LogManager.Configuration = new XmlLoggingConfiguration(
|
||||||
Path.Combine(ApplicationRoot, "NzbDrone.Web\\log.config"), false);
|
Path.Combine(ApplicationRoot, "NzbDrone.Web\\log.config"), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal virtual void CreateDefaultConfigFile()
|
public virtual void UpdateIISConfig(string configPath)
|
||||||
|
{
|
||||||
|
Logger.Info(@"Server configuration file: {0}", configPath);
|
||||||
|
Logger.Info(@"Configuring server to: [http://localhost:{0}]", Port);
|
||||||
|
|
||||||
|
var configXml = XDocument.Load(configPath);
|
||||||
|
|
||||||
|
var bindings =
|
||||||
|
configXml.XPathSelectElement("configuration/system.applicationHost/sites").Elements("site").Where(
|
||||||
|
d => d.Attribute("name").Value.ToLowerInvariant() == "nzbdrone").First().Element("bindings");
|
||||||
|
bindings.Descendants().Remove();
|
||||||
|
bindings.Add(
|
||||||
|
new XElement("binding",
|
||||||
|
new XAttribute("protocol", "http"),
|
||||||
|
new XAttribute("bindingInformation", String.Format("*:{0}:localhost", Port))
|
||||||
|
));
|
||||||
|
|
||||||
|
bindings.Add(
|
||||||
|
new XElement("binding",
|
||||||
|
new XAttribute("protocol", "http"),
|
||||||
|
new XAttribute("bindingInformation", String.Format("*:{0}:", Port))
|
||||||
|
));
|
||||||
|
|
||||||
|
configXml.Save(configPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void CreateDefaultConfigFile()
|
||||||
{
|
{
|
||||||
//Create the config file here
|
//Create the config file here
|
||||||
Directory.CreateDirectory(AppDataDirectory);
|
Directory.CreateDirectory(AppDataDirectory);
|
||||||
|
@ -69,7 +107,7 @@ namespace NzbDrone.Providers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal virtual void WriteDefaultConfig()
|
public virtual void WriteDefaultConfig()
|
||||||
{
|
{
|
||||||
var xDoc = new XDocument(new XDeclaration("1.0", "utf-8", "yes"));
|
var xDoc = new XDocument(new XDeclaration("1.0", "utf-8", "yes"));
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace NzbDrone.Providers
|
namespace NzbDrone.Providers
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,20 +1,17 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
|
||||||
namespace NzbDrone.Providers
|
namespace NzbDrone.Providers
|
||||||
{
|
{
|
||||||
internal class DebuggerProvider
|
public class DebuggerProvider
|
||||||
{
|
{
|
||||||
|
|
||||||
private static readonly Logger Logger = LogManager.GetLogger("DebuggerProvider");
|
private static readonly Logger Logger = LogManager.GetLogger("DebuggerProvider");
|
||||||
|
|
||||||
|
|
||||||
internal virtual void Attach()
|
public virtual void Attach()
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
if (Debugger.IsAttached)
|
if (Debugger.IsAttached)
|
||||||
|
|
|
@ -1,104 +1,79 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
|
||||||
using System.Runtime.Remoting;
|
|
||||||
using System.Timers;
|
|
||||||
using System.Xml.Linq;
|
|
||||||
using System.Xml.XPath;
|
|
||||||
using NLog;
|
using NLog;
|
||||||
|
using Ninject;
|
||||||
|
|
||||||
namespace NzbDrone.Providers
|
namespace NzbDrone.Providers
|
||||||
{
|
{
|
||||||
internal class IISProvider
|
public class IISProvider
|
||||||
{
|
{
|
||||||
private readonly ConfigProvider _configProvider;
|
private readonly ConfigProvider _configProvider;
|
||||||
|
private readonly ProcessProvider _processProvider;
|
||||||
private static readonly Logger IISLogger = LogManager.GetLogger("IISExpress");
|
private static readonly Logger IISLogger = LogManager.GetLogger("IISExpress");
|
||||||
private static readonly Logger Logger = LogManager.GetLogger("IISProvider");
|
private static readonly Logger Logger = LogManager.GetLogger("IISProvider");
|
||||||
|
|
||||||
private readonly string IISExe;
|
|
||||||
private readonly string IISConfigPath;
|
|
||||||
|
|
||||||
private static Timer _pingTimer;
|
[Inject]
|
||||||
private static int _pingFailCounter;
|
public IISProvider(ConfigProvider configProvider, ProcessProvider processProvider)
|
||||||
|
|
||||||
private static Process _iisProcess;
|
|
||||||
|
|
||||||
|
|
||||||
public IISProvider(ConfigProvider configProvider)
|
|
||||||
{
|
{
|
||||||
_configProvider = configProvider;
|
_configProvider = configProvider;
|
||||||
IISExe = Path.Combine(_configProvider.IISFolder, @"iisexpress.exe");
|
_processProvider = processProvider;
|
||||||
IISConfigPath = Path.Combine(_configProvider.IISFolder, "AppServer", "applicationhost.config");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal string AppUrl
|
public IISProvider()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public string AppUrl
|
||||||
{
|
{
|
||||||
get { return string.Format("http://localhost:{0}/", _configProvider.Port); }
|
get { return string.Format("http://localhost:{0}/", _configProvider.Port); }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal int IISProcessId
|
public int IISProcessId { get; private set; }
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_iisProcess == null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("IIS Process isn't running yet.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return _iisProcess.Id;
|
public bool ServerStarted { get; private set; }
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal Process StartServer()
|
public void StartServer()
|
||||||
{
|
{
|
||||||
Logger.Info("Preparing IISExpress Server...");
|
Logger.Info("Preparing IISExpress Server...");
|
||||||
_iisProcess = new Process();
|
|
||||||
|
|
||||||
_iisProcess.StartInfo.FileName = IISExe;
|
var startInfo = new ProcessStartInfo();
|
||||||
_iisProcess.StartInfo.Arguments = String.Format("/config:\"{0}\" /trace:i", IISConfigPath);//"/config:"""" /trace:i";
|
|
||||||
_iisProcess.StartInfo.WorkingDirectory = _configProvider.ApplicationRoot;
|
|
||||||
|
|
||||||
_iisProcess.StartInfo.UseShellExecute = false;
|
startInfo.FileName = _configProvider.IISExePath;
|
||||||
_iisProcess.StartInfo.RedirectStandardOutput = true;
|
startInfo.Arguments = String.Format("/config:\"{0}\" /trace:i", _configProvider.IISConfigPath);
|
||||||
_iisProcess.StartInfo.RedirectStandardError = true;
|
startInfo.WorkingDirectory = _configProvider.ApplicationRoot;
|
||||||
_iisProcess.StartInfo.CreateNoWindow = true;
|
|
||||||
|
|
||||||
|
startInfo.UseShellExecute = false;
|
||||||
_iisProcess.OutputDataReceived += (OnOutputDataReceived);
|
startInfo.RedirectStandardOutput = true;
|
||||||
_iisProcess.ErrorDataReceived += (OnErrorDataReceived);
|
startInfo.RedirectStandardError = true;
|
||||||
|
startInfo.CreateNoWindow = true;
|
||||||
|
|
||||||
//Set Variables for the config file.
|
//Set Variables for the config file.
|
||||||
_iisProcess.StartInfo.EnvironmentVariables.Add("NZBDRONE_PATH", _configProvider.ApplicationRoot);
|
startInfo.EnvironmentVariables.Add("NZBDRONE_PATH", _configProvider.ApplicationRoot);
|
||||||
_iisProcess.StartInfo.EnvironmentVariables.Add("NZBDRONE_PID", Process.GetCurrentProcess().Id.ToString());
|
startInfo.EnvironmentVariables.Add("NZBDRONE_PID", Process.GetCurrentProcess().Id.ToString());
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
UpdateIISConfig();
|
_configProvider.UpdateIISConfig(_configProvider.IISConfigPath);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Logger.ErrorException("An error has occurred while trying to update the config file.", e);
|
Logger.ErrorException("An error has occurred while trying to update the config file.", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var iisProcess = _processProvider.Start(startInfo);
|
||||||
|
IISProcessId = iisProcess.Id;
|
||||||
|
|
||||||
Logger.Info("Starting process. [{0}]", _iisProcess.StartInfo.FileName);
|
iisProcess.OutputDataReceived += (OnOutputDataReceived);
|
||||||
|
iisProcess.ErrorDataReceived += (OnErrorDataReceived);
|
||||||
|
|
||||||
|
iisProcess.BeginErrorReadLine();
|
||||||
|
iisProcess.BeginOutputReadLine();
|
||||||
|
|
||||||
|
ServerStarted = true;
|
||||||
_iisProcess.Start();
|
|
||||||
_iisProcess.PriorityClass = ProcessPriorityClass.AboveNormal;
|
|
||||||
|
|
||||||
_iisProcess.BeginErrorReadLine();
|
|
||||||
_iisProcess.BeginOutputReadLine();
|
|
||||||
|
|
||||||
//Start Ping
|
|
||||||
_pingTimer = new Timer(300000) { AutoReset = true };
|
|
||||||
_pingTimer.Elapsed += (PingServer);
|
|
||||||
_pingTimer.Start();
|
|
||||||
|
|
||||||
return _iisProcess;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void OnErrorDataReceived(object sender, DataReceivedEventArgs e)
|
private static void OnErrorDataReceived(object sender, DataReceivedEventArgs e)
|
||||||
|
@ -109,19 +84,18 @@ namespace NzbDrone.Providers
|
||||||
IISLogger.Error(e.Data);
|
IISLogger.Error(e.Data);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void StopServer()
|
public void StopServer()
|
||||||
{
|
{
|
||||||
KillProcess(_iisProcess);
|
_processProvider.Kill(IISProcessId);
|
||||||
|
|
||||||
Logger.Info("Finding orphaned IIS Processes.");
|
Logger.Info("Finding orphaned IIS Processes.");
|
||||||
foreach (var process in Process.GetProcessesByName("IISExpress"))
|
foreach (var process in _processProvider.GetProcessByName("IISExpress"))
|
||||||
{
|
{
|
||||||
string processPath = process.MainModule.FileName;
|
Logger.Info("[{0}]IIS Process found. Path:{1}", process.Id, process.StartPath);
|
||||||
Logger.Info("[{0}]IIS Process found. Path:{1}", process.Id, processPath);
|
if (NormalizePath(process.StartPath) == NormalizePath(_configProvider.IISExePath))
|
||||||
if (NormalizePath(processPath) == NormalizePath(IISExe))
|
|
||||||
{
|
{
|
||||||
Logger.Info("[{0}]Process is considered orphaned.", process.Id);
|
Logger.Info("[{0}]Process is considered orphaned.", process.Id);
|
||||||
KillProcess(process);
|
_processProvider.Kill(process.Id);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -130,41 +104,14 @@ namespace NzbDrone.Providers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RestartServer()
|
public void RestartServer()
|
||||||
{
|
{
|
||||||
_pingTimer.Stop();
|
ServerStarted = false;
|
||||||
Logger.Warn("Attempting to restart server.");
|
Logger.Warn("Attempting to restart server.");
|
||||||
StopServer();
|
StopServer();
|
||||||
StartServer();
|
StartServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PingServer(object sender, ElapsedEventArgs e)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var response = new WebClient().DownloadString(AppUrl + "/health");
|
|
||||||
|
|
||||||
if (!response.Contains("OK"))
|
|
||||||
{
|
|
||||||
throw new ServerException("Health services responded with an invalid response.");
|
|
||||||
}
|
|
||||||
if (_pingFailCounter > 0)
|
|
||||||
{
|
|
||||||
Logger.Info("Application pool has been successfully recovered.");
|
|
||||||
}
|
|
||||||
_pingFailCounter = 0;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_pingFailCounter++;
|
|
||||||
Logger.ErrorException("Application pool is not responding. Count " + _pingFailCounter, ex);
|
|
||||||
if (_pingFailCounter > 2)
|
|
||||||
{
|
|
||||||
RestartServer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnOutputDataReceived(object s, DataReceivedEventArgs e)
|
private void OnOutputDataReceived(object s, DataReceivedEventArgs e)
|
||||||
{
|
{
|
||||||
if (e == null || String.IsNullOrWhiteSpace(e.Data) || e.Data.StartsWith("Request started:") ||
|
if (e == null || String.IsNullOrWhiteSpace(e.Data) || e.Data.StartsWith("Request started:") ||
|
||||||
|
@ -180,47 +127,7 @@ namespace NzbDrone.Providers
|
||||||
IISLogger.Trace(e.Data);
|
IISLogger.Trace(e.Data);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateIISConfig()
|
private string NormalizePath(string path)
|
||||||
{
|
|
||||||
string configPath = Path.Combine(_configProvider.IISFolder, @"AppServer\applicationhost.config");
|
|
||||||
|
|
||||||
Logger.Info(@"Server configuration file: {0}", configPath);
|
|
||||||
Logger.Info(@"Configuring server to: [http://localhost:{0}]", _configProvider.Port);
|
|
||||||
|
|
||||||
var configXml = XDocument.Load(configPath);
|
|
||||||
|
|
||||||
var bindings =
|
|
||||||
configXml.XPathSelectElement("configuration/system.applicationHost/sites").Elements("site").Where(
|
|
||||||
d => d.Attribute("name").Value.ToLowerInvariant() == "nzbdrone").First().Element("bindings");
|
|
||||||
bindings.Descendants().Remove();
|
|
||||||
bindings.Add(
|
|
||||||
new XElement("binding",
|
|
||||||
new XAttribute("protocol", "http"),
|
|
||||||
new XAttribute("bindingInformation", String.Format("*:{0}:localhost", _configProvider.Port))
|
|
||||||
));
|
|
||||||
|
|
||||||
bindings.Add(
|
|
||||||
new XElement("binding",
|
|
||||||
new XAttribute("protocol", "http"),
|
|
||||||
new XAttribute("bindingInformation", String.Format("*:{0}:", _configProvider.Port))
|
|
||||||
));
|
|
||||||
|
|
||||||
configXml.Save(configPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void KillProcess(Process process)
|
|
||||||
{
|
|
||||||
if (process != null && !process.HasExited)
|
|
||||||
{
|
|
||||||
Logger.Info("[{0}]Killing process", process.Id);
|
|
||||||
process.Kill();
|
|
||||||
Logger.Info("[{0}]Waiting for exit", process.Id);
|
|
||||||
process.WaitForExit();
|
|
||||||
Logger.Info("[{0}]Process terminated successfully", process.Id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string NormalizePath(string path)
|
|
||||||
{
|
{
|
||||||
if (String.IsNullOrWhiteSpace(path))
|
if (String.IsNullOrWhiteSpace(path))
|
||||||
throw new ArgumentException("Path can not be null or empty");
|
throw new ArgumentException("Path can not be null or empty");
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Net;
|
||||||
|
using System.Runtime.Remoting;
|
||||||
|
using System.Timers;
|
||||||
|
using NLog;
|
||||||
|
using Ninject;
|
||||||
|
|
||||||
|
namespace NzbDrone.Providers
|
||||||
|
{
|
||||||
|
public class MonitoringProvider
|
||||||
|
{
|
||||||
|
private static readonly Logger Logger = LogManager.GetLogger("MonitoringProvider");
|
||||||
|
|
||||||
|
private readonly IISProvider _iisProvider;
|
||||||
|
private readonly ProcessProvider _processProvider;
|
||||||
|
|
||||||
|
private int _pingFailCounter;
|
||||||
|
private Timer _pingTimer;
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
public MonitoringProvider(ProcessProvider processProvider, IISProvider iisProvider)
|
||||||
|
{
|
||||||
|
_processProvider = processProvider;
|
||||||
|
_iisProvider = iisProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
AppDomain.CurrentDomain.UnhandledException += ((s, e) => AppDomainException(e));
|
||||||
|
|
||||||
|
AppDomain.CurrentDomain.ProcessExit += ProgramExited;
|
||||||
|
AppDomain.CurrentDomain.DomainUnload += ProgramExited;
|
||||||
|
|
||||||
|
var prioCheckTimer = new Timer(5000);
|
||||||
|
prioCheckTimer.Elapsed += EnsurePriority;
|
||||||
|
prioCheckTimer.Enabled = true;
|
||||||
|
|
||||||
|
_pingTimer = new Timer(60000) { AutoReset = true };
|
||||||
|
_pingTimer.Elapsed += (PingServer);
|
||||||
|
_pingTimer.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public MonitoringProvider()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public virtual void EnsurePriority(object sender, ElapsedEventArgs e)
|
||||||
|
{
|
||||||
|
var currentProcess = _processProvider.GetCurrentProcess();
|
||||||
|
if (currentProcess.Priority != ProcessPriorityClass.Normal)
|
||||||
|
{
|
||||||
|
_processProvider.SetPriority(currentProcess.Id, ProcessPriorityClass.Normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
var iisProcess = _processProvider.GetProcessById(_iisProvider.IISProcessId);
|
||||||
|
if (iisProcess != null && iisProcess.Priority != ProcessPriorityClass.Normal &&
|
||||||
|
iisProcess.Priority != ProcessPriorityClass.AboveNormal)
|
||||||
|
{
|
||||||
|
_processProvider.SetPriority(iisProcess.Id, ProcessPriorityClass.Normal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void PingServer(object sender, ElapsedEventArgs e)
|
||||||
|
{
|
||||||
|
if (!_iisProvider.ServerStarted) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string response = new WebClient().DownloadString(_iisProvider.AppUrl + "/health");
|
||||||
|
|
||||||
|
if (!response.Contains("OK"))
|
||||||
|
{
|
||||||
|
throw new ServerException("Health services responded with an invalid response.");
|
||||||
|
}
|
||||||
|
if (_pingFailCounter > 0)
|
||||||
|
{
|
||||||
|
Logger.Info("Application pool has been successfully recovered.");
|
||||||
|
}
|
||||||
|
_pingFailCounter = 0;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_pingFailCounter++;
|
||||||
|
Logger.ErrorException("Application pool is not responding. Count " + _pingFailCounter, ex);
|
||||||
|
if (_pingFailCounter > 2)
|
||||||
|
{
|
||||||
|
_iisProvider.RestartServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProgramExited(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
_iisProvider.StopServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void AppDomainException(object excepion)
|
||||||
|
{
|
||||||
|
Console.WriteLine("EPIC FAIL: {0}", excepion);
|
||||||
|
Logger.Fatal("EPIC FAIL: {0}", excepion);
|
||||||
|
|
||||||
|
#if RELEASE
|
||||||
|
new Client
|
||||||
|
{
|
||||||
|
ApiKey = "43BBF60A-EB2A-4C1C-B09E-422ADF637265",
|
||||||
|
ApplicationName = "NZBDrone",
|
||||||
|
CurrentException = excepion as Exception
|
||||||
|
}.Submit();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,6 @@
|
||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using NLog;
|
using NLog;
|
||||||
|
|
||||||
namespace NzbDrone.Providers
|
namespace NzbDrone.Providers
|
||||||
|
@ -12,6 +10,55 @@ namespace NzbDrone.Providers
|
||||||
private static readonly Logger Logger = LogManager.GetLogger("ProcessProvider");
|
private static readonly Logger Logger = LogManager.GetLogger("ProcessProvider");
|
||||||
|
|
||||||
|
|
||||||
|
public virtual ProcessInfo GetCurrentProcess()
|
||||||
|
{
|
||||||
|
return ConvertToProcessInfo(Process.GetCurrentProcess());
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual ProcessInfo GetProcessById(int id)
|
||||||
|
{
|
||||||
|
return ConvertToProcessInfo(Process.GetProcesses().Where(p => p.Id == id).FirstOrDefault());
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual IEnumerable<ProcessInfo> GetProcessByName(string name)
|
||||||
|
{
|
||||||
|
return Process.GetProcessesByName(name).Select(ConvertToProcessInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Start(string path)
|
||||||
|
{
|
||||||
|
Process.Start(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual Process Start(ProcessStartInfo startInfo)
|
||||||
|
{
|
||||||
|
Logger.Info("Starting process. [{0}]", startInfo.FileName);
|
||||||
|
|
||||||
|
var process = new Process
|
||||||
|
{
|
||||||
|
StartInfo = startInfo
|
||||||
|
};
|
||||||
|
process.Start();
|
||||||
|
return process;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Kill(int processId)
|
||||||
|
{
|
||||||
|
if (processId == 0) return;
|
||||||
|
if (!Process.GetProcesses().Any(p => p.Id == processId)) return;
|
||||||
|
|
||||||
|
var process = Process.GetProcessById(processId);
|
||||||
|
|
||||||
|
if (!process.HasExited)
|
||||||
|
{
|
||||||
|
Logger.Info("[{0}]Killing process", process.Id);
|
||||||
|
process.Kill();
|
||||||
|
Logger.Info("[{0}]Waiting for exit", process.Id);
|
||||||
|
process.WaitForExit();
|
||||||
|
Logger.Info("[{0}]Process terminated successfully", process.Id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public virtual void SetPriority(int processId, ProcessPriorityClass priority)
|
public virtual void SetPriority(int processId, ProcessPriorityClass priority)
|
||||||
{
|
{
|
||||||
var process = Process.GetProcessById(processId);
|
var process = Process.GetProcessById(processId);
|
||||||
|
@ -24,19 +71,16 @@ namespace NzbDrone.Providers
|
||||||
process.PriorityClass = priority;
|
process.PriorityClass = priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual ProcessPriorityClass GetProcessPriority(int processId)
|
private static ProcessInfo ConvertToProcessInfo(Process process)
|
||||||
{
|
{
|
||||||
return Process.GetProcessById(processId).PriorityClass;
|
if (process == null) return null;
|
||||||
}
|
|
||||||
|
|
||||||
public virtual int GetCurrentProcessId()
|
return new ProcessInfo
|
||||||
{
|
{
|
||||||
return Process.GetCurrentProcess().Id;
|
Id = process.Id,
|
||||||
}
|
Priority = process.PriorityClass,
|
||||||
|
StartPath = process.MainModule.FileName
|
||||||
public virtual Process Start(string path)
|
};
|
||||||
{
|
|
||||||
return Process.Start(path);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ using System.Text;
|
||||||
|
|
||||||
namespace NzbDrone.Providers
|
namespace NzbDrone.Providers
|
||||||
{
|
{
|
||||||
internal class WebClientProvider
|
public class WebClientProvider
|
||||||
{
|
{
|
||||||
|
|
||||||
public virtual string DownloadString(string url)
|
public virtual string DownloadString(string url)
|
||||||
|
|
Binary file not shown.
Binary file not shown.
BIN
packages/NBuilder.3.0.1/lib/Silverlight 3.0/FizzWare.NBuilder-Silverlight.dll
vendored
Normal file
BIN
packages/NBuilder.3.0.1/lib/Silverlight 3.0/FizzWare.NBuilder-Silverlight.dll
vendored
Normal file
Binary file not shown.
Loading…
Reference in New Issue