48 changes: 48 additions & 0 deletions Loader/NuGetAssemblyLoader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using NuGet;

namespace Loader
{
public class NuGetAssemblyLoader : IAssemblyLoader
{
private readonly LocalPackageRepository _repository;

public NuGetAssemblyLoader(string packagesDirectory)
{
_repository = new LocalPackageRepository(packagesDirectory);
}

public Assembly Load(string name)
{
var package = _repository.FindPackage(name);

if (package == null)
{
return null;
}

var path = _repository.PathResolver.GetInstallPath(package);

// REVIEW: How do we get the project framework?

var framework = VersionUtility.ParseFrameworkName("net45");
IEnumerable<IPackageAssemblyReference> references;
if (VersionUtility.TryGetCompatibleItems(framework, package.AssemblyReferences, out references))
{
foreach (var reference in references)
{
string fileName = Path.Combine(path, reference.Path);
if (File.Exists(fileName))
{
return Assembly.LoadFile(fileName);
}
}
}

return null;
}
}
}
75 changes: 75 additions & 0 deletions Loader/ProjectSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using System.Collections.Generic;
using System.IO;
using System.Runtime.Versioning;
using Newtonsoft.Json.Linq;
using NuGet;

namespace Loader
{
public class ProjectSettings
{
public static bool TryGetSettings(string path, out ProjectSettings projectSettings)
{
projectSettings = null;

string projectSettingsPath = Path.Combine(path, "project.json");

if (!File.Exists(projectSettingsPath))
{
return false;
}

projectSettings = new ProjectSettings();

string json = File.ReadAllText(projectSettingsPath);
var settings = JObject.Parse(json);
var targetFramework = settings["targetFramework"];

string framework = targetFramework == null ? "net40" : targetFramework.Value<string>();

projectSettings.Name = settings["name"].Value<string>();
projectSettings.TargetFramework = VersionUtility.ParseFrameworkName(framework);
projectSettings.Dependencies = new List<Dependency>();

var dependencies = settings["dependencies"] as JArray;
if (dependencies != null)
{
foreach (JObject dependency in dependencies)
{
foreach (var prop in dependency)
{
var properties = prop.Value.Value<JObject>();

var version = properties["version"];

projectSettings.Dependencies.Add(new Dependency
{
Name = prop.Key,
Version = version != null ? version.Value<string>() : null
});
}
}
}

return true;
}

public string Name { get; private set; }

public FrameworkName TargetFramework { get; set; }

public IList<Dependency> Dependencies { get; private set; }
}

public class Dependency
{
public string Name { get; set; }

public string Version { get; set; }

public override string ToString()
{
return Name + " " + Version;
}
}
}
36 changes: 36 additions & 0 deletions Loader/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -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("Loader")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Loader")]
[assembly: AssemblyCopyright("Copyright © 2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("988ef0b2-8b93-4ef4-b90b-13a5fa0a11af")]

// 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")]
131 changes: 131 additions & 0 deletions Loader/RoslynLoader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Emit;

namespace Loader
{
public class RoslynLoader : IAssemblyLoader
{
private readonly Dictionary<string, CompiledAssembly> _compiledAssemblies = new Dictionary<string, CompiledAssembly>();
private readonly string _solutionPath;

public RoslynLoader(string solutionPath)
{
_solutionPath = solutionPath;
}

public Assembly Load(string name)
{
CompiledAssembly compiledAssembly;
if (_compiledAssemblies.TryGetValue(name, out compiledAssembly))
{
return compiledAssembly.Assembly;
}

string path = Path.Combine(_solutionPath, name);
ProjectSettings settings;

// Can't find a project file with the name so bail
if (!ProjectSettings.TryGetSettings(path, out settings))
{
return null;
}

// Get all the cs files in this directory
var sources = Directory.GetFiles(path, "*.cs", SearchOption.AllDirectories);

var trees = sources.Select(p => SyntaxTree.ParseFile(p))
.ToList();

var references = settings.Dependencies
.Select(d =>
{
// Load the assembly so we run the "system" but grab the bytes for those assemblies
// that are in memory
var loadedAssembly = Assembly.Load(d.Name);
CompiledAssembly compiledDependency;
if (_compiledAssemblies.TryGetValue(d.Name, out compiledDependency))
{
return compiledDependency.Reference;
}
return new MetadataFileReference(loadedAssembly.Location);
})
.Concat(GetFrameworkAssemblies())
.ToList();

string generatedAssemblyName = GetAssemblyName(path);

// Create a compilation
var compilation = Compilation.Create(
name,
new CompilationOptions(OutputKind.DynamicallyLinkedLibrary),
syntaxTrees: trees,
references: references);

using (var ms = new MemoryStream())
{
EmitResult result = compilation.Emit(ms);

if (!result.Success)
{
Trace.TraceError("COMPILATION ERROR: " +
Environment.NewLine +
String.Join(Environment.NewLine,
result.Diagnostics.Select(d => d.GetMessage())));

return null;
}

var bytes = ms.ToArray();

var assembly = Assembly.Load(bytes);

var compiled = new CompiledAssembly
{
Assembly = assembly,
Reference = new MetadataImageReference(bytes)
};

_compiledAssemblies[generatedAssemblyName] = compiled;
_compiledAssemblies[name] = compiled;

return assembly;
}
}

private string GetAssemblyName(string path)
{
return "COMPILED_" + Normalize(path);
}

private static string Normalize(string path)
{
return path.Replace(':', '_').Replace(Path.DirectorySeparatorChar, '_');
}

// The "framework" is always implicitly referenced
public IEnumerable<MetadataReference> GetFrameworkAssemblies()
{
yield return new MetadataFileReference(typeof(object).Assembly.Location);
yield return new MetadataFileReference(typeof(File).Assembly.Location);
yield return new MetadataFileReference(typeof(System.Linq.Enumerable).Assembly.Location);
yield return new MetadataFileReference(typeof(System.Dynamic.DynamicObject).Assembly.Location);
yield return new MetadataFileReference(typeof(Microsoft.CSharp.RuntimeBinder.RuntimeBinderException).Assembly.Location);
}

private class CompiledAssembly
{
public Assembly Assembly { get; set; }
public MetadataReference Reference { get; set; }
}
}

}
7 changes: 7 additions & 0 deletions Loader/packages.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Web.Xdt" version="1.0.0" targetFramework="net45" />
<package id="Mono.CSharp" version="3.0.6" targetFramework="net45" />
<package id="Newtonsoft.Json" version="5.0.8" targetFramework="net45" />
<package id="NuGet.Core" version="2.7.1" targetFramework="net45" />
</packages>
14 changes: 14 additions & 0 deletions OwinHost2/App.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
82 changes: 82 additions & 0 deletions OwinHost2/DomainHostingStarter2.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.

using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;

namespace Microsoft.Owin.Hosting.Starter
{
/// <summary>
/// Creates a new AppDomain to run the IHostingEngine in.
/// </summary>
public class DomainHostingStarter2 : IHostingStarter
{
/// <summary>
/// Creates a new AppDomain to run the IHostingEngine in.
/// </summary>
/// <param name="options"></param>
/// <returns></returns>
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Disposed by caller")]
public virtual IDisposable Start(StartOptions options)
{
if (options == null)
{
throw new ArgumentNullException("options");
}

string directory;

if (!options.Settings.TryGetValue("directory", out directory) || string.IsNullOrWhiteSpace(directory))
{
directory = Directory.GetCurrentDirectory();

// If there are no /bin/ subdirs, and the current directory is called /bin/, move the current directory up one.
// This fixes the case where a web app was run by katana.exe from the wrong directory.
var directoryInfo = new DirectoryInfo(directory);
if (directoryInfo.GetDirectories()
.Where(subDirInfo => subDirInfo.Name.Equals("bin", StringComparison.OrdinalIgnoreCase)).Count() == 0
&& directoryInfo.Name.Equals("bin", StringComparison.OrdinalIgnoreCase))
{
directory = directoryInfo.Parent.FullName;
}
}

var info = new AppDomainSetup
{
ApplicationBase = directory,
PrivateBinPath = "bin",
PrivateBinPathProbe = "*",
LoaderOptimization = LoaderOptimization.MultiDomainHost,
ConfigurationFile = Path.Combine(directory, "web.config")
};

AppDomain domain = AppDomain.CreateDomain("OWIN", null, info);

DomainHostingStarterAgent2 agent = CreateAgent(domain);

agent.ResolveAssembliesFromDirectory(AppDomain.CurrentDomain.SetupInformation.ApplicationBase);

agent.Start(options);

return agent;
}

[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Fallback code")]
private static DomainHostingStarterAgent2 CreateAgent(AppDomain domain)
{
try
{
return (DomainHostingStarterAgent2)domain.CreateInstanceAndUnwrap(
typeof(DomainHostingStarterAgent2).Assembly.FullName,
typeof(DomainHostingStarterAgent2).FullName);
}
catch
{
return (DomainHostingStarterAgent2)domain.CreateInstanceFromAndUnwrap(
typeof(DomainHostingStarterAgent2).Assembly.Location,
typeof(DomainHostingStarterAgent2).FullName);
}
}
}
}
210 changes: 210 additions & 0 deletions OwinHost2/DomainHostingStarterAgent2.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Reflection;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Lifetime;
using Loader;
using Microsoft.Owin.Hosting.Engine;
using Microsoft.Owin.Hosting.Loader;
using Microsoft.Owin.Hosting.Services;
using OwinHost2;

namespace Microsoft.Owin.Hosting.Starter
{
/// <summary>
/// Used for executing the IHostingEngine in a new AppDomain.
/// </summary>
public class DomainHostingStarterAgent2 : MarshalByRefObject, ISponsor, IDisposable
{
private ILease _lease;
private bool _disposed;
private IDisposable _runningApp;
private FileSystemWatcher _watcher;

/// <summary>
/// Registers a fallback assembly resolver that looks in the given directory.
/// </summary>
/// <param name="directory"></param>
[SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.Reflection.Assembly.LoadFile", Justification = "By design")]
[SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "Invoked cross domain")]
public virtual void ResolveAssembliesFromDirectory(string directory)
{
var cache = new Dictionary<string, Assembly>();
AppDomain.CurrentDomain.AssemblyResolve +=
(a, b) =>
{
Assembly assembly;
if (cache.TryGetValue(b.Name, out assembly))
{
return assembly;
}
string shortName = new AssemblyName(b.Name).Name;
string path = Path.Combine(directory, shortName + ".dll");
if (File.Exists(path))
{
assembly = Assembly.LoadFile(path);
}
cache[b.Name] = assembly;
if (assembly != null)
{
cache[assembly.FullName] = assembly;
}
return assembly;
};
}

/// <summary>
/// Executes the IHostingEngine in a new AppDomain.
/// </summary>
/// <param name="options"></param>
[SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "Non-static needed for calling across AppDomain")]
public virtual void Start(StartOptions options)
{
var context = new StartContext(options);

// Project directory
string path = options.Settings["directory"];

ProjectSettings settings;
if (!ProjectSettings.TryGetSettings(path, out settings))
{
Trace.TraceError("Unable to find packages.json");
return;
}

var loader = new AssemblyLoader();
string solutionDir = Path.GetDirectoryName(path);
string packagesDir = Path.Combine(solutionDir, "packages");

Suicide(solutionDir);

AppDomain.CurrentDomain.AssemblyResolve += (a, b) =>
{
string name = new AssemblyName(b.Name).Name;
return loader.Load(name);
};

loader.Add(new RoslynLoader(solutionDir));
loader.Add(new NuGetAssemblyLoader(packagesDir));
loader.Add(new MSBuildProjectAssemblyLoader(solutionDir));

IServiceProvider services = ServicesFactory.Create(context.Options.Settings, sp =>
{
sp.AddInstance<IAppLoader>(new MyAppLoader(settings.Name));
});

var engine = services.GetService<IHostingEngine>();

try
{
_runningApp = engine.Start(context);
}
catch (Exception ex)
{
Trace.TraceError(String.Join("\n", GetExceptions(ex)));
}

_lease = (ILease)RemotingServices.GetLifetimeService(this);
_lease.Register(this);
}

private IEnumerable<string> GetExceptions(Exception ex)
{
if (ex.InnerException != null)
{
foreach (var e in GetExceptions(ex.InnerException))
{
yield return e;
}
}

yield return ex.Message;
}

private void Suicide(string solutionDir)
{
_watcher = new FileSystemWatcher(solutionDir);
_watcher.EnableRaisingEvents = true;
_watcher.IncludeSubdirectories = true;

_watcher.Changed += OnWatcherChanged;
}

void OnWatcherChanged(object sender, FileSystemEventArgs e)
{
var extension = Path.GetExtension(e.FullPath).ToLowerInvariant();

Trace.TraceInformation("Change detected in {0}", e.Name);

if (extension == ".pdb" ||
extension == ".dll" ||
extension == ".cshtml" ||
extension == ".cache" ||
IsUnder(e.FullPath, ".git") ||
IsUnder(e.FullPath, "bin"))
{
return;
}

Environment.Exit(250);
}

private bool IsUnder(string path, string folder)
{
// Not good enough
var index = path.IndexOf(folder, StringComparison.OrdinalIgnoreCase);

if (index >= 0)
{
return true;
}

return false;
}

/// <summary>
///
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

/// <summary>
///
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
if (disposing && !_disposed)
{
_disposed = true;
_lease.Unregister(this);
_runningApp.Dispose();
}
}

/// <summary>
/// Renews the given lease for 5 minutes.
/// </summary>
/// <param name="lease"></param>
/// <returns></returns>
public virtual TimeSpan Renewal(ILease lease)
{
if (_disposed)
{
return TimeSpan.Zero;
}

return TimeSpan.FromMinutes(5);
}
}
}
34 changes: 34 additions & 0 deletions OwinHost2/MyAppLoader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.Owin.Hosting.Loader;
using Owin;

namespace OwinHost2
{
public class MyAppLoader : IAppLoader
{
private string _assemblyName;

public MyAppLoader(string assemblyName)
{
_assemblyName = assemblyName;
}

public Action<IAppBuilder> Load(string appName, IList<string> errors)
{
var asm = Assembly.Load(_assemblyName);
var type = asm.GetType("Startup") ?? asm.GetTypes().FirstOrDefault(t => t.Name == "Startup");
var config = type.GetMethod("Configuration");
var obj = Activator.CreateInstance(type);

return app =>
{
app.Properties["host.AppName"] = _assemblyName;
config.Invoke(obj, new[] { app });
};
}
}
}
79 changes: 79 additions & 0 deletions OwinHost2/OwinHost2.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{9218547E-DEA4-42B1-8869-94B2C4865C61}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>OwinHost2</RootNamespace>
<AssemblyName>OwinHost2</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</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|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Owin.2.1.0-rc1-21106-691-dev\lib\net45\Microsoft.Owin.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Owin.Host.HttpListener, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Owin.Host.HttpListener.2.1.0-rc1-21106-691-dev\lib\net45\Microsoft.Owin.Host.HttpListener.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Owin.Hosting, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Owin.Hosting.2.1.0-rc1-21106-691-dev\lib\net45\Microsoft.Owin.Hosting.dll</HintPath>
</Reference>
<Reference Include="Owin">
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
<ItemGroup>
<Compile Include="DomainHostingStarterAgent2.cs" />
<Compile Include="DomainHostingStarter2.cs" />
<Compile Include="MyAppLoader.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Loader\Loader.csproj">
<Project>{8faf6303-4ad0-4468-8dbc-b8d32b1a9f9d}</Project>
<Name>Loader</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
37 changes: 37 additions & 0 deletions OwinHost2/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System;
using System.Diagnostics;
using System.Linq;
using Microsoft.Owin.Hosting;
using Microsoft.Owin.Hosting.Starter;

namespace OwinHost2
{
class Program
{
[LoaderOptimization(LoaderOptimization.MultiDomainHost)]
static void Main(string[] args)
{
string path = args.FirstOrDefault();

if (String.IsNullOrEmpty(path))
{
Console.WriteLine("owinhost2.exe [path]");

Environment.Exit(-1);
return;
}

var host = new DomainHostingStarter2();
var options = new StartOptions();
options.Settings["directory"] = path;
options.Urls.Add("http://localhost:8081");

Trace.Listeners.Add(new ConsoleTraceListener());
Trace.AutoFlush = true;

host.Start(options);

Console.ReadLine();
}
}
}
36 changes: 36 additions & 0 deletions OwinHost2/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -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("ProjectSystemBootstrapper")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ProjectSystemBootstrapper")]
[assembly: AssemblyCopyright("Copyright © 2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("abd3823a-ed60-47c6-91ec-05e45023a85d")]

// 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")]
7 changes: 7 additions & 0 deletions OwinHost2/packages.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Owin" version="2.1.0-rc1-21106-691-dev" targetFramework="net45" />
<package id="Microsoft.Owin.Host.HttpListener" version="2.1.0-rc1-21106-691-dev" targetFramework="net45" />
<package id="Microsoft.Owin.Hosting" version="2.1.0-rc1-21106-691-dev" targetFramework="net45" />
<package id="Owin" version="1.0" targetFramework="net45" />
</packages>
34 changes: 34 additions & 0 deletions ProjectSystem.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.21005.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WatchDog", "WatchDog\WatchDog.csproj", "{D02B8440-E49A-4D49-A42F-92C41ABB1945}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Loader", "Loader\Loader.csproj", "{8FAF6303-4AD0-4468-8DBC-B8D32B1A9F9D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OwinHost2", "OwinHost2\OwinHost2.csproj", "{9218547E-DEA4-42B1-8869-94B2C4865C61}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D02B8440-E49A-4D49-A42F-92C41ABB1945}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D02B8440-E49A-4D49-A42F-92C41ABB1945}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D02B8440-E49A-4D49-A42F-92C41ABB1945}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D02B8440-E49A-4D49-A42F-92C41ABB1945}.Release|Any CPU.Build.0 = Release|Any CPU
{8FAF6303-4AD0-4468-8DBC-B8D32B1A9F9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8FAF6303-4AD0-4468-8DBC-B8D32B1A9F9D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8FAF6303-4AD0-4468-8DBC-B8D32B1A9F9D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8FAF6303-4AD0-4468-8DBC-B8D32B1A9F9D}.Release|Any CPU.Build.0 = Release|Any CPU
{9218547E-DEA4-42B1-8869-94B2C4865C61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9218547E-DEA4-42B1-8869-94B2C4865C61}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9218547E-DEA4-42B1-8869-94B2C4865C61}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9218547E-DEA4-42B1-8869-94B2C4865C61}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
6 changes: 6 additions & 0 deletions WatchDog/App.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>
121 changes: 121 additions & 0 deletions WatchDog/Executable.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WatchDog
{
public class Executable
{
public Executable(string path, string workingDirectory, TimeSpan idleTimeout)
{
Path = path;
WorkingDirectory = workingDirectory;
EnvironmentVariables = new Dictionary<string, string>();
Encoding = Encoding.UTF8;
IdleTimeout = idleTimeout;
}

public bool IsAvailable
{
get
{
return File.Exists(Path);
}
}

public string WorkingDirectory { get; private set; }

public string Path { get; private set; }

public IDictionary<string, string> EnvironmentVariables { get; set; }

public Encoding Encoding { get; set; }

public TimeSpan IdleTimeout { get; private set; }

public int Execute(Func<string, bool> onWriteOutput, Func<string, bool> onWriteError, Encoding encoding, string arguments, params object[] args)
{
Process process = CreateProcess(arguments, args);
process.EnableRaisingEvents = true;

var errorBuffer = new StringBuilder();
var outputBuffer = new StringBuilder();

process.OutputDataReceived += (sender, e) =>
{
if (e.Data != null)
{
if (onWriteOutput(e.Data))
{
outputBuffer.AppendLine(Encoding.UTF8.GetString(encoding.GetBytes(e.Data)));
}
}
};

process.ErrorDataReceived += (sender, e) =>
{
if (e.Data != null)
{
if (onWriteError(e.Data))
{
errorBuffer.AppendLine(Encoding.UTF8.GetString(encoding.GetBytes(e.Data)));
}
}
};

process.Start();

process.BeginErrorReadLine();
process.BeginOutputReadLine();


process.WaitForExit();

return process.ExitCode;
}

internal Process CreateProcess(string arguments, object[] args)
{
return CreateProcess(String.Format(arguments, args));
}

internal Process CreateProcess(string arguments)
{
var psi = new ProcessStartInfo
{
FileName = Path,
WorkingDirectory = WorkingDirectory,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden,
UseShellExecute = false,
ErrorDialog = false,
Arguments = arguments
};

if (Encoding != null)
{
psi.StandardOutputEncoding = Encoding;
psi.StandardErrorEncoding = Encoding;
}

foreach (var pair in EnvironmentVariables)
{
psi.EnvironmentVariables[pair.Key] = pair.Value;
}

var process = new Process()
{
StartInfo = psi
};

return process;
}
}
}
60 changes: 60 additions & 0 deletions WatchDog/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;

namespace WatchDog
{
class Program
{
static void Main(string[] args)
{
string path = args.FirstOrDefault();

if (String.IsNullOrEmpty(path))
{
Console.WriteLine("watchdog.exe [path] [args]");
Environment.Exit(-1);
return;
}

string childProcess = Path.GetFullPath(path);
string childArgs = String.Join(" ", args.Skip(1));

while (true)
{
Console.Write("Starting process '" + Path.GetFileName(childProcess) + "'");
if (!String.IsNullOrEmpty(childArgs))
{
Console.WriteLine(" with " + childArgs);
}
else
{
Console.WriteLine();
}

var exe = new Executable(childProcess, Environment.CurrentDirectory, TimeSpan.FromHours(1));
var exitCode = exe.Execute(s =>
{
Console.WriteLine(s);
return false;
},
s =>
{
Console.Error.WriteLine(s);
return false;
},
Encoding.UTF8, childArgs);

if (exitCode != 250)
{
Console.WriteLine("Exit code unknown {0}, quitting", exitCode);
break;
}

Thread.Sleep(100);
}
}
}
}
36 changes: 36 additions & 0 deletions WatchDog/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -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("WatchDog")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("WatchDog")]
[assembly: AssemblyCopyright("Copyright © 2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("622f6edc-b948-4150-8975-b1af7d2e50a7")]

// 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")]
59 changes: 59 additions & 0 deletions WatchDog/WatchDog.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{D02B8440-E49A-4D49-A42F-92C41ABB1945}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>WatchDog</RootNamespace>
<AssemblyName>WatchDog</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</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|AnyCPU' ">
<PlatformTarget>AnyCPU</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="Executable.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
Binary file added roslyn/Microsoft.CodeAnalysis.CSharp.dll
Binary file not shown.
Binary file added roslyn/Microsoft.CodeAnalysis.Features.dll
Binary file not shown.
Binary file added roslyn/Microsoft.CodeAnalysis.dll
Binary file not shown.
Binary file added roslyn/Roslyn.Scripting.CSharp.dll
Binary file not shown.
Binary file added roslyn/Roslyn.Scripting.Common.dll
Binary file not shown.
Binary file added roslyn/System.Collections.Immutable.dll
Binary file not shown.