C# 检查.NET托管代码中的本机库
我有一个用C#编写的.NET应用程序。我的应用程序使用第三方库,第三方库使用第三方库,而第三方库又依赖于sqlceme35.dll(Microsoft SSCE)的存在。在某些情况下,对sqlceme35.dll的依赖性没有得到考虑,我们遇到过一些情况,我的软件安装在没有这个库的计算机上,应用程序在大多数功能中运行良好,但是,当我们试图调用sqlceme35.dll时,会以一种惊人的方式崩溃,并出现神秘的错误消息 尽管我们现在知道了库不存在时的效果,但我仍然希望更主动地检测库不可用的情况,并向用户提供友好的错误消息“问题出在这里,解决方案出在这里” 眼前的问题是:如何在运行时检测sqlceme35.dll库的存在C# 检查.NET托管代码中的本机库,c#,C#,我有一个用C#编写的.NET应用程序。我的应用程序使用第三方库,第三方库使用第三方库,而第三方库又依赖于sqlceme35.dll(Microsoft SSCE)的存在。在某些情况下,对sqlceme35.dll的依赖性没有得到考虑,我们遇到过一些情况,我的软件安装在没有这个库的计算机上,应用程序在大多数功能中运行良好,但是,当我们试图调用sqlceme35.dll时,会以一种惊人的方式崩溃,并出现神秘的错误消息 尽管我们现在知道了库不存在时的效果,但我仍然希望更主动地检测库不可用的情况,并向用
更大的问题是:如何在运行时检测任意.dll文件的存在,无论它是本机代码还是托管代码库?您可以检查dll可能存在的所有位置
您可以使用该函数,该函数应搜索与Windows相同的位置。我们将非托管dll嵌入程序集中,然后将其复制到正在执行的dll位置(对于web应用程序,为卷影复制bin文件夹)。这保证了为特定版本的应用程序运行正确的版本。不幸的是,根据不同应用程序的许可条款,这可能是不可行的(合法的)。在这些情况下,您最好的选择可能是使用来验证是否找到了库,但要小心加载错误的版本(另请参见:);这可能是您甚至可以解决的问题,也可能不是(对于我们来说,唯一的解决方案是嵌入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
}
}
公共静态类SybaseResourceExtractor{
公共静态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”);
}
///
///将资源提取到文件中。
///
///资源的名称。
///包含绝对路径的文件名。
静态void ExtractSybaseDependency(字符串resourceName、字符串文件名){
试一试{
var assembly=assembly.GetAssembly(typeof(AseConnection));
var executingAssembly=Assembly.GetExecutingAssembly();
filename=Path.GetDirectoryName(assembly.Location)+“\\”+文件名;
if(File.Exists(filename)){
删除(文件名);
}
如果(!File.Exists(filename)){
使用(Stream s=ExecutionGassembly.GetManifestResourceStream(resourceName)){
使用(var fs=newfilestream(文件名,FileMode.Create)){
如果(s==null){
抛出新异常(“无法获取“+resourceName”的资源流);
}
var b=新字节[s.Length];
s、 读取(b,0,b.长度);
fs.Write(b,0,b.长度);
}
}
}
}抓住{
//无所事事
}
}
一些帮助