// -------------------------------------------------------------------------------------------------------------------- // // Copyright (c) James South. // Licensed under the Apache License, Version 2.0. // // // The image processing native binary module. // // -------------------------------------------------------------------------------------------------------------------- namespace ImageProcessor.Web.HttpModules { using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Web; using ImageProcessor.Web.Helpers; /// /// Controls the loading and unloading of any native binaries required by ImageProcessor.Web. /// public sealed class ImageProcessorNativeBinaryModule : IHttpModule { /// /// Whether the process is running in 64bit mode. Used for calling the correct dllimport method. /// private static readonly bool Is64Bit = Environment.Is64BitProcess; /// /// The object to lock against. /// private static readonly object SyncRoot = new object(); /// /// The native binaries. /// private static readonly List NativeBinaries = new List(); /// /// A value indicating whether this instance of the given entity has been disposed. /// /// if this instance has been disposed; otherwise, . /// /// If the entity is disposed, it must not be disposed a second /// time. The isDisposed field is set the first time the entity /// is disposed. If the isDisposed field is true, then the Dispose() /// method will not dispose again. This help not to prolong the entity's /// life in the Garbage Collector. /// private bool isDisposed; /// /// Disposes of the resources (other than memory) used by the module that implements /// . /// public void Dispose() { if (this.isDisposed) { return; } // Call the appropriate methods to clean up // unmanaged resources here. lock (SyncRoot) { this.FreeNativeBinaries(); } // Note disposing is done. this.isDisposed = true; } /// /// Initializes a module and prepares it to handle requests. /// /// An that provides access to /// the methods, properties, and events common to all application objects within an ASP.NET application public void Init(HttpApplication context) { } /// /// Loads any native ImageProcessor binaries. /// public void LoadNativeBinaries() { lock (SyncRoot) { this.RegisterNativeBinaries(); } } /// /// Registers any native binaries. /// /// /// Thrown when a native binary cannot be loaded. /// private void RegisterNativeBinaries() { if (NativeBinaries.Any()) { return; } string folder = Is64Bit ? "x64" : "x86"; string sourcePath = HttpContext.Current.Server.MapPath("~/bin/" + folder); Assembly assembly = Assembly.GetExecutingAssembly(); string targetBasePath = new Uri(assembly.Location).LocalPath; DirectoryInfo directoryInfo = new DirectoryInfo(sourcePath); if (directoryInfo.Exists) { foreach (FileInfo fileInfo in directoryInfo.EnumerateFiles("*.dll")) { if (fileInfo.Name.ToUpperInvariant().StartsWith("IMAGEPROCESSOR")) { IntPtr pointer; string targetPath = Path.GetFullPath(Path.Combine(targetBasePath, "..\\" + folder + "\\" + fileInfo.Name)); File.Copy(sourcePath, targetPath, true); try { // Load the binary into memory. pointer = NativeMethods.LoadLibrary(targetPath); } catch (Exception ex) { throw new ApplicationException(ex.Message); } if (pointer == IntPtr.Zero) { throw new ApplicationException("Cannot load " + fileInfo.Name); } NativeBinaries.Add(pointer); } } } } /// /// Frees the reference to the native binaries. /// private void FreeNativeBinaries() { foreach (IntPtr nativeBinary in NativeBinaries) { // According to http://stackoverflow.com/a/2445558/427899 you need to call this twice. NativeMethods.FreeLibrary(nativeBinary); NativeMethods.FreeLibrary(nativeBinary); } } } }