【问题标题】:Check for native library in .NET managed code检查 .NET 托管代码中的本机库
【发布时间】:2010-06-22 18:44:20
【问题描述】:

我有一个用 C# 编写的 .NET 应用程序。我的应用程序使用 3rd 方库,它使用 3rd 方库,而后者又依赖于 sqlceme35.dll (Microsoft SSCE) 的存在。在某个地方,对 sqlceme35.dll 的依赖没有被考虑在内,我们遇到过很多情况,我的软件安装在没有这个库的计算机上,应用程序似乎对大多数功能运行良好,但崩溃了当我们尝试调用 sqlceme35.dll 时,以一种带有神秘错误消息的壮观方式。

即使我们现在知道库不存在时的效果如何,我仍然希望更积极主动地检测库何时不可用并向用户提供友好的错误消息“这就是问题所在,这是解决方案”。

直接的问题是:如何在运行时检测 sqlceme35.dll 库的存在?

更大的问题是:如何在运行时检测任意 .dll 文件的存在,无论是本机代码还是托管代码库?

【问题讨论】:

标签: c#


【解决方案1】:

您可以使用PInvoke 来使用LoadLibrary 函数,该函数应该搜索与Windows 相同的位置。

【讨论】:

    【解决方案2】:

    我们将非托管 dll 嵌入到程序集中,然后将它们复制到正在执行的 dll 位置(对于 Web 应用程序,复制 bin 文件夹)。这保证为我们的应用程序的特定版本运行正确的版本。不幸的是,这可能不可行(合法),具体取决于您的各种应用程序的许可条款。在这些情况下,您最好的选择可能是使用LoadLibrary 来验证是否找到了库,但要注意加载错误的版本(另请参见:DLL hell);这可能是也可能不是您甚至可以解决的问题(对我们来说,唯一的解决方案是嵌入 dll 并在需要时从程序集中提取它们)。

    这是我们的 Sybase ASE ADO 驱动程序代码:

    public static class SybaseResourceExtractor {
        public static void ExtractSybaseDependencies() {
            ExtractSybaseDependency("QueryLibrary.Unmanaged.sybdrvado20.dll", "sybdrvado20.dll");
            ExtractSybaseDependency("QueryLibrary.Unmanaged.msvcr80.dll", "msvcr80.dll");
            ExtractSybaseDependency("QueryLibrary.Unmanaged.sybcsi_certicom_fips26.dll", "sybcsi_certicom_fips26.dll");
            ExtractSybaseDependency("QueryLibrary.Unmanaged.sybcsi_core26.dll", "sybcsi_core26.dll");
            ExtractSybaseDependency("QueryLibrary.Unmanaged.sbgse2.dll", "sbgse2.dll");
        }
    
        /// <summary>
        /// Extracts a resource to a file.
        /// </summary>
        /// <param name="resourceName">Name of the resource.</param>
        /// <param name="filename">The filename including absolute path.</param>
        static void ExtractSybaseDependency(string resourceName, string filename) {
            try {
                var assembly = Assembly.GetAssembly(typeof(AseConnection));
                var executingAssembly = Assembly.GetExecutingAssembly();
                filename = Path.GetDirectoryName(assembly.Location) + "\\" + filename;
    
                if (File.Exists(filename)) {
                    File.Delete(filename);    
                }
    
                if (!File.Exists(filename)) {
                    using (Stream s = executingAssembly.GetManifestResourceStream(resourceName)) {
                        using (var fs = new FileStream(filename, FileMode.Create)) {
                            if (s == null) {
                                throw new Exception("Failed to get resource stream for " + resourceName);
                            }
    
                            var b = new byte[s.Length];
                            s.Read(b, 0, b.Length);
                            fs.Write(b, 0, b.Length);
                        }
                    }
                }
            } catch {
                //Doing nothing
            }
        }
    

    【讨论】:

      【解决方案3】:

      您可以检查 dll 可能存在的所有位置。

      http://msdn.microsoft.com/en-us/library/ms682586(VS.85).aspx

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-25
        • 2023-04-01
        • 1970-01-01
        相关资源
        最近更新 更多