AB3986 - Wrapped System.Web.Hosting.IRegisteredObject in the AspNetHostingEnvironment. Updated Maindom to use our own new interface and the wrapper and moved to infrastructure. Removed the Umbraco.Core project now that it was empty.

This commit is contained in:
Bjarke Berg
2020-01-08 09:01:58 +01:00
parent cdfd3df98a
commit c7f60d8312
21 changed files with 137 additions and 271 deletions

View File

@@ -23,5 +23,8 @@ namespace Umbraco.Core.Hosting
/// Terminates the current application. The application restarts the next time a request is received for it.
/// </summary>
void LazyRestartApplication();
void RegisterObject(IRegisteredObject registeredObject);
void UnregisterObject(IRegisteredObject registeredObject);
}
}

View File

@@ -0,0 +1,7 @@
namespace Umbraco.Core
{
public interface IRegisteredObject
{
void Stop(bool immediate);
}
}

View File

@@ -1,40 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("Umbraco.Core")]
[assembly: AssemblyDescription("Umbraco Core")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyProduct("Umbraco CMS")]
[assembly: ComVisible(false)]
[assembly: Guid("130a6b5c-50e7-4df3-a0dd-e9e7eb0b7c5c")]
// Umbraco Cms
[assembly: InternalsVisibleTo("Umbraco.Web")]
[assembly: InternalsVisibleTo("Umbraco.Web.UI")]
[assembly: InternalsVisibleTo("Umbraco.Examine")]
[assembly: InternalsVisibleTo("Umbraco.ModelsBuilder.Embedded")]
[assembly: InternalsVisibleTo("Umbraco.Tests")]
[assembly: InternalsVisibleTo("Umbraco.Tests.Benchmarks")]
// Allow this to be mocked in our unit tests
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
// Umbraco Deploy
[assembly: InternalsVisibleTo("Umbraco.Deploy")]
[assembly: InternalsVisibleTo("Umbraco.Deploy.UI")]
[assembly: InternalsVisibleTo("Umbraco.Deploy.Cloud")]
// Umbraco Forms
[assembly: InternalsVisibleTo("Umbraco.Forms.Core")]
[assembly: InternalsVisibleTo("Umbraco.Forms.Core.Providers")]
[assembly: InternalsVisibleTo("Umbraco.Forms.Web")]
// Umbraco Headless
[assembly: InternalsVisibleTo("Umbraco.Cloud.Headless")]
// code analysis
// IDE1006 is broken, wants _value syntax for consts, etc - and it's even confusing ppl at MS, kill it
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "~_~")]

View File

@@ -1,145 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<ProjectGuid>{31785BC3-256C-4613-B2F5-A1B0BDDED8C1}</ProjectGuid>
<OutputType>Library</OutputType>
<AssemblyName>Umbraco.Core</AssemblyName>
<RootNamespace>Umbraco.Core</RootNamespace>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<TargetFrameworkProfile />
<AdditionalFileItemNames>$(AdditionalFileItemNames);Content</AdditionalFileItemNames>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>portable</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>portable</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Release\Umbraco.Core.xml</DocumentationFile>
<Prefer32Bit>false</Prefer32Bit>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Data.Entity" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.IO.Compression.FileSystem" />
<Reference Include="System.Runtime.Caching" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Transactions" />
<Reference Include="System.Web" />
<Reference Include="System.Web.ApplicationServices" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<!-- note: NuGet deals with transitive references now -->
<PackageReference Include="Microsoft.SourceLink.GitHub">
<Version>1.0.0-beta2-19324-01</Version>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="SecurityCodeScan">
<Version>3.3.0</Version>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Serilog.Sinks.Async">
<Version>1.4.0</Version>
</PackageReference>
<PackageReference Include="Serilog.Sinks.Map">
<Version>1.0.0</Version>
</PackageReference>
<PackageReference Include="System.ComponentModel.Annotations">
<Version>4.6.0</Version>
</PackageReference>
<PackageReference Include="Umbraco.Code">
<Version>1.0.5</Version>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="LightInject" Version="5.4.0" />
<PackageReference Include="LightInject.Annotation" Version="1.1.0" />
<PackageReference Include="LightInject.Web" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNet.Identity.Core">
<Version>2.2.2</Version>
</PackageReference>
<PackageReference Include="Microsoft.AspNet.WebApi.Client">
<Version>5.2.7</Version>
</PackageReference>
<PackageReference Include="Microsoft.Owin">
<Version>4.0.1</Version>
</PackageReference>
<PackageReference Include="MiniProfiler" Version="4.0.138" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
<PackageReference Include="NPoco" Version="4.0.2" />
<PackageReference Include="Serilog">
<Version>2.9.0</Version>
</PackageReference>
<PackageReference Include="Serilog.Enrichers.Process">
<Version>2.0.1</Version>
</PackageReference>
<PackageReference Include="Serilog.Enrichers.Thread">
<Version>3.1.0</Version>
</PackageReference>
<PackageReference Include="Serilog.Filters.Expressions">
<Version>2.0.0</Version>
</PackageReference>
<PackageReference Include="Serilog.Formatting.Compact">
<Version>1.1.0</Version>
</PackageReference>
<PackageReference Include="Serilog.Formatting.Compact.Reader">
<Version>1.0.3</Version>
</PackageReference>
<PackageReference Include="Serilog.Settings.AppSettings">
<Version>2.2.2</Version>
</PackageReference>
<PackageReference Include="Serilog.Sinks.File">
<Version>4.1.0</Version>
</PackageReference>
</ItemGroup>
<ItemGroup>
<!--
this does not fully work - breaks intellisense
Exclude="Constants-*.cs"
<Compile Include="Constants-*.cs">
<DependentUpon>Constants.cs</DependentUpon>
</Compile>
-->
<Compile Include="MainDom.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="..\SolutionInfo.cs">
<Link>Properties\SolutionInfo.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Umbraco.Abstractions\Umbraco.Abstractions.csproj">
<Project>{29aa69d9-b597-4395-8d42-43b1263c240a}</Project>
<Name>Umbraco.Abstractions</Name>
</ProjectReference>
<ProjectReference Include="..\Umbraco.Infrastructure\Umbraco.Infrastructure.csproj">
<Project>{3ae7bf57-966b-45a5-910a-954d7c554441}</Project>
<Name>Umbraco.Infrastructure</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -110,10 +110,6 @@
<Project>{29aa69d9-b597-4395-8d42-43b1263c240a}</Project>
<Name>Umbraco.Abstractions</Name>
</ProjectReference>
<ProjectReference Include="..\Umbraco.Core\Umbraco.Core.csproj">
<Project>{31785bc3-256c-4613-b2f5-a1b0bdded8c1}</Project>
<Name>Umbraco.Core</Name>
</ProjectReference>
<ProjectReference Include="..\Umbraco.Infrastructure\Umbraco.Infrastructure.csproj">
<Project>{3ae7bf57-966b-45a5-910a-954d7c554441}</Project>
<Name>Umbraco.Infrastructure</Name>

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Threading;
using System.Web.Hosting;
using Umbraco.Core.Hosting;
using Umbraco.Core.Logging;
@@ -16,11 +15,12 @@ namespace Umbraco.Core
/// <para>When an AppDomain starts, it tries to acquire the main domain status.</para>
/// <para>When an AppDomain stops (eg the application is restarting) it should release the main domain status.</para>
/// </remarks>
internal class MainDom : IMainDom, IRegisteredObject, IDisposable
public class MainDom : IMainDom, IRegisteredObject, IDisposable
{
#region Vars
private readonly ILogger _logger;
private readonly IHostingEnvironment _hostingEnvironment;
// our own lock for local consistency
private object _locko = new object();
@@ -50,9 +50,11 @@ namespace Umbraco.Core
// initializes a new instance of MainDom
public MainDom(ILogger logger, IHostingEnvironment hostingEnvironment)
{
HostingEnvironment.RegisterObject(this);
hostingEnvironment.RegisterObject(this);
_logger = logger;
_hostingEnvironment = hostingEnvironment;
// HostingEnvironment.ApplicationID is null in unit tests, making ReplaceNonAlphanumericChars fail
var appId = hostingEnvironment.ApplicationId?.ReplaceNonAlphanumericChars(string.Empty);
@@ -216,7 +218,7 @@ namespace Umbraco.Core
// The web app is stopping, need to wind down
Dispose(true);
HostingEnvironment.UnregisterObject(this);
_hostingEnvironment.UnregisterObject(this);
}
#region IDisposable Support

View File

@@ -10,9 +10,9 @@ using System.Text.RegularExpressions;
using System.Threading;
using System.Web;
using System.Web.Compilation;
using System.Web.Hosting;
using System.Web.WebPages.Razor;
using Umbraco.Core;
using Umbraco.Core.Hosting;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.ModelsBuilder.Embedded.Building;
@@ -41,20 +41,22 @@ namespace Umbraco.ModelsBuilder.Embedded
private static readonly string[] OurFiles = { "models.hash", "models.generated.cs", "all.generated.cs", "all.dll.path", "models.err" };
private readonly IModelsBuilderConfig _config;
private readonly IHostingEnvironment _hostingEnvironment;
private readonly ModelsGenerationError _errors;
public PureLiveModelFactory(Lazy<UmbracoServices> umbracoServices, IProfilingLogger logger, IModelsBuilderConfig config)
public PureLiveModelFactory(Lazy<UmbracoServices> umbracoServices, IProfilingLogger logger, IModelsBuilderConfig config, IHostingEnvironment hostingEnvironment)
{
_umbracoServices = umbracoServices;
_logger = logger;
_config = config;
_hostingEnvironment = hostingEnvironment;
_errors = new ModelsGenerationError(config);
_ver = 1; // zero is for when we had no version
_skipver = -1; // nothing to skip
RazorBuildProvider.CodeGenerationStarted += RazorBuildProvider_CodeGenerationStarted;
if (!HostingEnvironment.IsHosted) return;
if (!_hostingEnvironment.IsHosted) return;
var modelsDirectory = _config.ModelsDirectory;
if (!Directory.Exists(modelsDirectory))
@@ -63,7 +65,7 @@ namespace Umbraco.ModelsBuilder.Embedded
// BEWARE! if the watcher is not properly released then for some reason the
// BuildManager will start confusing types - using a 'registered object' here
// though we should probably plug into Umbraco's MainDom - which is internal
HostingEnvironment.RegisterObject(this);
_hostingEnvironment.RegisterObject(this);
_watcher = new FileSystemWatcher(modelsDirectory);
_watcher.Changed += WatcherOnChanged;
_watcher.EnableRaisingEvents = true;
@@ -667,7 +669,7 @@ namespace Umbraco.ModelsBuilder.Embedded
{
_watcher.EnableRaisingEvents = false;
_watcher.Dispose();
HostingEnvironment.UnregisterObject(this);
_hostingEnvironment.UnregisterObject(this);
}
#endregion

View File

@@ -105,10 +105,6 @@
<Project>{29aa69d9-b597-4395-8d42-43b1263c240a}</Project>
<Name>Umbraco.Abstractions</Name>
</ProjectReference>
<ProjectReference Include="..\Umbraco.Core\Umbraco.Core.csproj">
<Project>{31785BC3-256C-4613-B2F5-A1B0BDDED8C1}</Project>
<Name>Umbraco.Core</Name>
</ProjectReference>
<ProjectReference Include="..\Umbraco.Infrastructure\Umbraco.Infrastructure.csproj">
<Project>{3ae7bf57-966b-45a5-910a-954d7c554441}</Project>
<Name>Umbraco.Infrastructure</Name>

View File

@@ -148,7 +148,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
LongRunning = true,
KeepAlive = true,
Hosted = false // main domain will take care of stopping the runner (see below)
}, logger);
}, logger, _hostingEnvironment);
// create (and add to runner)
_persisterTask = new XmlStoreFilePersister(runner, this, logger);

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Web.Hosting;
using Examine;
using Moq;
using NUnit.Framework;

View File

@@ -6,6 +6,7 @@ using System.Threading;
using System.Threading.Tasks;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Hosting;
using Umbraco.Core.Logging;
using Umbraco.Tests.TestHelpers;
using Umbraco.Web.Scheduling;
@@ -18,17 +19,19 @@ namespace Umbraco.Tests.Scheduling
public class BackgroundTaskRunnerTests
{
private ILogger _logger;
private IHostingEnvironment _hostingEnvironment;
[OneTimeSetUp]
public void InitializeFixture()
{
_logger = new ConsoleLogger(new MessageTemplates());
_hostingEnvironment = TestHelper.GetHostingEnvironment();
}
[Test]
public async Task ShutdownWhenRunningWithWait()
{
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger))
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger, _hostingEnvironment))
{
var stopped = false;
runner.Stopped += (sender, args) => { stopped = true; };
@@ -51,7 +54,7 @@ namespace Umbraco.Tests.Scheduling
[Test]
public async Task ShutdownWhenRunningWithoutWait()
{
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger))
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger, _hostingEnvironment))
{
var stopped = false;
runner.Stopped += (sender, args) => { stopped = true; };
@@ -78,7 +81,7 @@ namespace Umbraco.Tests.Scheduling
[Test]
public async Task ShutdownCompletesTheRunner()
{
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger))
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger, _hostingEnvironment))
{
Assert.IsFalse(runner.IsRunning); // because AutoStart is false
@@ -101,7 +104,7 @@ namespace Umbraco.Tests.Scheduling
[Test]
public async Task ShutdownFlushesTheQueue()
{
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger))
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger, _hostingEnvironment))
{
MyTask t1, t2, t3;
@@ -123,7 +126,7 @@ namespace Umbraco.Tests.Scheduling
[Test]
public async Task ShutdownForceTruncatesTheQueue()
{
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger))
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger, _hostingEnvironment))
{
MyTask t1, t2, t3;
@@ -150,7 +153,7 @@ namespace Umbraco.Tests.Scheduling
[Test]
public async Task ShutdownThenForce()
{
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger))
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger, _hostingEnvironment))
{
Assert.IsFalse(runner.IsRunning); // because AutoStart is false
@@ -185,7 +188,7 @@ namespace Umbraco.Tests.Scheduling
[Test]
public async Task HostingStopNonImmediate()
{
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger))
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger, _hostingEnvironment))
{
MyTask t;
@@ -219,7 +222,7 @@ namespace Umbraco.Tests.Scheduling
[Test]
public async Task HostingStopImmediate()
{
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger))
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger, _hostingEnvironment))
{
MyTask t;
@@ -254,7 +257,7 @@ namespace Umbraco.Tests.Scheduling
[Test]
public void Create_IsNotRunning()
{
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger))
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger, _hostingEnvironment))
{
Assert.IsFalse(runner.IsRunning);
}
@@ -268,7 +271,7 @@ namespace Umbraco.Tests.Scheduling
{
AutoStart = true,
KeepAlive = true // else stops!
}, _logger))
}, _logger, _hostingEnvironment))
{
Assert.IsTrue(runner.IsRunning); // because AutoStart is true
await runner.StopInternal(false); // keepalive = must be stopped
@@ -278,7 +281,7 @@ namespace Umbraco.Tests.Scheduling
[Test]
public void Create_AutoStartAndKeepAlive_IsRunning()
{
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions { AutoStart = true, KeepAlive = true }, _logger))
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions { AutoStart = true, KeepAlive = true }, _logger, _hostingEnvironment))
{
Assert.IsTrue(runner.IsRunning); // because AutoStart is true
Thread.Sleep(800); // for long
@@ -291,7 +294,7 @@ namespace Umbraco.Tests.Scheduling
public async Task Dispose_IsRunning()
{
BackgroundTaskRunner<IBackgroundTask> runner;
using (runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions { AutoStart = true, KeepAlive = true }, _logger))
using (runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions { AutoStart = true, KeepAlive = true }, _logger, _hostingEnvironment))
{
Assert.IsTrue(runner.IsRunning);
// dispose will stop it
@@ -315,7 +318,7 @@ namespace Umbraco.Tests.Scheduling
[Test]
public void Startup_KeepAlive_IsRunning()
{
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions { KeepAlive = true }, _logger))
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions { KeepAlive = true }, _logger, _hostingEnvironment))
{
Assert.IsFalse(runner.IsRunning);
runner.StartUp();
@@ -327,7 +330,7 @@ namespace Umbraco.Tests.Scheduling
[Test]
public async Task Create_AddTask_IsRunning()
{
using (var runner = new BackgroundTaskRunner<BaseTask>(new BackgroundTaskRunnerOptions(), _logger))
using (var runner = new BackgroundTaskRunner<BaseTask>(new BackgroundTaskRunnerOptions(), _logger, _hostingEnvironment))
{
var waitHandle = new ManualResetEvent(false);
runner.TaskCompleted += (sender, args) =>
@@ -345,7 +348,7 @@ namespace Umbraco.Tests.Scheduling
[Test]
public void Create_KeepAliveAndAddTask_IsRunning()
{
using (var runner = new BackgroundTaskRunner<BaseTask>(new BackgroundTaskRunnerOptions { KeepAlive = true }, _logger))
using (var runner = new BackgroundTaskRunner<BaseTask>(new BackgroundTaskRunnerOptions { KeepAlive = true }, _logger, _hostingEnvironment))
{
var waitHandle = new ManualResetEvent(false);
runner.TaskCompleted += (sender, args) =>
@@ -363,7 +366,7 @@ namespace Umbraco.Tests.Scheduling
[Test]
public async Task WaitOnRunner_OneTask()
{
using (var runner = new BackgroundTaskRunner<BaseTask>(new BackgroundTaskRunnerOptions(), _logger))
using (var runner = new BackgroundTaskRunner<BaseTask>(new BackgroundTaskRunnerOptions(), _logger, _hostingEnvironment))
{
var task = new MyTask();
Assert.IsTrue(task.Ended == default(DateTime));
@@ -382,7 +385,7 @@ namespace Umbraco.Tests.Scheduling
for (var i = 0; i < 10; i++)
tasks.Add(new MyTask());
using (var runner = new BackgroundTaskRunner<BaseTask>(new BackgroundTaskRunnerOptions { KeepAlive = false, LongRunning = true, PreserveRunningTask = true }, _logger))
using (var runner = new BackgroundTaskRunner<BaseTask>(new BackgroundTaskRunnerOptions { KeepAlive = false, LongRunning = true, PreserveRunningTask = true }, _logger, _hostingEnvironment))
{
tasks.ForEach(runner.Add);
@@ -400,7 +403,7 @@ namespace Umbraco.Tests.Scheduling
[Test]
public async Task WaitOnTask()
{
using (var runner = new BackgroundTaskRunner<BaseTask>(new BackgroundTaskRunnerOptions(), _logger))
using (var runner = new BackgroundTaskRunner<BaseTask>(new BackgroundTaskRunnerOptions(), _logger, _hostingEnvironment))
{
var task = new MyTask();
var waitHandle = new ManualResetEvent(false);
@@ -420,7 +423,7 @@ namespace Umbraco.Tests.Scheduling
for (var i = 0; i < 10; i++)
tasks.Add(new MyTask(), new ManualResetEvent(false));
using (var runner = new BackgroundTaskRunner<BaseTask>(new BackgroundTaskRunnerOptions(), _logger))
using (var runner = new BackgroundTaskRunner<BaseTask>(new BackgroundTaskRunnerOptions(), _logger, _hostingEnvironment))
{
runner.TaskCompleted += (sender, task) => tasks[task.Task].Set();
foreach (var t in tasks) runner.Add(t.Key);
@@ -449,7 +452,7 @@ namespace Umbraco.Tests.Scheduling
IDictionary<BaseTask, ManualResetEvent> tasks = getTasks();
BackgroundTaskRunner<BaseTask> tManager;
using (tManager = new BackgroundTaskRunner<BaseTask>(new BackgroundTaskRunnerOptions { LongRunning = true, KeepAlive = true }, _logger))
using (tManager = new BackgroundTaskRunner<BaseTask>(new BackgroundTaskRunnerOptions { LongRunning = true, KeepAlive = true }, _logger, _hostingEnvironment))
{
tManager.TaskCompleted += (sender, task) => tasks[task.Task].Set();
@@ -495,7 +498,7 @@ namespace Umbraco.Tests.Scheduling
List<BaseTask> tasks = getTasks();
using (var tManager = new BackgroundTaskRunner<BaseTask>(new BackgroundTaskRunnerOptions { LongRunning = true, PreserveRunningTask = true }, _logger))
using (var tManager = new BackgroundTaskRunner<BaseTask>(new BackgroundTaskRunnerOptions { LongRunning = true, PreserveRunningTask = true }, _logger, _hostingEnvironment))
{
tasks.ForEach(tManager.Add);
@@ -537,7 +540,7 @@ namespace Umbraco.Tests.Scheduling
{
var runCount = 0;
var waitHandle = new ManualResetEvent(false);
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger))
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger, _hostingEnvironment))
{
runner.TaskCompleted += (sender, args) =>
{
@@ -568,7 +571,7 @@ namespace Umbraco.Tests.Scheduling
[Test]
public async Task LatchedTaskRuns()
{
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger))
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger, _hostingEnvironment))
{
var task = new MyLatchedTask(200, false);
runner.Add(task);
@@ -588,7 +591,7 @@ namespace Umbraco.Tests.Scheduling
[Test]
public async Task LatchedTaskStops_Runs_On_Shutdown()
{
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger))
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger, _hostingEnvironment))
{
var task = new MyLatchedTask(200, true);
runner.Add(task);
@@ -608,7 +611,7 @@ namespace Umbraco.Tests.Scheduling
{
var runCount = 0;
var waitHandle = new ManualResetEvent(false);
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger))
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger, _hostingEnvironment))
{
runner.TaskCompleted += (sender, args) =>
{
@@ -635,7 +638,7 @@ namespace Umbraco.Tests.Scheduling
[Test]
public async Task FailingTaskSync()
{
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger))
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger, _hostingEnvironment))
{
var exceptions = new ConcurrentQueue<Exception>();
runner.TaskError += (sender, args) => exceptions.Enqueue(args.Exception);
@@ -652,7 +655,7 @@ namespace Umbraco.Tests.Scheduling
[Test]
public async Task FailingTaskDisposing()
{
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger))
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger, _hostingEnvironment))
{
var exceptions = new ConcurrentQueue<Exception>();
runner.TaskError += (sender, args) => exceptions.Enqueue(args.Exception);
@@ -669,7 +672,7 @@ namespace Umbraco.Tests.Scheduling
[Test]
public async Task FailingTaskAsync()
{
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger))
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger, _hostingEnvironment))
{
var exceptions = new ConcurrentQueue<Exception>();
runner.TaskError += (sender, args) => exceptions.Enqueue(args.Exception);
@@ -685,7 +688,7 @@ namespace Umbraco.Tests.Scheduling
[Test]
public async Task FailingTaskDisposingAsync()
{
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger))
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger, _hostingEnvironment))
{
var exceptions = new ConcurrentQueue<Exception>();
runner.TaskError += (sender, args) => exceptions.Enqueue(args.Exception);
@@ -702,7 +705,7 @@ namespace Umbraco.Tests.Scheduling
[Test]
public async Task CancelAsyncTask()
{
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger))
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger, _hostingEnvironment))
{
var task = new MyAsyncTask(4000);
runner.Add(task);
@@ -718,7 +721,7 @@ namespace Umbraco.Tests.Scheduling
[Test]
public async Task CancelLatchedTask()
{
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger))
using (var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions(), _logger, _hostingEnvironment))
{
var task = new MyLatchedTask(4000, false);
runner.Add(task);
@@ -931,7 +934,7 @@ namespace Umbraco.Tests.Scheduling
[Test]
public void SourceTaskTest()
{
var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions { KeepAlive = true, LongRunning = true }, _logger);
var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions { KeepAlive = true, LongRunning = true }, _logger, TestHelper.GetHostingEnvironment());
var task = new SourceTask();
runner.Add(task);

View File

@@ -22,7 +22,7 @@ namespace Umbraco.Tests.Scheduling
public async Task ThreadResumeIssue()
{
var logger = new DebugDiagnosticsLogger(new MessageTemplates());
var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions { KeepAlive = true, LongRunning = true }, logger);
var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions { KeepAlive = true, LongRunning = true }, logger, TestHelper.GetHostingEnvironment());
var work = new ThreadResumeIssueWorkItem();
runner.Add(work);
@@ -77,7 +77,7 @@ namespace Umbraco.Tests.Scheduling
public async Task DebuggerInterferenceIssue()
{
var logger = new DebugDiagnosticsLogger(new MessageTemplates());
var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions { KeepAlive = true, LongRunning = true }, logger);
var runner = new BackgroundTaskRunner<IBackgroundTask>(new BackgroundTaskRunnerOptions { KeepAlive = true, LongRunning = true }, logger, TestHelper.GetHostingEnvironment());
var taskCompleted = false;
runner.TaskCompleted += (sender, args) =>
{

View File

@@ -354,7 +354,7 @@ namespace Umbraco.Tests.Testing
{
return new TypeLoader(ioHelper, typeFinder, runtimeCache, new DirectoryInfo(hostingEnvironment.LocalTempPath), logger, false, new[]
{
Assembly.Load("Umbraco.Core"),
Assembly.Load("Umbraco.Abstractions"),
Assembly.Load("Umbraco.Web"),
Assembly.Load("Umbraco.Tests"),
Assembly.Load("Umbraco.Infrastructure")

View File

@@ -17,7 +17,7 @@
<!-- Default JSON log file -->
<!-- This is used by the default log viewer in the Umbraco backoffice -->
<add key="serilog:using:File" value="Umbraco.Core" />
<add key="serilog:using:File" value="Umbraco.Infrastructure" />
<add key="serilog:write-to:File.formatter" value="Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact" />
<add key="serilog:write-to:File.path" value="%BASEDIR%\App_Data\Logs\UmbracoTraceLog.%MACHINENAME%..json" />
<add key="serilog:write-to:File.restrictedToMinimumLevel" value="Debug" />

View File

@@ -2,6 +2,7 @@
using System.Threading;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Hosting;
using Umbraco.Core.Logging;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Changes;
@@ -89,7 +90,7 @@ namespace Umbraco.Web.Compose
private IBackgroundTask[] _tasks;
private IndexRebuilder _indexRebuilder;
public DatabaseServerRegistrarAndMessengerComponent(IRuntimeState runtime, IServerRegistrar serverRegistrar, IServerMessenger serverMessenger, IServerRegistrationService registrationService, ILogger logger, IndexRebuilder indexRebuilder)
public DatabaseServerRegistrarAndMessengerComponent(IRuntimeState runtime, IServerRegistrar serverRegistrar, IServerMessenger serverMessenger, IServerRegistrationService registrationService, ILogger logger, IHostingEnvironment hostingEnvironment, IndexRebuilder indexRebuilder)
{
_runtime = runtime;
_logger = logger;
@@ -101,7 +102,7 @@ namespace Umbraco.Web.Compose
if (_registrar != null)
{
_touchTaskRunner = new BackgroundTaskRunner<IBackgroundTask>("ServerRegistration",
new BackgroundTaskRunnerOptions { AutoStart = true }, logger);
new BackgroundTaskRunnerOptions { AutoStart = true }, logger, hostingEnvironment);
}
// create task runner for BatchedDatabaseServerMessenger
@@ -109,7 +110,7 @@ namespace Umbraco.Web.Compose
if (_messenger != null)
{
_processTaskRunner = new BackgroundTaskRunner<IBackgroundTask>("ServerInstProcess",
new BackgroundTaskRunnerOptions { AutoStart = true }, logger);
new BackgroundTaskRunnerOptions { AutoStart = true }, logger, hostingEnvironment);
}
}

View File

@@ -1,10 +1,13 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Web;
using System.Web.Hosting;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Hosting;
using Umbraco.Core.IO;
using IRegisteredObject = Umbraco.Core.IRegisteredObject;
namespace Umbraco.Web.Hosting
{
@@ -44,6 +47,23 @@ namespace Umbraco.Web.Hosting
HttpRuntime.UnloadAppDomain();
}
private IDictionary<IRegisteredObject, RegisteredObjectWrapper> RegisteredObjects { get; } = new Dictionary<IRegisteredObject, RegisteredObjectWrapper>();
public void RegisterObject(IRegisteredObject registeredObject)
{
var wrapped = new RegisteredObjectWrapper(registeredObject);
RegisteredObjects.Add(registeredObject, wrapped);
HostingEnvironment.RegisterObject(wrapped);
}
public void UnregisterObject(IRegisteredObject registeredObject)
{
if (RegisteredObjects.TryGetValue(registeredObject, out var wrapped))
{
HostingEnvironment.UnregisterObject(wrapped);
}
}
public string LocalTempPath
{
@@ -82,6 +102,21 @@ namespace Umbraco.Web.Hosting
}
}
}
private class RegisteredObjectWrapper : System.Web.Hosting.IRegisteredObject
{
private readonly IRegisteredObject _inner;
public RegisteredObjectWrapper(IRegisteredObject inner)
{
_inner = inner;
}
public void Stop(bool immediate)
{
_inner.Stop(immediate);
}
}
}
}

View File

@@ -5,6 +5,7 @@ using System.Threading.Tasks.Dataflow;
using System.Web.Hosting;
using Umbraco.Core;
using Umbraco.Core.Events;
using Umbraco.Core.Hosting;
using Umbraco.Core.Logging;
namespace Umbraco.Web.Scheduling
@@ -81,6 +82,7 @@ namespace Umbraco.Web.Scheduling
private readonly string _logPrefix;
private readonly BackgroundTaskRunnerOptions _options;
private readonly ILogger _logger;
private readonly IHostingEnvironment _hostingEnvironment;
private readonly object _locker = new object();
private readonly BufferBlock<T> _tasks = new BufferBlock<T>(new DataflowBlockOptions());
@@ -102,9 +104,10 @@ namespace Umbraco.Web.Scheduling
/// Initializes a new instance of the <see cref="BackgroundTaskRunner{T}"/> class.
/// </summary>
/// <param name="logger">A logger.</param>
/// <param name="hostingEnvironment">The hosting environment</param>
/// <param name="hook">An optional main domain hook.</param>
public BackgroundTaskRunner(ILogger logger, MainDomHook hook = null)
: this(typeof(T).FullName, new BackgroundTaskRunnerOptions(), logger, hook)
public BackgroundTaskRunner(ILogger logger, IHostingEnvironment hostingEnvironment, MainDomHook hook = null)
: this(typeof(T).FullName, new BackgroundTaskRunnerOptions(), logger, hostingEnvironment, hook)
{ }
/// <summary>
@@ -112,9 +115,10 @@ namespace Umbraco.Web.Scheduling
/// </summary>
/// <param name="name">The name of the runner.</param>
/// <param name="logger">A logger.</param>
/// <param name="hostingEnvironment">The hosting environment</param>
/// <param name="hook">An optional main domain hook.</param>
public BackgroundTaskRunner(string name, ILogger logger, MainDomHook hook = null)
: this(name, new BackgroundTaskRunnerOptions(), logger, hook)
public BackgroundTaskRunner(string name, ILogger logger, IHostingEnvironment hostingEnvironment, MainDomHook hook = null)
: this(name, new BackgroundTaskRunnerOptions(), logger, hostingEnvironment, hook)
{ }
/// <summary>
@@ -122,9 +126,10 @@ namespace Umbraco.Web.Scheduling
/// </summary>
/// <param name="options">The set of options.</param>
/// <param name="logger">A logger.</param>
/// <param name="hostingEnvironment">The hosting environment</param>
/// <param name="hook">An optional main domain hook.</param>
public BackgroundTaskRunner(BackgroundTaskRunnerOptions options, ILogger logger, MainDomHook hook = null)
: this(typeof(T).FullName, options, logger, hook)
public BackgroundTaskRunner(BackgroundTaskRunnerOptions options, ILogger logger, IHostingEnvironment hostingEnvironment, MainDomHook hook = null)
: this(typeof(T).FullName, options, logger, hostingEnvironment, hook)
{ }
/// <summary>
@@ -133,15 +138,17 @@ namespace Umbraco.Web.Scheduling
/// <param name="name">The name of the runner.</param>
/// <param name="options">The set of options.</param>
/// <param name="logger">A logger.</param>
/// <param name="hostingEnvironment">The hosting environment</param>
/// <param name="hook">An optional main domain hook.</param>
public BackgroundTaskRunner(string name, BackgroundTaskRunnerOptions options, ILogger logger, MainDomHook hook = null)
public BackgroundTaskRunner(string name, BackgroundTaskRunnerOptions options, ILogger logger, IHostingEnvironment hostingEnvironment, MainDomHook hook = null)
{
_options = options ?? throw new ArgumentNullException(nameof(options));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_hostingEnvironment = hostingEnvironment;
_logPrefix = "[" + name + "] ";
if (options.Hosted)
HostingEnvironment.RegisterObject(this);
_hostingEnvironment.RegisterObject(this);
if (hook != null)
_completed = _terminated = hook.Register() == false;
@@ -212,7 +219,7 @@ namespace Umbraco.Web.Scheduling
/// <remarks>
/// <para>Used to wait until the runner has terminated.</para>
/// <para>
/// The only time the runner will be terminated is by the Hosting Environment when the application is being shutdown.
/// The only time the runner will be terminated is by the Hosting Environment when the application is being shutdown.
/// </para>
/// </remarks>
internal ThreadingTaskImmutable TerminatedAwaitable
@@ -350,14 +357,14 @@ namespace Umbraco.Web.Scheduling
if (force)
{
// we must bring everything down, now
// we must bring everything down, now
lock (_locker)
{
// was Complete() enough?
// if _tasks.Complete() ended up triggering code to stop the runner and reset
// the _isRunning flag, then there's no need to initiate a cancel on the cancelation token.
if (_isRunning == false)
return;
return;
}
// try to cancel running async tasks (cannot do much about sync tasks)
@@ -805,7 +812,7 @@ namespace Umbraco.Web.Scheduling
if (immediate)
{
//only unregister when it's the final call, else we won't be notified of the final call
HostingEnvironment.UnregisterObject(this);
_hostingEnvironment.UnregisterObject(this);
}
if (_terminated) return; // already taken care of

View File

@@ -1,5 +1,5 @@
using System;
using System.Web.Hosting;
using Umbraco.Core;
namespace Umbraco.Web.Scheduling
{

View File

@@ -6,6 +6,7 @@ using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration.HealthChecks;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Hosting;
using Umbraco.Core.Logging;
using Umbraco.Core.Scoping;
using Umbraco.Core.Services;
@@ -26,6 +27,7 @@ namespace Umbraco.Web.Scheduling
private readonly IContentService _contentService;
private readonly IAuditService _auditService;
private readonly IProfilingLogger _logger;
private readonly IHostingEnvironment _hostingEnvironment;
private readonly IScopeProvider _scopeProvider;
private readonly HealthCheckCollection _healthChecks;
private readonly HealthCheckNotificationMethodCollection _notifications;
@@ -45,13 +47,14 @@ namespace Umbraco.Web.Scheduling
public SchedulerComponent(IRuntimeState runtime,
IContentService contentService, IAuditService auditService,
HealthCheckCollection healthChecks, HealthCheckNotificationMethodCollection notifications,
IScopeProvider scopeProvider, IUmbracoContextFactory umbracoContextFactory, IProfilingLogger logger)
IScopeProvider scopeProvider, IUmbracoContextFactory umbracoContextFactory, IProfilingLogger logger, IHostingEnvironment hostingEnvironment)
{
_runtime = runtime;
_contentService = contentService;
_auditService = auditService;
_scopeProvider = scopeProvider;
_logger = logger;
_hostingEnvironment = hostingEnvironment;
_umbracoContextFactory = umbracoContextFactory;
_healthChecks = healthChecks;
@@ -61,12 +64,12 @@ namespace Umbraco.Web.Scheduling
public void Initialize()
{
// backgrounds runners are web aware, if the app domain dies, these tasks will wind down correctly
_keepAliveRunner = new BackgroundTaskRunner<IBackgroundTask>("KeepAlive", _logger);
_publishingRunner = new BackgroundTaskRunner<IBackgroundTask>("ScheduledPublishing", _logger);
_tasksRunner = new BackgroundTaskRunner<IBackgroundTask>("ScheduledTasks", _logger);
_scrubberRunner = new BackgroundTaskRunner<IBackgroundTask>("LogScrubber", _logger);
_fileCleanupRunner = new BackgroundTaskRunner<IBackgroundTask>("TempFileCleanup", _logger);
_healthCheckRunner = new BackgroundTaskRunner<IBackgroundTask>("HealthCheckNotifier", _logger);
_keepAliveRunner = new BackgroundTaskRunner<IBackgroundTask>("KeepAlive", _logger, _hostingEnvironment);
_publishingRunner = new BackgroundTaskRunner<IBackgroundTask>("ScheduledPublishing", _logger, _hostingEnvironment);
_tasksRunner = new BackgroundTaskRunner<IBackgroundTask>("ScheduledTasks", _logger, _hostingEnvironment);
_scrubberRunner = new BackgroundTaskRunner<IBackgroundTask>("LogScrubber", _logger, _hostingEnvironment);
_fileCleanupRunner = new BackgroundTaskRunner<IBackgroundTask>("TempFileCleanup", _logger, _hostingEnvironment);
_healthCheckRunner = new BackgroundTaskRunner<IBackgroundTask>("HealthCheckNotifier", _logger, _hostingEnvironment);
// we will start the whole process when a successful request is made
UmbracoModule.RouteAttempt += RegisterBackgroundTasksOnce;

View File

@@ -4,6 +4,7 @@ using Umbraco.Core.Logging;
using Umbraco.Examine;
using System.Threading.Tasks;
using Umbraco.Core;
using Umbraco.Core.Hosting;
using Umbraco.Web.Scheduling;
namespace Umbraco.Web.Search
@@ -17,12 +18,14 @@ namespace Umbraco.Web.Search
private readonly IndexRebuilder _indexRebuilder;
private readonly IMainDom _mainDom;
private readonly IProfilingLogger _logger;
private readonly IHostingEnvironment _hostingEnvironment;
private static BackgroundTaskRunner<IBackgroundTask> _rebuildOnStartupRunner;
public BackgroundIndexRebuilder(IMainDom mainDom, IProfilingLogger logger, IndexRebuilder indexRebuilder)
public BackgroundIndexRebuilder(IMainDom mainDom, IProfilingLogger logger, IHostingEnvironment hostingEnvironment, IndexRebuilder indexRebuilder)
{
_mainDom = mainDom;
_logger = logger;
_hostingEnvironment = hostingEnvironment;
_indexRebuilder = indexRebuilder;
}
@@ -51,7 +54,7 @@ namespace Umbraco.Web.Search
_rebuildOnStartupRunner = new BackgroundTaskRunner<IBackgroundTask>(
"RebuildIndexesOnStartup",
_logger);
_logger, _hostingEnvironment);
_rebuildOnStartupRunner.TryAdd(task);
}

View File

@@ -60,8 +60,6 @@ Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "Umbraco.Web.UI.Client", "ht
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Umbraco.Web", "Umbraco.Web\Umbraco.Web.csproj", "{651E1350-91B6-44B7-BD60-7207006D7003}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Umbraco.Core", "Umbraco.Core\Umbraco.Core.csproj", "{31785BC3-256C-4613-B2F5-A1B0BDDED8C1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Umbraco.Tests", "Umbraco.Tests\Umbraco.Tests.csproj", "{5D3B8245-ADA6-453F-A008-50ED04BFE770}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Umbraco.Examine", "Umbraco.Examine\Umbraco.Examine.csproj", "{07FBC26B-2927-4A22-8D96-D644C667FECC}"
@@ -128,10 +126,6 @@ Global
{651E1350-91B6-44B7-BD60-7207006D7003}.Debug|Any CPU.Build.0 = Debug|Any CPU
{651E1350-91B6-44B7-BD60-7207006D7003}.Release|Any CPU.ActiveCfg = Release|Any CPU
{651E1350-91B6-44B7-BD60-7207006D7003}.Release|Any CPU.Build.0 = Release|Any CPU
{31785BC3-256C-4613-B2F5-A1B0BDDED8C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{31785BC3-256C-4613-B2F5-A1B0BDDED8C1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{31785BC3-256C-4613-B2F5-A1B0BDDED8C1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{31785BC3-256C-4613-B2F5-A1B0BDDED8C1}.Release|Any CPU.Build.0 = Release|Any CPU
{5D3B8245-ADA6-453F-A008-50ED04BFE770}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5D3B8245-ADA6-453F-A008-50ED04BFE770}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5D3B8245-ADA6-453F-A008-50ED04BFE770}.Release|Any CPU.ActiveCfg = Release|Any CPU