Code:
/ FXUpdate3074 / FXUpdate3074 / 1.1 / DEVDIV / depot / DevDiv / releases / whidbey / QFE / ndp / fx / src / xsp / System / Web / Compilation / ClientBuildManager.cs / 4 / ClientBuildManager.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- /************************************************************************************************************/ namespace System.Web.Compilation { using System; using System.Collections; using System.Collections.Specialized; using System.Configuration; using System.Diagnostics; using System.IO; using System.Threading; using System.Reflection; using System.Runtime.InteropServices; using System.Runtime.Remoting; using System.Security.Permissions; using System.Globalization; using System.CodeDom; using System.CodeDom.Compiler; using System.Web; using System.Web.Configuration; using System.Web.Util; using System.Web.UI; using System.Web.Hosting; using System.Xml; using Debug=System.Web.Util.Debug; // Flags that drive the behavior of precompilation [Flags] public enum PrecompilationFlags { Default = 0x00000000, // determines whether the deployed app will be updatable Updatable = 0x00000001, // determines whether the target directory can be overwritten OverwriteTarget = 0x00000002, // determines whether the compiler will emit debug information ForceDebug = 0x00000004, // determines whether the application is built clean Clean = 0x00000008, // determines whether the /define:CodeAnalysis flag needs to be added // as compilation symbol CodeAnalysis = 0x00000010, // determines whether to generate APTCA attribute. AllowPartiallyTrustedCallers = 0x00000020, // determines whether to delaySign the generate assemblies. DelaySign = 0x00000040, // determines whether to use fixed assembly names FixedNames = 0x00000080, } [Serializable] [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class ClientBuildManagerParameter { private string _strongNameKeyFile; private string _strongNameKeyContainer; private PrecompilationFlags _precompilationFlags = PrecompilationFlags.Default; // Determines the behavior of the precompilation public PrecompilationFlags PrecompilationFlags { get { return _precompilationFlags; } set { _precompilationFlags = value; } } public string StrongNameKeyFile { get { return _strongNameKeyFile; } set { _strongNameKeyFile = value; } } public string StrongNameKeyContainer { get { return _strongNameKeyContainer; } set { _strongNameKeyContainer = value; } } } // // This class provide access to the BuildManager outside of an IIS environment // Instances of this class are created in the caller's App Domain. // // It creates and configures the new App Domain for handling BuildManager calls // using System.Web.Hosting.ApplicationHost.CreateApplicationHost() // [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)] [PermissionSet(SecurityAction.InheritanceDemand, Unrestricted = true)] public sealed class ClientBuildManager : MarshalByRefObject, IDisposable { private VirtualPath _virtualPath; private string _physicalPath; private string _installPath; private string _appId; private string _codeGenDir; private HostingEnvironmentParameters _hostingParameters; private WaitCallback _onAppDomainUnloadedCallback; private WaitCallback _onAppDomainShutdown; private ApplicationShutdownReason _reason; private BuildManagerHost _host; private Exception _hostCreationException; private bool _hostCreationPending; public event BuildManagerHostUnloadEventHandler AppDomainUnloaded; public event EventHandler AppDomainStarted; public event BuildManagerHostUnloadEventHandler AppDomainShutdown; // internal lock used for host creation. private object _lock = new object(); // Whether to wait for the call back from the previous host unloading before creating a new one private bool _waitForCallBack; /* * Creates an instance of the ClientBuildManager. * appPhysicalSourceDir points to the physical root of the application (e.g "c:\myapp") * virtualPath is the virtual path to the app root. It can be anything (e.g. "/dummy"), * but ideally it should match the path later given to Cassini, in order for * compilation that happens here to be reused there. */ public ClientBuildManager(string appVirtualDir, string appPhysicalSourceDir) : this(appVirtualDir, appPhysicalSourceDir, null /*appPhysicalTargetDir*/, null /*ClientBuildManagerParameter*/) { } /* * Creates an instance of the PrecompilationManager. * appPhysicalSourceDir points to the physical root of the application (e.g "c:\myapp") * appVirtualDir is the virtual path to the app root. It can be anything (e.g. "/dummy"), * but ideally it should match the path later given to Cassini, in order for * compilation that happens here to be reused there. * appPhysicalTargetDir is the directory where the precompiled site is placed */ public ClientBuildManager(string appVirtualDir, string appPhysicalSourceDir, string appPhysicalTargetDir) : this(appVirtualDir, appPhysicalSourceDir, appPhysicalTargetDir, null /*ClientBuildManagerParameter*/) { } /* * Creates an instance of the PrecompilationManager. * appPhysicalSourceDir points to the physical root of the application (e.g "c:\myapp") * appVirtualDir is the virtual path to the app root. It can be anything (e.g. "/dummy"), * but ideally it should match the path later given to Cassini, in order for * compilation that happens here to be reused there. * appPhysicalTargetDir is the directory where the precompiled site is placed * flags determines the behavior of the precompilation */ public ClientBuildManager(string appVirtualDir, string appPhysicalSourceDir, string appPhysicalTargetDir, ClientBuildManagerParameter parameter) { if (parameter == null) { parameter = new ClientBuildManagerParameter(); } // Always build clean in precompilation for deployment mode, // since building incrementally raises all kind of issues ( if (!String.IsNullOrEmpty(appPhysicalTargetDir)) { parameter.PrecompilationFlags |= PrecompilationFlags.Clean; } _hostingParameters = new HostingEnvironmentParameters(); _hostingParameters.HostingFlags = HostingEnvironmentFlags.DontCallAppInitialize | HostingEnvironmentFlags.ClientBuildManager; _hostingParameters.ClientBuildManagerParameter = parameter; _hostingParameters.PrecompilationTargetPhysicalDirectory = appPhysicalTargetDir; // Make sure the app virtual dir starts with / if (appVirtualDir[0] != '/') appVirtualDir = "/" + appVirtualDir; Initialize(VirtualPath.CreateNonRelative(appVirtualDir), appPhysicalSourceDir); } /* * returns the codegendir used by runtime appdomain */ public string CodeGenDir { get { if (_codeGenDir == null) { EnsureHostCreated(); _codeGenDir = _host.CodeGenDir; } return _codeGenDir; } } /* * Indicates whether the host is created. */ public bool IsHostCreated { get { return _host != null; } } /* * Create an object in the runtime appdomain */ public IRegisteredObject CreateObject(Type type, bool failIfExists) { if (type == null) { throw new ArgumentNullException("type"); } EnsureHostCreated(); Debug.Assert(_appId != null); _host.RegisterAssembly(type.Assembly.FullName, type.Assembly.Location); ApplicationManager appManager = ApplicationManager.GetApplicationManager(); return appManager.CreateObjectInternal(_appId, type, _host.ApplicationHost, failIfExists); } /* * Return the list of directories that would cause appdomain shutdown. */ public string[] GetAppDomainShutdownDirectories() { Debug.Trace("CBM", "GetAppDomainShutdownDirectories"); return FileChangesMonitor.s_dirsToMonitor; } /* * Makes sure that all the top level files are compiled (code, global.asax, ...) */ public void CompileApplicationDependencies() { Debug.Trace("CBM", "CompileApplicationDependencies"); EnsureHostCreated(); _host.CompileApplicationDependencies(); } public IDictionary GetBrowserDefinitions() { Debug.Trace("CBM", "GetBrowserDefinitions"); EnsureHostCreated(); return _host.GetBrowserDefinitions(); } /* * Returns the physical path of the generated file corresponding to the virtual directory. * Note the virtualPath needs to use this format: * "/[appname]/App_WebReferences/{[subDir]/}" */ public string GetGeneratedSourceFile(string virtualPath) { Debug.Trace("CBM", "GetGeneratedSourceFile " + virtualPath); if (virtualPath == null) { throw new ArgumentNullException("virtualPath"); } EnsureHostCreated(); return _host.GetGeneratedSourceFile(VirtualPath.CreateTrailingSlash(virtualPath)); } /* * Returns the virtual path of the corresponding generated file. * Note the filepath needs to be a full path. */ public string GetGeneratedFileVirtualPath(string filePath) { Debug.Trace("CBM", "GetGeneratedFileVirtualPath " + filePath); if (filePath == null) { throw new ArgumentNullException("filePath"); } EnsureHostCreated(); return _host.GetGeneratedFileVirtualPath(filePath); } /* * Returns an array of the virtual paths to all the code directories in the app thru the hosted appdomain */ public string[] GetVirtualCodeDirectories() { Debug.Trace("CBM", "GetHostedVirtualCodeDirectories"); EnsureHostCreated(); return _host.GetVirtualCodeDirectories(); } /* * Returns an array of the assemblies defined in the bin and assembly reference config section */ public String[] GetTopLevelAssemblyReferences(string virtualPath) { Debug.Trace("CBM", "GetHostedVirtualCodeDirectories"); if (virtualPath == null) { throw new ArgumentNullException("virtualPath"); } EnsureHostCreated(); return _host.GetTopLevelAssemblyReferences(VirtualPath.Create(virtualPath)); } /* * Returns the compiler type and parameters that need to be used to build * a given code directory. Also, returns the directory containing all the code * files generated from non-code files in the code directory (e.g. wsdl files) */ public void GetCodeDirectoryInformation(string virtualCodeDir, out Type codeDomProviderType, out CompilerParameters compilerParameters, out string generatedFilesDir) { Debug.Trace("CBM", "GetCodeDirectoryInformation " + virtualCodeDir); if (virtualCodeDir == null) { throw new ArgumentNullException("virtualCodeDir"); } EnsureHostCreated(); _host.GetCodeDirectoryInformation(VirtualPath.CreateTrailingSlash(virtualCodeDir), out codeDomProviderType, out compilerParameters, out generatedFilesDir); Debug.Trace("CBM", "GetCodeDirectoryInformation " + virtualCodeDir + " end"); } /* * Returns the compiler type and parameters that need to be used to build * a given file. */ public void GetCompilerParameters(string virtualPath, out Type codeDomProviderType, out CompilerParameters compilerParameters) { Debug.Trace("CBM", "GetCompilerParameters " + virtualPath); if (virtualPath == null) { throw new ArgumentNullException("virtualPath"); } EnsureHostCreated(); _host.GetCompilerParams(VirtualPath.Create(virtualPath), out codeDomProviderType, out compilerParameters); } /* * Returns the codedom tree and the compiler type/param for a given file. */ public CodeCompileUnit GenerateCodeCompileUnit( string virtualPath, out Type codeDomProviderType, out CompilerParameters compilerParameters, out IDictionary linePragmasTable) { Debug.Trace("CBM", "GenerateCodeCompileUnit " + virtualPath); return GenerateCodeCompileUnit(virtualPath, null, out codeDomProviderType, out compilerParameters, out linePragmasTable); } public CodeCompileUnit GenerateCodeCompileUnit( string virtualPath, String virtualFileString, out Type codeDomProviderType, out CompilerParameters compilerParameters, out IDictionary linePragmasTable) { Debug.Trace("CBM", "GenerateCodeCompileUnit " + virtualPath); if (virtualPath == null) { throw new ArgumentNullException("virtualPath"); } EnsureHostCreated(); return _host.GenerateCodeCompileUnit(VirtualPath.Create(virtualPath), virtualFileString, out codeDomProviderType, out compilerParameters, out linePragmasTable); } public string GenerateCode( string virtualPath, String virtualFileString, out IDictionary linePragmasTable) { Debug.Trace("CBM", "GenerateCode " + virtualPath); if (virtualPath == null) { throw new ArgumentNullException("virtualPath"); } EnsureHostCreated(); return _host.GenerateCode(VirtualPath.Create(virtualPath), virtualFileString, out linePragmasTable); } /* * Returns the compiled type for an input file */ public Type GetCompiledType(string virtualPath) { Debug.Trace("CBM", "GetCompiledType " + virtualPath); if (virtualPath == null) { throw new ArgumentNullException("virtualPath"); } EnsureHostCreated(); string[] typeAndAsemblyName = _host.GetCompiledTypeAndAssemblyName(VirtualPath.Create(virtualPath), null); if (typeAndAsemblyName == null) return null; Assembly a = Assembly.LoadFrom(typeAndAsemblyName[1]); Type t = a.GetType(typeAndAsemblyName[0]); return t; } /* * Compile a file */ public void CompileFile(string virtualPath) { CompileFile(virtualPath, null); } public void CompileFile(string virtualPath, ClientBuildManagerCallback callback) { Debug.Trace("CBM", "CompileFile " + virtualPath); if (virtualPath == null) { throw new ArgumentNullException("virtualPath"); } try { EnsureHostCreated(); _host.GetCompiledTypeAndAssemblyName(VirtualPath.Create(virtualPath), callback); } finally { // DevDiv 180798. We are returning null in ClientBuildManagerCallback.InitializeLifetimeService, // so we need to manually disconnect the instance so that it will be released. if (callback != null) { RemotingServices.Disconnect(callback); } } } /* * Indicates whether an assembly is a code assembly. */ public bool IsCodeAssembly(string assemblyName) { Debug.Trace("CBM", "IsCodeAssembly " + assemblyName); if (assemblyName == null) { throw new ArgumentNullException("assemblyName"); } // EnsureHostCreated(); bool result = _host.IsCodeAssembly(assemblyName); Debug.Trace("CBM", "IsCodeAssembly " + result.ToString()); return result; } public bool Unload() { Debug.Trace("CBM", "Unload"); BuildManagerHost host = _host; if (host != null) { _host = null; return host.UnloadAppDomain(); } return false; } /* * Precompile an application */ public void PrecompileApplication() { PrecompileApplication(null); } /* * Precompile an application with callback support */ public void PrecompileApplication(ClientBuildManagerCallback callback) { PrecompileApplication(callback, false); } public void PrecompileApplication(ClientBuildManagerCallback callback, bool forceCleanBuild) { Debug.Trace("CBM", "PrecompileApplication"); PrecompilationFlags savedFlags = _hostingParameters.ClientBuildManagerParameter.PrecompilationFlags; if (forceCleanBuild) { // If there was a previous host, it will be unloaded by CBM and we will wait for the callback. // If there was no previous host, we don't do any waiting. // DevDiv 46290 _waitForCallBack = _host != null; Debug.Trace("CBM", "Started Unload"); // Unload the existing appdomain so the new one will be created with the clean flag Unload(); _hostingParameters.ClientBuildManagerParameter.PrecompilationFlags = savedFlags | PrecompilationFlags.Clean; WaitForCallBack(); } try { EnsureHostCreated(); _host.PrecompileApp(callback); } finally { if (forceCleanBuild) { // Revert precompilationFlags _hostingParameters.ClientBuildManagerParameter.PrecompilationFlags = savedFlags; } // DevDiv 180798. We are returning null in ClientBuildManagerCallback.InitializeLifetimeService, // so we need to manually disconnect the instance so that it will be released. if (callback != null) { RemotingServices.Disconnect(callback); } } } // _waitForCallBack is set to false in OnAppDomainUnloaded. // This method waits until it is set to false before continuing, so that // we do not run into a concurrency issue where _host could be set to null. // DevDiv 46290 private void WaitForCallBack() { Debug.Trace("CBM", "WaitForCallBack"); int waited = 0; while (_waitForCallBack && waited <= 50) { Thread.Sleep(200); waited++; } if (_waitForCallBack) { Debug.Trace("CBM", "timeout while waiting for callback"); } else { Debug.Trace("CBM", "callback received before timeout"); } } public override Object InitializeLifetimeService() { return null; // never expire lease } internal void Initialize(VirtualPath virtualPath, string physicalPath) { Debug.Trace("CBM", "Initialize"); _virtualPath = virtualPath; _physicalPath = FileUtil.FixUpPhysicalDirectory(physicalPath); _onAppDomainUnloadedCallback = new WaitCallback(OnAppDomainUnloadedCallback); _onAppDomainShutdown = new WaitCallback(OnAppDomainShutdownCallback); _installPath = RuntimeEnvironment.GetRuntimeDirectory(); // Do not create host during intialization. It will be done on demand. //CreateHost(); } private void EnsureHostCreated() { if (_host == null) { lock (_lock) { // Create the host if necessary if (_host == null) { CreateHost(); Debug.Trace("CBM", "EnsureHostCreated: after CreateHost()"); } } } // If an exception happened during host creation, rethrow it if (_hostCreationException != null) { Debug.Trace("CBM", "EnsureHostCreated: failed. " + _hostCreationException); // We need to wrap it in a new exception, otherwise we lose the original stack. throw new HttpException(_hostCreationException.Message, _hostCreationException); } } private void CreateHost() { Debug.Trace("CBM", "CreateHost"); Debug.Assert(_host == null); Debug.Assert(!_hostCreationPending, "CreateHost: creation already pending"); _hostCreationPending = true; // Use a local to avoid having a partially created _host BuildManagerHost host = null; try { string appId; ApplicationManager appManager = ApplicationManager.GetApplicationManager(); host = (BuildManagerHost) appManager.CreateObjectWithDefaultAppHostAndAppId( _physicalPath, _virtualPath, typeof(BuildManagerHost), false /*failIfExists*/, _hostingParameters, out appId); // host appdomain cannot be unloaded during creation. host.AddPendingCall(); host.Configure(this); _host = host; _appId = appId; _hostCreationException = _host.InitializationException; } catch (Exception e) { // If an exception happens, keep track of it _hostCreationException = e; // Even though the host initialization failed, keep track of it so subsequent // request will see the error _host = host; } finally { _hostCreationPending = false; if (host != null) { // Notify the client that the host is ready if (AppDomainStarted != null) { AppDomainStarted(this, EventArgs.Empty); } // The host can be unloaded safely now. host.RemovePendingCall(); } } Debug.Trace("CBM", "CreateHost LEAVE"); } // Called by BuildManagerHost when the ASP appdomain is unloaded internal void OnAppDomainUnloaded(ApplicationShutdownReason reason) { Debug.Trace("CBM", "OnAppDomainUnloaded " + reason.ToString()); // Don't try to use this host anymore _host = null; _hostCreationException = null; _reason = reason; _waitForCallBack = false; // Don't do anything that can be slow here. Instead queue in a worker thread ThreadPool.QueueUserWorkItem(_onAppDomainUnloadedCallback); } private void OnAppDomainUnloadedCallback(Object unused) { Debug.Trace("CBM", "OnAppDomainUnloadedCallback"); // Notify the client that the appdomain is unloaded if (AppDomainUnloaded != null) { AppDomainUnloaded(this, new BuildManagerHostUnloadEventArgs(_reason)); } } private void OnAppDomainShutdownCallback(Object o) { if (AppDomainShutdown != null) { AppDomainShutdown(this, new BuildManagerHostUnloadEventArgs((ApplicationShutdownReason)o)); } } internal void OnAppDomainShutdown(ApplicationShutdownReason reason) { // Don't do anything that can be slow here. Instead queue in a worker thread ThreadPool.QueueUserWorkItem(_onAppDomainShutdown, reason); } #region IDisposable //Dispose the runtime appdomain properly when CBM is disposed void IDisposable.Dispose() { Unload(); } #endregion } [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)] [PermissionSet(SecurityAction.InheritanceDemand, Unrestricted = true)] public class BuildManagerHostUnloadEventArgs : EventArgs { ApplicationShutdownReason _reason; public BuildManagerHostUnloadEventArgs(ApplicationShutdownReason reason) { _reason = reason; } // Get the reason for the hosted appdomain shutdown public ApplicationShutdownReason Reason { get { return _reason; } } } public delegate void BuildManagerHostUnloadEventHandler(object sender, BuildManagerHostUnloadEventArgs e); /* * Type of the entries in the table returned by GenerateCodeCompileUnit */ [Serializable] [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] public sealed class LinePragmaCodeInfo { public LinePragmaCodeInfo() { } public LinePragmaCodeInfo(int startLine, int startColumn, int startGeneratedColumn, int codeLength, bool isCodeNugget) { this._startLine = startLine; this._startColumn = startColumn; this._startGeneratedColumn = startGeneratedColumn; this._codeLength = codeLength; this._isCodeNugget = isCodeNugget; } // Starting line in ASPX file internal int _startLine; public int StartLine { get { return _startLine; } } // Starting column in the ASPX file internal int _startColumn; public int StartColumn { get { return _startColumn; } } // Starting column in the generated source file (assuming no indentations are used) internal int _startGeneratedColumn; public int StartGeneratedColumn { get { return _startGeneratedColumn; } } // Length of the code snippet internal int _codeLength; public int CodeLength { get { return _codeLength; } } // Whether the script block is a nugget. internal bool _isCodeNugget; public bool IsCodeNugget { get { return _isCodeNugget; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- /************************************************************************************************************/ namespace System.Web.Compilation { using System; using System.Collections; using System.Collections.Specialized; using System.Configuration; using System.Diagnostics; using System.IO; using System.Threading; using System.Reflection; using System.Runtime.InteropServices; using System.Runtime.Remoting; using System.Security.Permissions; using System.Globalization; using System.CodeDom; using System.CodeDom.Compiler; using System.Web; using System.Web.Configuration; using System.Web.Util; using System.Web.UI; using System.Web.Hosting; using System.Xml; using Debug=System.Web.Util.Debug; // Flags that drive the behavior of precompilation [Flags] public enum PrecompilationFlags { Default = 0x00000000, // determines whether the deployed app will be updatable Updatable = 0x00000001, // determines whether the target directory can be overwritten OverwriteTarget = 0x00000002, // determines whether the compiler will emit debug information ForceDebug = 0x00000004, // determines whether the application is built clean Clean = 0x00000008, // determines whether the /define:CodeAnalysis flag needs to be added // as compilation symbol CodeAnalysis = 0x00000010, // determines whether to generate APTCA attribute. AllowPartiallyTrustedCallers = 0x00000020, // determines whether to delaySign the generate assemblies. DelaySign = 0x00000040, // determines whether to use fixed assembly names FixedNames = 0x00000080, } [Serializable] [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class ClientBuildManagerParameter { private string _strongNameKeyFile; private string _strongNameKeyContainer; private PrecompilationFlags _precompilationFlags = PrecompilationFlags.Default; // Determines the behavior of the precompilation public PrecompilationFlags PrecompilationFlags { get { return _precompilationFlags; } set { _precompilationFlags = value; } } public string StrongNameKeyFile { get { return _strongNameKeyFile; } set { _strongNameKeyFile = value; } } public string StrongNameKeyContainer { get { return _strongNameKeyContainer; } set { _strongNameKeyContainer = value; } } } // // This class provide access to the BuildManager outside of an IIS environment // Instances of this class are created in the caller's App Domain. // // It creates and configures the new App Domain for handling BuildManager calls // using System.Web.Hosting.ApplicationHost.CreateApplicationHost() // [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)] [PermissionSet(SecurityAction.InheritanceDemand, Unrestricted = true)] public sealed class ClientBuildManager : MarshalByRefObject, IDisposable { private VirtualPath _virtualPath; private string _physicalPath; private string _installPath; private string _appId; private string _codeGenDir; private HostingEnvironmentParameters _hostingParameters; private WaitCallback _onAppDomainUnloadedCallback; private WaitCallback _onAppDomainShutdown; private ApplicationShutdownReason _reason; private BuildManagerHost _host; private Exception _hostCreationException; private bool _hostCreationPending; public event BuildManagerHostUnloadEventHandler AppDomainUnloaded; public event EventHandler AppDomainStarted; public event BuildManagerHostUnloadEventHandler AppDomainShutdown; // internal lock used for host creation. private object _lock = new object(); // Whether to wait for the call back from the previous host unloading before creating a new one private bool _waitForCallBack; /* * Creates an instance of the ClientBuildManager. * appPhysicalSourceDir points to the physical root of the application (e.g "c:\myapp") * virtualPath is the virtual path to the app root. It can be anything (e.g. "/dummy"), * but ideally it should match the path later given to Cassini, in order for * compilation that happens here to be reused there. */ public ClientBuildManager(string appVirtualDir, string appPhysicalSourceDir) : this(appVirtualDir, appPhysicalSourceDir, null /*appPhysicalTargetDir*/, null /*ClientBuildManagerParameter*/) { } /* * Creates an instance of the PrecompilationManager. * appPhysicalSourceDir points to the physical root of the application (e.g "c:\myapp") * appVirtualDir is the virtual path to the app root. It can be anything (e.g. "/dummy"), * but ideally it should match the path later given to Cassini, in order for * compilation that happens here to be reused there. * appPhysicalTargetDir is the directory where the precompiled site is placed */ public ClientBuildManager(string appVirtualDir, string appPhysicalSourceDir, string appPhysicalTargetDir) : this(appVirtualDir, appPhysicalSourceDir, appPhysicalTargetDir, null /*ClientBuildManagerParameter*/) { } /* * Creates an instance of the PrecompilationManager. * appPhysicalSourceDir points to the physical root of the application (e.g "c:\myapp") * appVirtualDir is the virtual path to the app root. It can be anything (e.g. "/dummy"), * but ideally it should match the path later given to Cassini, in order for * compilation that happens here to be reused there. * appPhysicalTargetDir is the directory where the precompiled site is placed * flags determines the behavior of the precompilation */ public ClientBuildManager(string appVirtualDir, string appPhysicalSourceDir, string appPhysicalTargetDir, ClientBuildManagerParameter parameter) { if (parameter == null) { parameter = new ClientBuildManagerParameter(); } // Always build clean in precompilation for deployment mode, // since building incrementally raises all kind of issues ( if (!String.IsNullOrEmpty(appPhysicalTargetDir)) { parameter.PrecompilationFlags |= PrecompilationFlags.Clean; } _hostingParameters = new HostingEnvironmentParameters(); _hostingParameters.HostingFlags = HostingEnvironmentFlags.DontCallAppInitialize | HostingEnvironmentFlags.ClientBuildManager; _hostingParameters.ClientBuildManagerParameter = parameter; _hostingParameters.PrecompilationTargetPhysicalDirectory = appPhysicalTargetDir; // Make sure the app virtual dir starts with / if (appVirtualDir[0] != '/') appVirtualDir = "/" + appVirtualDir; Initialize(VirtualPath.CreateNonRelative(appVirtualDir), appPhysicalSourceDir); } /* * returns the codegendir used by runtime appdomain */ public string CodeGenDir { get { if (_codeGenDir == null) { EnsureHostCreated(); _codeGenDir = _host.CodeGenDir; } return _codeGenDir; } } /* * Indicates whether the host is created. */ public bool IsHostCreated { get { return _host != null; } } /* * Create an object in the runtime appdomain */ public IRegisteredObject CreateObject(Type type, bool failIfExists) { if (type == null) { throw new ArgumentNullException("type"); } EnsureHostCreated(); Debug.Assert(_appId != null); _host.RegisterAssembly(type.Assembly.FullName, type.Assembly.Location); ApplicationManager appManager = ApplicationManager.GetApplicationManager(); return appManager.CreateObjectInternal(_appId, type, _host.ApplicationHost, failIfExists); } /* * Return the list of directories that would cause appdomain shutdown. */ public string[] GetAppDomainShutdownDirectories() { Debug.Trace("CBM", "GetAppDomainShutdownDirectories"); return FileChangesMonitor.s_dirsToMonitor; } /* * Makes sure that all the top level files are compiled (code, global.asax, ...) */ public void CompileApplicationDependencies() { Debug.Trace("CBM", "CompileApplicationDependencies"); EnsureHostCreated(); _host.CompileApplicationDependencies(); } public IDictionary GetBrowserDefinitions() { Debug.Trace("CBM", "GetBrowserDefinitions"); EnsureHostCreated(); return _host.GetBrowserDefinitions(); } /* * Returns the physical path of the generated file corresponding to the virtual directory. * Note the virtualPath needs to use this format: * "/[appname]/App_WebReferences/{[subDir]/}" */ public string GetGeneratedSourceFile(string virtualPath) { Debug.Trace("CBM", "GetGeneratedSourceFile " + virtualPath); if (virtualPath == null) { throw new ArgumentNullException("virtualPath"); } EnsureHostCreated(); return _host.GetGeneratedSourceFile(VirtualPath.CreateTrailingSlash(virtualPath)); } /* * Returns the virtual path of the corresponding generated file. * Note the filepath needs to be a full path. */ public string GetGeneratedFileVirtualPath(string filePath) { Debug.Trace("CBM", "GetGeneratedFileVirtualPath " + filePath); if (filePath == null) { throw new ArgumentNullException("filePath"); } EnsureHostCreated(); return _host.GetGeneratedFileVirtualPath(filePath); } /* * Returns an array of the virtual paths to all the code directories in the app thru the hosted appdomain */ public string[] GetVirtualCodeDirectories() { Debug.Trace("CBM", "GetHostedVirtualCodeDirectories"); EnsureHostCreated(); return _host.GetVirtualCodeDirectories(); } /* * Returns an array of the assemblies defined in the bin and assembly reference config section */ public String[] GetTopLevelAssemblyReferences(string virtualPath) { Debug.Trace("CBM", "GetHostedVirtualCodeDirectories"); if (virtualPath == null) { throw new ArgumentNullException("virtualPath"); } EnsureHostCreated(); return _host.GetTopLevelAssemblyReferences(VirtualPath.Create(virtualPath)); } /* * Returns the compiler type and parameters that need to be used to build * a given code directory. Also, returns the directory containing all the code * files generated from non-code files in the code directory (e.g. wsdl files) */ public void GetCodeDirectoryInformation(string virtualCodeDir, out Type codeDomProviderType, out CompilerParameters compilerParameters, out string generatedFilesDir) { Debug.Trace("CBM", "GetCodeDirectoryInformation " + virtualCodeDir); if (virtualCodeDir == null) { throw new ArgumentNullException("virtualCodeDir"); } EnsureHostCreated(); _host.GetCodeDirectoryInformation(VirtualPath.CreateTrailingSlash(virtualCodeDir), out codeDomProviderType, out compilerParameters, out generatedFilesDir); Debug.Trace("CBM", "GetCodeDirectoryInformation " + virtualCodeDir + " end"); } /* * Returns the compiler type and parameters that need to be used to build * a given file. */ public void GetCompilerParameters(string virtualPath, out Type codeDomProviderType, out CompilerParameters compilerParameters) { Debug.Trace("CBM", "GetCompilerParameters " + virtualPath); if (virtualPath == null) { throw new ArgumentNullException("virtualPath"); } EnsureHostCreated(); _host.GetCompilerParams(VirtualPath.Create(virtualPath), out codeDomProviderType, out compilerParameters); } /* * Returns the codedom tree and the compiler type/param for a given file. */ public CodeCompileUnit GenerateCodeCompileUnit( string virtualPath, out Type codeDomProviderType, out CompilerParameters compilerParameters, out IDictionary linePragmasTable) { Debug.Trace("CBM", "GenerateCodeCompileUnit " + virtualPath); return GenerateCodeCompileUnit(virtualPath, null, out codeDomProviderType, out compilerParameters, out linePragmasTable); } public CodeCompileUnit GenerateCodeCompileUnit( string virtualPath, String virtualFileString, out Type codeDomProviderType, out CompilerParameters compilerParameters, out IDictionary linePragmasTable) { Debug.Trace("CBM", "GenerateCodeCompileUnit " + virtualPath); if (virtualPath == null) { throw new ArgumentNullException("virtualPath"); } EnsureHostCreated(); return _host.GenerateCodeCompileUnit(VirtualPath.Create(virtualPath), virtualFileString, out codeDomProviderType, out compilerParameters, out linePragmasTable); } public string GenerateCode( string virtualPath, String virtualFileString, out IDictionary linePragmasTable) { Debug.Trace("CBM", "GenerateCode " + virtualPath); if (virtualPath == null) { throw new ArgumentNullException("virtualPath"); } EnsureHostCreated(); return _host.GenerateCode(VirtualPath.Create(virtualPath), virtualFileString, out linePragmasTable); } /* * Returns the compiled type for an input file */ public Type GetCompiledType(string virtualPath) { Debug.Trace("CBM", "GetCompiledType " + virtualPath); if (virtualPath == null) { throw new ArgumentNullException("virtualPath"); } EnsureHostCreated(); string[] typeAndAsemblyName = _host.GetCompiledTypeAndAssemblyName(VirtualPath.Create(virtualPath), null); if (typeAndAsemblyName == null) return null; Assembly a = Assembly.LoadFrom(typeAndAsemblyName[1]); Type t = a.GetType(typeAndAsemblyName[0]); return t; } /* * Compile a file */ public void CompileFile(string virtualPath) { CompileFile(virtualPath, null); } public void CompileFile(string virtualPath, ClientBuildManagerCallback callback) { Debug.Trace("CBM", "CompileFile " + virtualPath); if (virtualPath == null) { throw new ArgumentNullException("virtualPath"); } try { EnsureHostCreated(); _host.GetCompiledTypeAndAssemblyName(VirtualPath.Create(virtualPath), callback); } finally { // DevDiv 180798. We are returning null in ClientBuildManagerCallback.InitializeLifetimeService, // so we need to manually disconnect the instance so that it will be released. if (callback != null) { RemotingServices.Disconnect(callback); } } } /* * Indicates whether an assembly is a code assembly. */ public bool IsCodeAssembly(string assemblyName) { Debug.Trace("CBM", "IsCodeAssembly " + assemblyName); if (assemblyName == null) { throw new ArgumentNullException("assemblyName"); } // EnsureHostCreated(); bool result = _host.IsCodeAssembly(assemblyName); Debug.Trace("CBM", "IsCodeAssembly " + result.ToString()); return result; } public bool Unload() { Debug.Trace("CBM", "Unload"); BuildManagerHost host = _host; if (host != null) { _host = null; return host.UnloadAppDomain(); } return false; } /* * Precompile an application */ public void PrecompileApplication() { PrecompileApplication(null); } /* * Precompile an application with callback support */ public void PrecompileApplication(ClientBuildManagerCallback callback) { PrecompileApplication(callback, false); } public void PrecompileApplication(ClientBuildManagerCallback callback, bool forceCleanBuild) { Debug.Trace("CBM", "PrecompileApplication"); PrecompilationFlags savedFlags = _hostingParameters.ClientBuildManagerParameter.PrecompilationFlags; if (forceCleanBuild) { // If there was a previous host, it will be unloaded by CBM and we will wait for the callback. // If there was no previous host, we don't do any waiting. // DevDiv 46290 _waitForCallBack = _host != null; Debug.Trace("CBM", "Started Unload"); // Unload the existing appdomain so the new one will be created with the clean flag Unload(); _hostingParameters.ClientBuildManagerParameter.PrecompilationFlags = savedFlags | PrecompilationFlags.Clean; WaitForCallBack(); } try { EnsureHostCreated(); _host.PrecompileApp(callback); } finally { if (forceCleanBuild) { // Revert precompilationFlags _hostingParameters.ClientBuildManagerParameter.PrecompilationFlags = savedFlags; } // DevDiv 180798. We are returning null in ClientBuildManagerCallback.InitializeLifetimeService, // so we need to manually disconnect the instance so that it will be released. if (callback != null) { RemotingServices.Disconnect(callback); } } } // _waitForCallBack is set to false in OnAppDomainUnloaded. // This method waits until it is set to false before continuing, so that // we do not run into a concurrency issue where _host could be set to null. // DevDiv 46290 private void WaitForCallBack() { Debug.Trace("CBM", "WaitForCallBack"); int waited = 0; while (_waitForCallBack && waited <= 50) { Thread.Sleep(200); waited++; } if (_waitForCallBack) { Debug.Trace("CBM", "timeout while waiting for callback"); } else { Debug.Trace("CBM", "callback received before timeout"); } } public override Object InitializeLifetimeService() { return null; // never expire lease } internal void Initialize(VirtualPath virtualPath, string physicalPath) { Debug.Trace("CBM", "Initialize"); _virtualPath = virtualPath; _physicalPath = FileUtil.FixUpPhysicalDirectory(physicalPath); _onAppDomainUnloadedCallback = new WaitCallback(OnAppDomainUnloadedCallback); _onAppDomainShutdown = new WaitCallback(OnAppDomainShutdownCallback); _installPath = RuntimeEnvironment.GetRuntimeDirectory(); // Do not create host during intialization. It will be done on demand. //CreateHost(); } private void EnsureHostCreated() { if (_host == null) { lock (_lock) { // Create the host if necessary if (_host == null) { CreateHost(); Debug.Trace("CBM", "EnsureHostCreated: after CreateHost()"); } } } // If an exception happened during host creation, rethrow it if (_hostCreationException != null) { Debug.Trace("CBM", "EnsureHostCreated: failed. " + _hostCreationException); // We need to wrap it in a new exception, otherwise we lose the original stack. throw new HttpException(_hostCreationException.Message, _hostCreationException); } } private void CreateHost() { Debug.Trace("CBM", "CreateHost"); Debug.Assert(_host == null); Debug.Assert(!_hostCreationPending, "CreateHost: creation already pending"); _hostCreationPending = true; // Use a local to avoid having a partially created _host BuildManagerHost host = null; try { string appId; ApplicationManager appManager = ApplicationManager.GetApplicationManager(); host = (BuildManagerHost) appManager.CreateObjectWithDefaultAppHostAndAppId( _physicalPath, _virtualPath, typeof(BuildManagerHost), false /*failIfExists*/, _hostingParameters, out appId); // host appdomain cannot be unloaded during creation. host.AddPendingCall(); host.Configure(this); _host = host; _appId = appId; _hostCreationException = _host.InitializationException; } catch (Exception e) { // If an exception happens, keep track of it _hostCreationException = e; // Even though the host initialization failed, keep track of it so subsequent // request will see the error _host = host; } finally { _hostCreationPending = false; if (host != null) { // Notify the client that the host is ready if (AppDomainStarted != null) { AppDomainStarted(this, EventArgs.Empty); } // The host can be unloaded safely now. host.RemovePendingCall(); } } Debug.Trace("CBM", "CreateHost LEAVE"); } // Called by BuildManagerHost when the ASP appdomain is unloaded internal void OnAppDomainUnloaded(ApplicationShutdownReason reason) { Debug.Trace("CBM", "OnAppDomainUnloaded " + reason.ToString()); // Don't try to use this host anymore _host = null; _hostCreationException = null; _reason = reason; _waitForCallBack = false; // Don't do anything that can be slow here. Instead queue in a worker thread ThreadPool.QueueUserWorkItem(_onAppDomainUnloadedCallback); } private void OnAppDomainUnloadedCallback(Object unused) { Debug.Trace("CBM", "OnAppDomainUnloadedCallback"); // Notify the client that the appdomain is unloaded if (AppDomainUnloaded != null) { AppDomainUnloaded(this, new BuildManagerHostUnloadEventArgs(_reason)); } } private void OnAppDomainShutdownCallback(Object o) { if (AppDomainShutdown != null) { AppDomainShutdown(this, new BuildManagerHostUnloadEventArgs((ApplicationShutdownReason)o)); } } internal void OnAppDomainShutdown(ApplicationShutdownReason reason) { // Don't do anything that can be slow here. Instead queue in a worker thread ThreadPool.QueueUserWorkItem(_onAppDomainShutdown, reason); } #region IDisposable //Dispose the runtime appdomain properly when CBM is disposed void IDisposable.Dispose() { Unload(); } #endregion } [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)] [PermissionSet(SecurityAction.InheritanceDemand, Unrestricted = true)] public class BuildManagerHostUnloadEventArgs : EventArgs { ApplicationShutdownReason _reason; public BuildManagerHostUnloadEventArgs(ApplicationShutdownReason reason) { _reason = reason; } // Get the reason for the hosted appdomain shutdown public ApplicationShutdownReason Reason { get { return _reason; } } } public delegate void BuildManagerHostUnloadEventHandler(object sender, BuildManagerHostUnloadEventArgs e); /* * Type of the entries in the table returned by GenerateCodeCompileUnit */ [Serializable] [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] public sealed class LinePragmaCodeInfo { public LinePragmaCodeInfo() { } public LinePragmaCodeInfo(int startLine, int startColumn, int startGeneratedColumn, int codeLength, bool isCodeNugget) { this._startLine = startLine; this._startColumn = startColumn; this._startGeneratedColumn = startGeneratedColumn; this._codeLength = codeLength; this._isCodeNugget = isCodeNugget; } // Starting line in ASPX file internal int _startLine; public int StartLine { get { return _startLine; } } // Starting column in the ASPX file internal int _startColumn; public int StartColumn { get { return _startColumn; } } // Starting column in the generated source file (assuming no indentations are used) internal int _startGeneratedColumn; public int StartGeneratedColumn { get { return _startGeneratedColumn; } } // Length of the code snippet internal int _codeLength; public int CodeLength { get { return _codeLength; } } // Whether the script block is a nugget. internal bool _isCodeNugget; public bool IsCodeNugget { get { return _isCodeNugget; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- XmlSchemaSimpleType.cs
- SharedPerformanceCounter.cs
- GiveFeedbackEventArgs.cs
- SimpleHandlerFactory.cs
- ParallelRangeManager.cs
- Soap12FormatExtensions.cs
- UrlRoutingModule.cs
- CheckBoxList.cs
- WeakReferenceEnumerator.cs
- NonSerializedAttribute.cs
- InputBinder.cs
- DesignSurfaceCollection.cs
- SmtpNtlmAuthenticationModule.cs
- PointLight.cs
- PageCatalogPartDesigner.cs
- WebPartsPersonalizationAuthorization.cs
- WindowPattern.cs
- ColorConvertedBitmapExtension.cs
- DataViewManager.cs
- PropertyTabChangedEvent.cs
- VBIdentifierName.cs
- MissingMemberException.cs
- SeekStoryboard.cs
- TrackingStringDictionary.cs
- DataGridViewRow.cs
- GregorianCalendarHelper.cs
- TabletDeviceInfo.cs
- ClientSideQueueItem.cs
- XPathExpr.cs
- ASCIIEncoding.cs
- XamlPointCollectionSerializer.cs
- StorageAssociationTypeMapping.cs
- PreviewPrintController.cs
- Int16Animation.cs
- ProxyGenerator.cs
- UITypeEditor.cs
- SoapEnumAttribute.cs
- CachingHintValidation.cs
- DBCommandBuilder.cs
- RegexTree.cs
- XmlAggregates.cs
- DispatcherProcessingDisabled.cs
- LinearGradientBrush.cs
- SqlTransaction.cs
- StrokeNodeEnumerator.cs
- ObjectAnimationBase.cs
- XpsPackagingException.cs
- MsmqIntegrationBindingElement.cs
- TriggerAction.cs
- FixedSOMTable.cs
- DesignerHelpers.cs
- DataTableCollection.cs
- LiteralTextContainerControlBuilder.cs
- StructuredProperty.cs
- TextEffectResolver.cs
- SynchronizationLockException.cs
- PopupControlService.cs
- DbCommandDefinition.cs
- AssemblyInfo.cs
- CqlParser.cs
- RightsManagementPermission.cs
- TreeSet.cs
- EventLogTraceListener.cs
- ProcessHostServerConfig.cs
- XmlFormatWriterGenerator.cs
- RowParagraph.cs
- OracleParameter.cs
- FtpWebResponse.cs
- AttributeProviderAttribute.cs
- _AutoWebProxyScriptHelper.cs
- ZoneIdentityPermission.cs
- Point3DAnimationBase.cs
- _OSSOCK.cs
- Msec.cs
- DataGridLinkButton.cs
- LoadGrammarCompletedEventArgs.cs
- HttpDigestClientCredential.cs
- Path.cs
- ZoneIdentityPermission.cs
- DbTransaction.cs
- ThreadLocal.cs
- DataGridSortCommandEventArgs.cs
- ReadOnlyDictionary.cs
- Random.cs
- XmlSignatureManifest.cs
- SqlReferenceCollection.cs
- IResourceProvider.cs
- ListContractAdapter.cs
- GridViewDeletedEventArgs.cs
- __Filters.cs
- wmiprovider.cs
- SqlVisitor.cs
- SQLBytes.cs
- AuthenticateEventArgs.cs
- ContentOperations.cs
- SmiGettersStream.cs
- XmlHierarchicalEnumerable.cs
- ResXResourceReader.cs
- HelpKeywordAttribute.cs
- IndependentAnimationStorage.cs