;;EXPORT ;;(install-assembly-resolver) ;;(assembly-path! "C:/path/to/assemblies1" ...) ;;automatically uninstalls previous assembly resolver when ;;calling (install-assembly-resolver) ;;FIXES bug in which assembly-name is passed to assembly-resolver ;;in fullname, thus the function attempts to find wrong dll name. (in-package :rdnzl-user) ;;; Adds additional paths to the search-path used by the ;;; assembly-loader; so that e.g. (load-assembly x) will search for x ;;; not only in the system and application directories, but also in ;;; every directory in *additional-assembly-directories* ;;; ;;; Example: ;;; RDNZL-USER 3 > (load-assembly "AproposGui") ;;; Warning: Returning NULL object from .NET call ;;, NIL ;;; RDNZL-USER 4 > (pushnew (translate-logical-pathname #P"rdnzl:examples;") ;;; *additional-assembly-directories*) ;;; RDNZL-USER 5 > (install-assembly-resolver) ;;; # ;;; RDNZL-USER 6 > (load-assembly "AproposGui") ;;; # ;;; ;;; Alternative method of loading an assembly that doesn't lock the ;;; assembly file: ;;; byte[] asm = File.ReadAllBytes(asmPath); ;;; return Assembly.Load(asm); (defparameter *additional-assembly-directories* nil) (defun assembly-path! (&rest args) (loop for arg in args do(pushnew arg *additional-assembly-directories* :test #'equal)) *additional-assembly-directories*) (defun assembly-resolver (app-domain resolve-event-args) (declare (ignore app-domain)) (let ((assembly-name (property resolve-event-args "Name"))) (loop with parsed-name = (let ((comma-pos (position #\, assembly-name))) (if comma-pos (subseq assembly-name 0 comma-pos) assembly-name)) with filename = (make-pathname :name parsed-name :type "dll") for dir in *additional-assembly-directories* for dirpath = (if (pathnamep dir) dir (parse-namestring dir)) for path = (merge-pathnames dirpath filename) when (probe-file path) do (let* ((evidence (property (invoke "System.Reflection.Assembly" "GetExecutingAssembly") "Evidence")) (assembly (invoke "System.Reflection.Assembly" "LoadFile" (namestring path) evidence))) (return-from assembly-resolver assembly)) finally (return (make-null-object "System.Reflection.Assembly"))))) (defvar *assembly-resolve-handler* nil) (defun install-assembly-resolver (&optional (handler #'assembly-resolver)) (let ((my-domain (property "System.AppDomain" "CurrentDomain")) (assembly-resolve-delegate (new "System.ResolveEventHandler" handler))) (when *assembly-resolve-handler* (uninstall-assembly-resolve-handler *assembly-resolve-handler*) (setf *assembly-resolve-delegate* assembly-resolve-delegate)) (prog1 assembly-resolve-delegate (invoke my-domain "add_AssemblyResolve" assembly-resolve-delegate)))) (defun uninstall-assembly-resolve-handler (handler) (invoke (property "System.AppDomain" "CurrentDomain") "remove_AssemblyResolve" handler) (setf *assembly-resolve-handler* nil))