diff --git a/build/NuSpecs/ImageProcessor.nuspec b/build/NuSpecs/ImageProcessor.nuspec
index 557d85150..f12daba8f 100644
--- a/build/NuSpecs/ImageProcessor.nuspec
+++ b/build/NuSpecs/ImageProcessor.nuspec
@@ -25,8 +25,8 @@ Feedback is always welcome.
-
-
+
+
\ No newline at end of file
diff --git a/build/content/ImageProcessor.Web/web.config.transform b/build/content/ImageProcessor.Web/web.config.transform
index 7d02ee462..5c3edb967 100644
--- a/build/content/ImageProcessor.Web/web.config.transform
+++ b/build/content/ImageProcessor.Web/web.config.transform
@@ -3,6 +3,7 @@
+
@@ -13,6 +14,7 @@
+
\ No newline at end of file
diff --git a/src/ImageProcessor.Web/NET4/ImageProcessor.Web_NET4.csproj b/src/ImageProcessor.Web/NET4/ImageProcessor.Web_NET4.csproj
index 82d3986a7..12c43700b 100644
--- a/src/ImageProcessor.Web/NET4/ImageProcessor.Web_NET4.csproj
+++ b/src/ImageProcessor.Web/NET4/ImageProcessor.Web_NET4.csproj
@@ -116,6 +116,9 @@
+
+ ImageProcessorNativeBinaryModule.cs
+
Alpha.cs
diff --git a/src/ImageProcessor.Web/NET45/Configuration/ImageProcessorConfiguration.cs b/src/ImageProcessor.Web/NET45/Configuration/ImageProcessorConfiguration.cs
index 9d3ea6be9..95c3123e2 100644
--- a/src/ImageProcessor.Web/NET45/Configuration/ImageProcessorConfiguration.cs
+++ b/src/ImageProcessor.Web/NET45/Configuration/ImageProcessorConfiguration.cs
@@ -23,6 +23,7 @@ namespace ImageProcessor.Web.Configuration
using ImageProcessor.Common.Extensions;
using ImageProcessor.Processors;
using ImageProcessor.Web.Helpers;
+ using ImageProcessor.Web.HttpModules;
using ImageProcessor.Web.Processors;
///
@@ -370,30 +371,14 @@ namespace ImageProcessor.Web.Configuration
///
private void EnsureNativeBinariesLoaded()
{
- string binary = Is64Bit ? "libwebp64.dll" : "libwebp32.dll";
- string sourcePath = HttpContext.Current.Server.MapPath("~/bin");
- string targetPath = new Uri(Assembly.GetExecutingAssembly().Location).LocalPath;
- IntPtr pointer = IntPtr.Zero;
+ // Load the correct method from the native binary module.
+ // We do it here as on init will cause an UnauthorizedAccessException.
+ HttpModuleCollection modules = HttpContext.Current.ApplicationInstance.Modules;
+ ImageProcessorNativeBinaryModule nativeBinaryModule = modules.Get("ImageProcessorNativeBinaryModule") as ImageProcessorNativeBinaryModule;
- // Shadow copy the native binaries.
- sourcePath = Path.Combine(sourcePath, binary);
- targetPath = Path.GetFullPath(Path.Combine(targetPath, "..\\" + binary));
-
- File.Copy(sourcePath, targetPath, true);
-
- try
- {
- // Load the binary into memory.
- pointer = NativeMethods.LoadLibrary(targetPath);
- }
- catch (Exception ex)
- {
- Debug.WriteLine(ex.Message);
- }
-
- if (pointer == IntPtr.Zero)
+ if (nativeBinaryModule != null)
{
- throw new ApplicationException("Cannot open " + binary);
+ nativeBinaryModule.LoadNativeBinaries();
}
}
#endregion
diff --git a/src/ImageProcessor.Web/NET45/HttpModules/ImageProcessorNativeBinaryModule.cs b/src/ImageProcessor.Web/NET45/HttpModules/ImageProcessorNativeBinaryModule.cs
new file mode 100644
index 000000000..87120a77b
--- /dev/null
+++ b/src/ImageProcessor.Web/NET45/HttpModules/ImageProcessorNativeBinaryModule.cs
@@ -0,0 +1,159 @@
+// --------------------------------------------------------------------------------------------------------------------
+//
+// 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);
+ string targetBasePath = new Uri(Assembly.GetExecutingAssembly().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);
+ }
+ }
+ }
+}
diff --git a/src/ImageProcessor.Web/NET45/ImageProcessor.Web_NET45.csproj b/src/ImageProcessor.Web/NET45/ImageProcessor.Web_NET45.csproj
index 40bd16bc7..47bd96a17 100644
--- a/src/ImageProcessor.Web/NET45/ImageProcessor.Web_NET45.csproj
+++ b/src/ImageProcessor.Web/NET45/ImageProcessor.Web_NET45.csproj
@@ -62,6 +62,7 @@
+
diff --git a/src/ImageProcessor.sln.DotSettings b/src/ImageProcessor.sln.DotSettings
index 94cb9dbcb..4970d0c6c 100644
--- a/src/ImageProcessor.sln.DotSettings
+++ b/src/ImageProcessor.sln.DotSettings
@@ -1,4 +1,5 @@
+ BGRA
BPP
DT
FPX
diff --git a/src/ImageProcessor/ImageProcessor.csproj b/src/ImageProcessor/ImageProcessor.csproj
index 0e0d276bb..73ac24ef7 100644
--- a/src/ImageProcessor/ImageProcessor.csproj
+++ b/src/ImageProcessor/ImageProcessor.csproj
@@ -130,13 +130,14 @@
-
+
PreserveNewest
-
+
PreserveNewest
+