mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-14 19:04:51 +08:00
Initial version of "Orchard.exe"
* Understands "/workingdirectory", "/verbose", "/virtualpath" switches * Starts up a WebHost instance in a separate AppDomain --HG-- branch : dev
This commit is contained in:
@@ -53,6 +53,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Futures.Widgets", "Orchard.
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.Specs", "Orchard.Specs\Orchard.Specs.csproj", "{7354DF37-934B-46CF-A13C-455D5F5F5413}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard", "Tools\Orchard\Orchard.csproj", "{33B1BC8D-E292-4972-A363-22056B207156}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -147,6 +149,10 @@ Global
|
||||
{7354DF37-934B-46CF-A13C-455D5F5F5413}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7354DF37-934B-46CF-A13C-455D5F5F5413}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7354DF37-934B-46CF-A13C-455D5F5F5413}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{33B1BC8D-E292-4972-A363-22056B207156}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{33B1BC8D-E292-4972-A363-22056B207156}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{33B1BC8D-E292-4972-A363-22056B207156}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{33B1BC8D-E292-4972-A363-22056B207156}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -170,6 +176,7 @@ Global
|
||||
{8C7FCBC2-E6E1-405E-BFB5-D8D9E67A09C4} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5}
|
||||
{5E5E7A21-C7B2-44D8-8593-2F9541AE041D} = {383DBA32-4A3E-48D1-AAC3-75377A694452}
|
||||
{4AB4B5B6-277E-4FF6-B69B-7AE9E16D2A56} = {383DBA32-4A3E-48D1-AAC3-75377A694452}
|
||||
{33B1BC8D-E292-4972-A363-22056B207156} = {383DBA32-4A3E-48D1-AAC3-75377A694452}
|
||||
{E65E5633-C0FF-453C-A906-481C14F969D6} = {E75A4CE4-CAA6-41E4-B951-33ACC60DC77C}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
7
src/Tools/Orchard/Arguments/IParser.cs
Normal file
7
src/Tools/Orchard/Arguments/IParser.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Orchard.Arguments {
|
||||
public interface IParser {
|
||||
ParserResult Parse(IEnumerable<string> args);
|
||||
}
|
||||
}
|
34
src/Tools/Orchard/Arguments/Parser.cs
Normal file
34
src/Tools/Orchard/Arguments/Parser.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Orchard.Arguments {
|
||||
public class Parser : IParser {
|
||||
public ParserResult Parse(IEnumerable<string> args) {
|
||||
ParserResult result = new ParserResult();
|
||||
|
||||
IEnumerator<string> e = args.GetEnumerator();
|
||||
while (e.MoveNext()) {
|
||||
if (e.Current[0] == '/') {
|
||||
var s = ParseSwitch(e);
|
||||
result.Switches.Add(s);
|
||||
}
|
||||
else {
|
||||
result.Arguments.Add(e.Current);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private Switch ParseSwitch(IEnumerator<string> enumerator) {
|
||||
string sw = enumerator.Current.Substring(1);
|
||||
string[] args = sw.Split(':');
|
||||
return new Switch {
|
||||
Name = args[0],
|
||||
Value = args.Length >= 2 ? args[1] : string.Empty
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
13
src/Tools/Orchard/Arguments/ParserResult.cs
Normal file
13
src/Tools/Orchard/Arguments/ParserResult.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Orchard.Arguments {
|
||||
public class ParserResult {
|
||||
public ParserResult() {
|
||||
this.Arguments = new List<string>();
|
||||
this.Switches = new List<Switch>();
|
||||
}
|
||||
|
||||
public IList<string> Arguments { get; set; }
|
||||
public IList<Switch> Switches { get; set; }
|
||||
}
|
||||
}
|
6
src/Tools/Orchard/Arguments/Switch.cs
Normal file
6
src/Tools/Orchard/Arguments/Switch.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace Orchard.Arguments {
|
||||
public class Switch {
|
||||
public string Name { get; set; }
|
||||
public string Value { get; set; }
|
||||
}
|
||||
}
|
22
src/Tools/Orchard/Host/CommandHost.cs
Normal file
22
src/Tools/Orchard/Host/CommandHost.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Web.Hosting;
|
||||
|
||||
namespace Orchard.Host {
|
||||
class CommandHost : MarshalByRefObject, IRegisteredObject {
|
||||
public CommandHost() {
|
||||
HostingEnvironment.RegisterObject(this);
|
||||
}
|
||||
|
||||
public override object InitializeLifetimeService() {
|
||||
// never expire the license
|
||||
return null;
|
||||
}
|
||||
|
||||
public void Stop(bool immediate) {
|
||||
//TODO
|
||||
}
|
||||
}
|
||||
}
|
67
src/Tools/Orchard/Orchard.csproj
Normal file
67
src/Tools/Orchard/Orchard.csproj
Normal file
@@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{33B1BC8D-E292-4972-A363-22056B207156}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Orchard</RootNamespace>
|
||||
<AssemblyName>Orchard</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Xml.Linq">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Data.DataSetExtensions">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Arguments\IParser.cs" />
|
||||
<Compile Include="OrchardArguments.cs" />
|
||||
<Compile Include="Arguments\Parser.cs" />
|
||||
<Compile Include="Arguments\ParserResult.cs" />
|
||||
<Compile Include="Host\CommandHost.cs" />
|
||||
<Compile Include="OrchardArgumentsParser.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Arguments\Switch.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
12
src/Tools/Orchard/OrchardArguments.cs
Normal file
12
src/Tools/Orchard/OrchardArguments.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Orchard {
|
||||
public class OrchardArguments {
|
||||
public bool Verbose { get; set; }
|
||||
public string VirtualPath { get; set; }
|
||||
public string WorkingDirectory { get; set; }
|
||||
}
|
||||
}
|
38
src/Tools/Orchard/OrchardArgumentsParser.cs
Normal file
38
src/Tools/Orchard/OrchardArgumentsParser.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Orchard.Arguments;
|
||||
|
||||
namespace Orchard {
|
||||
public interface IOrchardArgumentsParser {
|
||||
OrchardArguments Parse(ParserResult arguments);
|
||||
}
|
||||
|
||||
public class OrchardArgumentsParser : IOrchardArgumentsParser {
|
||||
public OrchardArguments Parse(ParserResult arguments) {
|
||||
OrchardArguments result = new OrchardArguments();
|
||||
|
||||
foreach (var sw in arguments.Switches) {
|
||||
switch (sw.Name.ToLowerInvariant()) {
|
||||
case "wd":
|
||||
case "workingdirectory":
|
||||
result.WorkingDirectory = sw.Value;
|
||||
break;
|
||||
|
||||
case "v":
|
||||
case "verbose":
|
||||
result.Verbose = bool.Parse(sw.Value);
|
||||
break;
|
||||
|
||||
case "vp":
|
||||
case "virtualpath":
|
||||
result.VirtualPath = sw.Value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
96
src/Tools/Orchard/Program.cs
Normal file
96
src/Tools/Orchard/Program.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using System.Web.Hosting;
|
||||
using Orchard.Host;
|
||||
|
||||
namespace Orchard {
|
||||
class Program {
|
||||
private readonly string[] _args;
|
||||
|
||||
private Program(string[] args) {
|
||||
_args = args;
|
||||
}
|
||||
|
||||
static void Main(string[] args) {
|
||||
new Program(args).Run();
|
||||
}
|
||||
|
||||
public void Run() {
|
||||
// Parse command line arguments
|
||||
var arguments = new OrchardArgumentsParser().Parse(new Orchard.Arguments.Parser().Parse(_args));
|
||||
|
||||
if (string.IsNullOrEmpty(arguments.VirtualPath))
|
||||
arguments.VirtualPath = "/";
|
||||
|
||||
if (string.IsNullOrEmpty(arguments.WorkingDirectory))
|
||||
arguments.WorkingDirectory = Environment.CurrentDirectory;
|
||||
|
||||
if (arguments.Verbose) {
|
||||
Console.WriteLine("Virtual path: {0}", arguments.VirtualPath);
|
||||
Console.WriteLine("Working directory: {0}", arguments.WorkingDirectory);
|
||||
}
|
||||
|
||||
var orchardDirectory = GetOrchardDirectory(arguments.WorkingDirectory);
|
||||
if (arguments.Verbose) {
|
||||
Console.WriteLine("Detected and using orchard directory \"{0}\"", orchardDirectory.FullName);
|
||||
}
|
||||
|
||||
object host = CreateWorkerAppDomainWithHost(arguments.VirtualPath, orchardDirectory.FullName, typeof(CommandHost));
|
||||
|
||||
}
|
||||
|
||||
private DirectoryInfo GetOrchardDirectory(string directory) {
|
||||
for (var directoryInfo = new DirectoryInfo(directory); directoryInfo != null; directoryInfo = directoryInfo.Parent) {
|
||||
if (!directoryInfo.Exists) {
|
||||
throw new ApplicationException(string.Format("Directory \"{0}\" does not exist", directoryInfo.FullName));
|
||||
}
|
||||
|
||||
var webConfigFileInfo = new FileInfo(Path.Combine(directoryInfo.FullName, "web.config"));
|
||||
if (!webConfigFileInfo.Exists)
|
||||
continue;
|
||||
|
||||
var binDirectoryInfo = new DirectoryInfo(Path.Combine(directoryInfo.FullName, "bin"));
|
||||
if (!binDirectoryInfo.Exists)
|
||||
continue;
|
||||
|
||||
var orchardFrameworkFileInfo = new FileInfo(Path.Combine(binDirectoryInfo.FullName, "Orchard.Framework.dll"));
|
||||
if (!orchardFrameworkFileInfo.Exists)
|
||||
continue;
|
||||
|
||||
return directoryInfo;
|
||||
}
|
||||
|
||||
throw new ApplicationException("Directory \"{0}\" doesn't seem to contain an Orchard installation");
|
||||
}
|
||||
|
||||
public object CreateWorkerAppDomainWithHost(string virtualPath, string physicalPath, Type hostType) {
|
||||
// this creates worker app domain in a way that host doesn't need to be in GAC or bin
|
||||
// using BuildManagerHost via private reflection
|
||||
string uniqueAppString = string.Concat(virtualPath, physicalPath).ToLowerInvariant();
|
||||
string appId = (uniqueAppString.GetHashCode()).ToString("x", CultureInfo.InvariantCulture);
|
||||
|
||||
// create BuildManagerHost in the worker app domain
|
||||
var appManager = ApplicationManager.GetApplicationManager();
|
||||
var buildManagerHostType = typeof(HttpRuntime).Assembly.GetType("System.Web.Compilation.BuildManagerHost");
|
||||
var buildManagerHost = appManager.CreateObject(appId, buildManagerHostType, virtualPath, physicalPath, false);
|
||||
|
||||
// call BuildManagerHost.RegisterAssembly to make Host type loadable in the worker app domain
|
||||
buildManagerHostType.InvokeMember(
|
||||
"RegisterAssembly",
|
||||
BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.NonPublic,
|
||||
null,
|
||||
buildManagerHost,
|
||||
new object[2] { hostType.Assembly.FullName, hostType.Assembly.Location });
|
||||
|
||||
// create Host in the worker app domain
|
||||
return appManager.CreateObject(appId, hostType, virtualPath, physicalPath, false);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
36
src/Tools/Orchard/Properties/AssemblyInfo.cs
Normal file
36
src/Tools/Orchard/Properties/AssemblyInfo.cs
Normal file
@@ -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("Orchard")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Microsoft")]
|
||||
[assembly: AssemblyProduct("Orchard")]
|
||||
[assembly: AssemblyCopyright("Copyright © Microsoft 2010")]
|
||||
[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("5ee627dd-b767-441e-b8d0-ec7d26faac49")]
|
||||
|
||||
// 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")]
|
Reference in New Issue
Block a user