【问题标题】:How to use native dll's in ASP.NET?如何在 ASP.NET 中使用本机 dll?
【发布时间】:2012-01-07 08:55:07
【问题描述】:

问题:

我使用 System.Data.OracleClient。

System.Data.OracleClient 需要 OracleInstantClient,它们是本机 dll。 因此,为了使用 System.Data.OracleClient,我需要安装本机 dll,或者在路径环境变量中的文件夹中。

现在,基本问题是,我没有管理员权限(公司笔记本电脑 - 公司愚蠢 - 不会改变)...
所以我既不能安装任何东西,也不能在 PATH 的文件夹中复制任何东西,也不能将文件夹添加到路径环境变量,也不能重新启动/管理 IIS 或任何其他服务...

所以作为测试,我只是将 oci.dll 和 oraociei11.dll 复制到与 WinForms .exe 相同的文件夹中。
这工作得很好。我能够毫无问题地访问 Oracle 数据库 (SELECT * FROM COUNTRIES)。

但是现在,我需要在 ASP.NET 解决方案中执行相同的查询。 问题是,ASP.NET dll 在执行时会将影子复制到临时文件夹中。

现在要将 dll 放到 webapp bin 中,
在 Global.asax 中

public class MvcApplication : System.Web.HttpApplication

我用这个覆盖了 Init:

public override void Init()
{
    int iBitNess = IntPtr.Size;
    //System.Windows.Forms.MessageBox.Show(iBitNess.ToString());
    // iBitNess = 4, so 32 bit dll's are right



    string strTargetDirectory = System.Reflection.Assembly.GetExecutingAssembly().Location;
    strTargetDirectory = typeof(DB.Abstraction.cDAL).Assembly.Location;
    strTargetDirectory = typeof(MvcApplication).Assembly.Location;
    strTargetDirectory = System.IO.Path.GetDirectoryName(strTargetDirectory);

    string strSourcePath = Server.MapPath("~/bin/dependencies/InstantClient");
    string[] astrAllFiles = System.IO.Directory.GetFiles(strSourcePath, "*.dll");

    foreach (string strSourceFile in astrAllFiles)
    {
        string strTargetFile = System.IO.Path.GetFileName(strSourceFile);
        strTargetFile = System.IO.Path.Combine(strTargetDirectory, strTargetFile);
        System.IO.File.Copy(strSourceFile, strTargetFile);
    }

    base.Init();
} // End Sub Init

为了将本机 dll 复制到所谓的正确位置。 但我仍然得到 DllNotFound 异常...

我必须在何处或如何将本机 dll 放入 ASP.NET 应用程序?

我再说一遍:我无法设置环境变量,也无法将 dll 复制到路径中的文件夹中。(这通常可以解决问题)。

正如你看到的多次出现的

strTargetDirectory =

我尝试了几种可能,但都没有奏效。

【问题讨论】:

  • 您只需要将 DLL 放入应用程序的 bin 文件夹中。为什么要在 Init() 代码中单独访问 DLL?
  • @RickNZ:应该是对的。但事实并非如此。但我现在解决了。添加解决方案。
  • @RickNZ:ShadowCopy 将 .NET dll 复制到另一个文件夹中,然后从那里执行。因此,bin 文件夹中的本机 dll 位于另一个文件夹中,不会被找到/加载。

标签: c# asp.net .net asp.net-mvc asp.net-mvc-3


【解决方案1】:

解决了。
显然,在将它们复制到目标文件夹后,仍然需要加载本机 dll。
OnInit 不正确,它用于 HTTP 模块。
我们只需要这样做一次,因此移至 Application_Start。

这是我的代码,以防有人需要:

   // Hinweis: Anweisungen zum Aktivieren des klassischen Modus von IIS6 oder IIS7 
    // finden Sie unter "http://go.microsoft.com/?LinkId=9394801".
    public class MvcApplication : System.Web.HttpApplication
    {

        [System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
        static extern IntPtr LoadLibrary(string lpFileName);

        [System.Runtime.InteropServices.DllImport("kernel32", CharSet = System.Runtime.InteropServices.CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
        static extern UIntPtr GetProcAddress(IntPtr hModule, string procName);

        [System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true)]
        [return: System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)]
        static extern bool FreeLibrary(IntPtr hModule);


        // See http://mpi4py.googlecode.com/svn/trunk/src/dynload.h
        const int RTLD_LAZY = 1; // for dlopen's flags
        const int RTLD_NOW = 2; // for dlopen's flags

        [System.Runtime.InteropServices.DllImport("libdl")]
        static extern IntPtr dlopen(string filename, int flags);

        [System.Runtime.InteropServices.DllImport("libdl")]
        static extern IntPtr dlsym(IntPtr handle, string symbol);

        [System.Runtime.InteropServices.DllImport("libdl")]
        static extern int dlclose(IntPtr handle);

        [System.Runtime.InteropServices.DllImport("libdl")]
        static extern string dlerror();


        public void LoadSharedObject(string strFileName)
        {
            IntPtr hSO = IntPtr.Zero;

            try
            {

                if (Environment.OSVersion.Platform == PlatformID.Unix)
                {
                    hSO = dlopen(strFileName, RTLD_NOW);
                }
                else
                {
                    hSO = LoadLibrary(strFileName);

                } // End if (Environment.OSVersion.Platform == PlatformID.Unix)

            } // End Try
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
            } // End Catch

            if (hSO == IntPtr.Zero)
            {
                throw new ApplicationException("Cannot open " + strFileName);
            } // End if (hExe == IntPtr.Zero)

        } // End Sub LoadSharedObject


        // http://stackoverflow.com/questions/281145/asp-net-hostingenvironment-shadowcopybinassemblies
        public void EnsureOracleDllsLoaded()
        {
            int iBitNess = IntPtr.Size * 8;

            string strTargetDirectory = System.Reflection.Assembly.GetExecutingAssembly().Location;
            strTargetDirectory = System.IO.Path.GetDirectoryName(strTargetDirectory);

            string strSourcePath = "~/bin/dependencies/InstantClient/";

            if (Environment.OSVersion.Platform == PlatformID.Unix)
            {
                strSourcePath += "Linux" + iBitNess.ToString();
            }
            else
            {
                strSourcePath += "Win" + iBitNess.ToString();
            }

            strSourcePath = Server.MapPath(strSourcePath);

            string[] astrAllFiles = System.IO.Directory.GetFiles(strSourcePath, "*.dll");


            foreach (string strSourceFile in astrAllFiles)
            {
                string strTargetFile = System.IO.Path.GetFileName(strSourceFile);
                strTargetFile = System.IO.Path.Combine(strTargetDirectory, strTargetFile);
                System.IO.File.Copy(strSourceFile, strTargetFile, true);

                //if(strTargetFile.EndsWith("orannzsbb11.dll", StringComparison.OrdinalIgnoreCase))
                if (System.Text.RegularExpressions.Regex.IsMatch(strTargetFile, @"^(.*" + RegexDirSeparator + @")?orannzsbb11\.(dll|so|dylib)$", System.Text.RegularExpressions.RegexOptions.IgnoreCase))
                    continue; // Unneeded exception thrower

                try
                {
                    LoadSharedObject(strTargetFile);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }

            } // Next strSourceFile

        } // End Sub EnsureOracleDllsLoaded


        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
        } // End Sub RegisterGlobalFilters


        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "Default", // Routenname
                "{controller}/{action}/{id}", // URL mit Parametern
                //new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameterstandardwerte
                new { controller = "Home", action = "Test", id = UrlParameter.Optional } // Parameterstandardwerte
            );

        } // End Sub RegisterRoutes


        protected void Application_Start()
        {
            EnsureOracleDllsLoaded();
            AreaRegistration.RegisterAllAreas();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
        } // End Sub Application_Start


    } // End Class MvcApplication : System.Web.HttpApplication

【讨论】:

  • RegexDirSeparator: System.Text.RegularExpressions.Regex.Escape(System.IO.Path.DirectorySeparatorChar.ToString());
猜你喜欢
  • 1970-01-01
  • 2016-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-18
  • 1970-01-01
相关资源
最近更新 更多