internal void Process() { this.AddBuildProviders(true); if (this._buildProviders.Count != 0) { BuildManager.ReportDirectoryCompilationProgress(this._vdir.VirtualPathObject); this.GetBuildResultDependencies(); this.ProcessDependencies(); ArrayList[] listArray = this._nonDependentBuckets; for (int i = 0; i < listArray.Length; i++) { ICollection buildProviders = listArray[i]; if (!this.CompileNonDependentBuildProviders(buildProviders)) { break; } } if ((this._parserErrors != null) && (this._parserErrors.Count > 0)) { HttpParseException exception = new HttpParseException(this._firstException.Message, this._firstException, this._firstException.VirtualPath, this._firstException.Source, this._firstException.Line); for (int j = 1; j < this._parserErrors.Count; j++) { exception.ParserErrors.Add(this._parserErrors[j]); } throw exception; } } }
internal void Process() { AddBuildProviders(true /*retryIfDeletionHappens*/); // If there are no BuildProvider's, we're done if (_buildProviders.Count == 0) { return; } BuildManager.ReportDirectoryCompilationProgress(_vdir.VirtualPathObject); GetBuildResultDependencies(); ProcessDependencies(); foreach (ICollection buildProviders in _nonDependentBuckets) { if (!CompileNonDependentBuildProviders(buildProviders)) { break; } } // Report all parse exceptions if (_parserErrors != null && _parserErrors.Count > 0) { Debug.Assert(!_ignoreProvidersWithErrors); // Throw the first exception as inner exception along with the parse errors. HttpParseException newException = new HttpParseException(_firstException.Message, _firstException, _firstException.VirtualPath, _firstException.Source, _firstException.Line); // Add the rest of the parser errors to the exception. // The first one is already added. for (int i = 1; i < _parserErrors.Count; i++) { newException.ParserErrors.Add(_parserErrors[i]); } // rethrow the new exception throw newException; } }
internal static Assembly GetCodeDirectoryAssembly(VirtualPath virtualDir, CodeDirectoryType dirType, string assemblyName, StringSet excludedSubdirectories, bool isDirectoryAllowed) { string path = virtualDir.MapPath(); if (!isDirectoryAllowed && Directory.Exists(path)) { throw new HttpException(System.Web.SR.GetString("Bar_dir_in_precompiled_app", new object[] { virtualDir })); } bool supportLocalization = IsResourceCodeDirectoryType(dirType); string cacheKey = assemblyName; BuildResult buildResultFromCache = BuildManager.GetBuildResultFromCache(cacheKey); Assembly a = null; if ((buildResultFromCache != null) && (buildResultFromCache is BuildResultCompiledAssembly)) { if (buildResultFromCache is BuildResultMainCodeAssembly) { _mainCodeBuildResult = (BuildResultMainCodeAssembly)buildResultFromCache; } a = ((BuildResultCompiledAssembly)buildResultFromCache).ResultAssembly; if (!supportLocalization) { return(a); } if (!isDirectoryAllowed) { return(a); } BuildResultResourceAssembly assembly2 = (BuildResultResourceAssembly)buildResultFromCache; if (HashCodeCombiner.GetDirectoryHash(virtualDir) == assembly2.ResourcesDependenciesHash) { return(a); } } if (!isDirectoryAllowed) { return(null); } if ((dirType != CodeDirectoryType.LocalResources) && !StringUtil.StringStartsWithIgnoreCase(path, HttpRuntime.AppDomainAppPathInternal)) { throw new HttpException(System.Web.SR.GetString("Virtual_codedir", new object[] { virtualDir.VirtualPathString })); } if (!Directory.Exists(path)) { if (dirType != CodeDirectoryType.MainCode) { return(null); } if (!ProfileBuildProvider.HasCompilableProfile) { return(null); } } BuildManager.ReportDirectoryCompilationProgress(virtualDir); DateTime utcNow = DateTime.UtcNow; CodeDirectoryCompiler compiler = new CodeDirectoryCompiler(virtualDir, dirType, excludedSubdirectories); string outputAssemblyName = null; if (a != null) { outputAssemblyName = a.GetName().Name; compiler._onlyBuildLocalizedResources = true; } else { outputAssemblyName = BuildManager.GenerateRandomAssemblyName(assemblyName); } BuildProvidersCompiler compiler2 = new BuildProvidersCompiler(virtualDir, supportLocalization, outputAssemblyName); compiler._bpc = compiler2; compiler.FindBuildProviders(); compiler2.SetBuildProviders(compiler._buildProviders); CompilerResults results = compiler2.PerformBuild(); if (results != null) { DateTime time2 = DateTime.UtcNow.AddMilliseconds(3000.0); do { if (UnsafeNativeMethods.GetModuleHandle(results.PathToAssembly) == IntPtr.Zero) { a = results.CompiledAssembly; goto Label_01E6; } Thread.Sleep(250); }while (DateTime.UtcNow <= time2); throw new HttpException(System.Web.SR.GetString("Assembly_already_loaded", new object[] { results.PathToAssembly })); } Label_01E6: if (a == null) { return(null); } if (dirType == CodeDirectoryType.MainCode) { _mainCodeBuildResult = new BuildResultMainCodeAssembly(a); buildResultFromCache = _mainCodeBuildResult; } else if (supportLocalization) { buildResultFromCache = new BuildResultResourceAssembly(a); } else { buildResultFromCache = new BuildResultCompiledAssembly(a); } buildResultFromCache.VirtualPath = virtualDir; if (BuildManager.OptimizeCompilations && (dirType != CodeDirectoryType.LocalResources)) { buildResultFromCache.AddVirtualPathDependencies(new SingleObjectCollection(virtualDir.AppRelativeVirtualPathString)); } if (dirType != CodeDirectoryType.LocalResources) { buildResultFromCache.CacheToMemory = false; } BuildManager.CacheBuildResult(cacheKey, buildResultFromCache, utcNow); return(a); }
internal static Assembly GetCodeDirectoryAssembly(VirtualPath virtualDir, CodeDirectoryType dirType, string assemblyName, StringSet excludedSubdirectories, bool isDirectoryAllowed) { string physicalDir = virtualDir.MapPath(); if (!isDirectoryAllowed) { // The directory should never exist in a precompiled app if (Directory.Exists(physicalDir)) { throw new HttpException(SR.GetString(SR.Bar_dir_in_precompiled_app, virtualDir)); } } bool supportLocalization = IsResourceCodeDirectoryType(dirType); // Determine the proper cache key based on the type of directory we're processing string cacheKey = assemblyName; // Try the cache first BuildResult result = BuildManager.GetBuildResultFromCache(cacheKey); Assembly resultAssembly = null; // If it's cached, just return it if (result != null) { // It should always be a BuildResultCompiledAssembly, though if there is // a VirtualPathProvider doing very bad things, it may not (VSWhidbey 341701) Debug.Assert(result is BuildResultCompiledAssembly); if (result is BuildResultCompiledAssembly) { // If it's the main code assembly, keep track of it so we can later call // the AppInitialize method if (result is BuildResultMainCodeAssembly) { Debug.Assert(dirType == CodeDirectoryType.MainCode); Debug.Assert(_mainCodeBuildResult == null); _mainCodeBuildResult = (BuildResultMainCodeAssembly)result; } resultAssembly = ((BuildResultCompiledAssembly)result).ResultAssembly; if (!supportLocalization) { return(resultAssembly); } // We found a preserved resource assembly. However, we may not be done, // as the culture specific files may have changed. // But don't make any further checks if the directory is not allowed (precomp secenario). // In that case, we should always return the assembly (VSWhidbey 533498) if (!isDirectoryAllowed) { return(resultAssembly); } BuildResultResourceAssembly buildResultResAssembly = (BuildResultResourceAssembly)result; string newResourcesDependenciesHash = HashCodeCombiner.GetDirectoryHash(virtualDir); // If the resources hash (which includes satellites) is up to date, we're done if (newResourcesDependenciesHash == buildResultResAssembly.ResourcesDependenciesHash) { return(resultAssembly); } } } // If app was precompiled, don't attempt compilation if (!isDirectoryAllowed) { return(null); } // Check whether the virtual dir is mapped to a different application, // which we don't support (VSWhidbey 218603). But don't do this for LocalResource (VSWhidbey 237935) if (dirType != CodeDirectoryType.LocalResources && !StringUtil.StringStartsWithIgnoreCase(physicalDir, HttpRuntime.AppDomainAppPathInternal)) { throw new HttpException(SR.GetString(SR.Virtual_codedir, virtualDir.VirtualPathString)); } // If the directory doesn't exist, we may be done if (!Directory.Exists(physicalDir)) { // We're definitely done if it's not the main code dir if (dirType != CodeDirectoryType.MainCode) { return(null); } // If it is the main code dir, we're only done is there is no profile to compile // since the profice gets built as part of the main assembly. if (!ProfileBuildProvider.HasCompilableProfile) { return(null); } } // Otherwise, compile it BuildManager.ReportDirectoryCompilationProgress(virtualDir); DateTime utcStart = DateTime.UtcNow; CodeDirectoryCompiler cdc = new CodeDirectoryCompiler(virtualDir, dirType, excludedSubdirectories); string outputAssemblyName = null; if (resultAssembly != null) { // If resultAssembly is not null, we are in the case where we just need to build // the localized resx file in a resources dir (local or global) Debug.Assert(supportLocalization); outputAssemblyName = resultAssembly.GetName().Name; cdc._onlyBuildLocalizedResources = true; } else { outputAssemblyName = BuildManager.GenerateRandomAssemblyName(assemblyName); } BuildProvidersCompiler bpc = new BuildProvidersCompiler(virtualDir, supportLocalization, outputAssemblyName); cdc._bpc = bpc; // Find all the build provider we want to compile from the code directory cdc.FindBuildProviders(); // Give them to the BuildProvidersCompiler bpc.SetBuildProviders(cdc._buildProviders); // Compile them into an assembly CompilerResults results = bpc.PerformBuild(); // Did we just compile something? if (results != null) { Debug.Assert(result == null); Debug.Assert(resultAssembly == null); // If there is already a loaded module with the same path, try to wait for it to be unloaded. // Otherwise, we would end up loading this old assembly instead of the new one (VSWhidbey 554697) DateTime waitLimit = DateTime.UtcNow.AddMilliseconds(3000); for (;;) { IntPtr hModule = UnsafeNativeMethods.GetModuleHandle(results.PathToAssembly); if (hModule == IntPtr.Zero) { break; } Debug.Trace("CodeDirectoryCompiler", results.PathToAssembly + " is already loaded. Waiting a bit"); System.Threading.Thread.Sleep(250); // Stop trying if the timeout was reached if (DateTime.UtcNow > waitLimit) { Debug.Trace("CodeDirectoryCompiler", "Timeout waiting for old assembly to unload: " + results.PathToAssembly); throw new HttpException(SR.GetString(SR.Assembly_already_loaded, results.PathToAssembly)); } } resultAssembly = results.CompiledAssembly; } // It is possible that there was nothing to compile (and we're not in the // satellite resources case) if (resultAssembly == null) { return(null); } // For the main code directory, use a special BuildResult that takes care of // calling AppInitialize if it finds one if (dirType == CodeDirectoryType.MainCode) { // Keep track of it so we can later call the AppInitialize method _mainCodeBuildResult = new BuildResultMainCodeAssembly(resultAssembly); result = _mainCodeBuildResult; } else if (supportLocalization) { result = new BuildResultResourceAssembly(resultAssembly); } else { result = new BuildResultCompiledAssembly(resultAssembly); } result.VirtualPath = virtualDir; // If compilations are optimized, we need to include the right dependencies, since we can no longer // rely on everything getting wiped out when something in App_Code changes. // But don't do this for local resources, since they have their own special way of // dealing with dependencies (in BuildResultResourceAssembly.ComputeSourceDependenciesHashCode). // It's crucial *not* to do it as it triggers a tricky infinite recursion due to the fact // that GetBuildResultFromCacheInternal calls EnsureFirstTimeDirectoryInitForDependencies if // there is at least one dependency if (BuildManager.OptimizeCompilations && dirType != CodeDirectoryType.LocalResources) { result.AddVirtualPathDependencies(new SingleObjectCollection(virtualDir.AppRelativeVirtualPathString)); } // Top level assembly should not be cached to memory. But LocalResources are *not* // top level files, and do benefit from memory caching if (dirType != CodeDirectoryType.LocalResources) { result.CacheToMemory = false; } // Cache it for next time BuildManager.CacheBuildResult(cacheKey, result, utcStart); return(resultAssembly); }