| 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; | ||
| } | ||
| } | ||
| } |
| 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; | ||
| } | ||
| } | ||
| } |
| 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")] |
| 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; } | ||
| } | ||
| } | ||
|
|
||
| } |
| 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> |
| 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> |
| 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); | ||
| } | ||
| } | ||
| } | ||
| } |
| 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); | ||
| } | ||
| } | ||
| } |
| 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 }); | ||
| }; | ||
| } | ||
| } | ||
| } |
| 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> |
| 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(); | ||
| } | ||
| } | ||
| } |
| 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")] |
| 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> |
| 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 |
| 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> |
| 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; | ||
| } | ||
| } | ||
| } |
| 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); | ||
| } | ||
| } | ||
| } | ||
| } |
| 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")] |
| 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> |