Code:
/ FX-1434 / FX-1434 / 1.0 / untmp / whidbey / REDBITS / 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.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 (VSWhidbey 382954). 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"); } EnsureHostCreated(); _host.GetCompiledTypeAndAssemblyName(VirtualPath.Create(virtualPath), 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; } } } // _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; } } } }
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- EntityDataSourceQueryBuilder.cs
- SystemIPv4InterfaceProperties.cs
- MetadataArtifactLoaderComposite.cs
- UpdatePanelControlTrigger.cs
- InheritablePropertyChangeInfo.cs
- EntityContainerEmitter.cs
- TableItemProviderWrapper.cs
- Timer.cs
- MatrixConverter.cs
- XmlWriterSettings.cs
- XmlTextWriter.cs
- XmlTextEncoder.cs
- SymbolUsageManager.cs
- DbDataReader.cs
- BinHexEncoding.cs
- StackBuilderSink.cs
- DataControlImageButton.cs
- XamlHttpHandlerFactory.cs
- SafeSecurityHandles.cs
- CompilerParameters.cs
- XmlSchemaObjectTable.cs
- DataGridViewAccessibleObject.cs
- DataGridPagingPage.cs
- BitConverter.cs
- NavigationWindow.cs
- SpellerHighlightLayer.cs
- SmtpNtlmAuthenticationModule.cs
- EntityClientCacheEntry.cs
- PrivateFontCollection.cs
- MessageContractAttribute.cs
- ImpersonateTokenRef.cs
- FrameDimension.cs
- Adorner.cs
- Span.cs
- Point4D.cs
- milexports.cs
- InvokeMethod.cs
- JournalEntryListConverter.cs
- typedescriptorpermissionattribute.cs
- FixedHighlight.cs
- PenLineCapValidation.cs
- StyleCollectionEditor.cs
- Expression.cs
- Attributes.cs
- InkCollectionBehavior.cs
- TextRange.cs
- TrackingMemoryStream.cs
- ResourcesChangeInfo.cs
- UserPersonalizationStateInfo.cs
- activationcontext.cs
- Catch.cs
- EntityExpressionVisitor.cs
- XmlLanguage.cs
- TimeManager.cs
- AppDomainManager.cs
- RtType.cs
- DrawingContext.cs
- HtmlToClrEventProxy.cs
- WsdlInspector.cs
- SyndicationItem.cs
- BoolLiteral.cs
- FactoryGenerator.cs
- InputReportEventArgs.cs
- Invariant.cs
- LineBreakRecord.cs
- Quaternion.cs
- StringFreezingAttribute.cs
- WindowsListViewItem.cs
- ConstraintEnumerator.cs
- SharedStatics.cs
- BamlVersionHeader.cs
- SoapAttributeOverrides.cs
- QueryComponents.cs
- StandardBindingElement.cs
- IdentityHolder.cs
- Section.cs
- AtomicFile.cs
- InputLangChangeEvent.cs
- WebDisplayNameAttribute.cs
- EntityDataSourceColumn.cs
- MainMenu.cs
- MessagePropertyFilter.cs
- Pens.cs
- HttpRequest.cs
- sqlstateclientmanager.cs
- BitmapCodecInfo.cs
- SQLResource.cs
- ToolStripItemClickedEventArgs.cs
- HttpApplicationStateBase.cs
- TabControlDesigner.cs
- NativeMethods.cs
- DateTimeOffsetStorage.cs
- TypeConvertions.cs
- _FtpControlStream.cs
- WebPartDescription.cs
- GridPattern.cs
- TableLayoutColumnStyleCollection.cs
- elementinformation.cs
- SystemPens.cs
- ToolStripRendererSwitcher.cs