在 .NET 中编译与版本无关的 DLL [英] Compile a version agnostic DLL in .NET

查看:20
本文介绍了在 .NET 中编译与版本无关的 DLL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个围绕 Microsoft Office 的包装器,一个用于 2003 年,一个用于 2007 年.由于同时运行两个版本的 Microsoft Office 是官方不可能的",也不推荐 Microsoft,我们有两个盒子,一个用于 Office 2003另一个使用Office 2007.我们分别编译包装器.DLL 包含在我们的解决方案中,每个框都有 相同 检出,但 Office 2003 或 2007 已卸载",因此它不会尝试编译该特定 DLL.由于 Office COM DLL 不可用,否则将在编译时引发错误.

I have two wrappers around Microsoft Office, one for 2003 and one for 2007. Since having two versions of Microsoft Office running side by side is "not officially possible" nor recommended by Microsoft, we have two boxes, one with Office 2003 and the other with Office 2007. We compile the wrappers separately. The DLLs are included in our solution, each box has the same checkout but with either Office 2003 or 2007 "unloaded" so it doesn't attempt to compile that particular DLL. Failure to do that will throw errors on compilation due to the Office COM DLLs not available.

我们使用 .NET 2.0 和 Visual Studio 2008.

We use .NET 2.0 and Visual Studio 2008.

由于微软在 2007 年神秘地更改了 Office 2003 API,重命名和更改了一些方法(sigh)从而使它们不向后兼容,我们需要这两个包装器.我们为每台构建机器配备了解决方案并激活了一个 Office DLL.例如:装有 Office 2003 的机器已卸载Office 2007"DLL,因此未对其进行编译.另一个盒子是相同的想法,但相反.所有这一切都是因为出于编程目的,我们不能在同一个盒子中放置 2 个不同的 Office.(根据 Microsoft 的说法,您在技术上可以将两个 Office 放在一起)但不是用于编程,也不是没有问题.

Since Microsoft mysteriously changed the Office 2003 API in 2007, renaming and changing some methods (sigh) thus making them not backwards compatible, we need the two wrappers. We have each build machine with the solution and one Office DLL activated. E.g.: the machine with Office 2003 has the "Office 2007" DLL unloaded, therefore not compiling it. The other box is the same idea but the other way around. All this because we can't have 2 different Office in the same box for programming purposes. (you could technically have two Office together according to Microsoft) but not for programming and not without some issues.

当我们更改应用程序版本(例如从 1.5.0.1 到 1.5.0.2)时,我们需要重新编译 DLL 以匹配应用程序的新版本,这是自动完成的,因为解决方案中包含 Office 包装器.由于包装器包含在解决方案中,它们继承了 APP 版本,但我们必须执行两次,然后将另一个 DLL复制"到创建安装程序的机器上.(痛……)

When we change the Application Version (from 1.5.0.1 to 1.5.0.2 for example) we need to recompile the DLL to match the new version of the application, this is automatically done, because the Office wrapper is included in the solution. Since the wrappers are contained in the solution, those inherit the APP Version, but we have to do it twice and then "copy" the other DLL to the machine that creates the installer. (A Pain…)

是否可以编译一个可以与任何版本的应用程序一起使用的 DLL,尽管它较旧"?我读过一些关于清单的东西,但我从来没有与它们互动过.任何指针将不胜感激.

Is it possible to compile a DLL that will work with any version of the application, despite being "older"? I've read something about manifests but I have never had to interact with those. Any pointers will be appreciated.

这样做的秘密原因是我们在时代"没有改变我们的包装器,微软也没有改变他们古老的 API,但我们正在重新编译 DLL 以匹配 每个的应用程序版本我们发布.我想自动化这个过程,而不必依赖两台机器.

The secret reason for this is that we haven't changed our wrappers in "ages" and neither did Microsoft with their ancient APIs, yet we are recompiling the DLL to match the app version on every release we make. I'd like to automate this process instead of having to rely on two machines.

我无法从项目中删除 DLL(两者都没有),因为存在依赖关系.

I can't remove the DLL from the project (neither of them) because there are dependencies.

我可以创建第三个主包装器",但还没有考虑过.

I could create a third "master wrapper" but haven't thought about it yet.

有什么想法吗?还有人有同样的要求吗?

Any ideas? Anyone else with the same requirement?

澄清:

我有 N 个项目的 1 个解决方案.

I have 1 solution with N projects.

应用程序"+ Office11Wrapper.dll + Office12Wrapper.dll.

"Application" + Office11Wrapper.dll + Office12Wrapper.dll.

两个包装器"都使用应用程序和解决方案中的其他库(数据层、业务层、框架等)的依赖项

Both "wrappers" use dependencies for application + other libraries in the solution (datalayer, businesslayer, framework, etc.)

每个包装器都有对各自 Office 包(2003 和 2007)的引用.

Each wrapper has references for the respective Office package (2003 and 2007).

如果我编译但没有安装 office 12,我会收到来自 Office12Wrapper.dll 的错误,找不到 Office 2007 库.所以我有两台构建机器,一台装有 Office 2003,一台装有 Office 2007.在每台机器上进行完整的 SVN 更新 + 编译后,我们只需在安装程序"中使用 office12.dll 来针对相同代码,相同版本".

If I compile and don't have office 12 installed, I get errors from Office12Wrapper.dll not finding the Office 2007 libraries. So what I have are two building machines, one with Office 2003, one with Office 2007. After a full SVN update + compile on each machine, we simply use office12.dll in the "installer" to have the wrapper compiled against the "same code, same version".

注意:Office 2007 Build Machine 具有卸载"Office 2003 的 Wrapper,反之亦然.

Note: The Office 2007 Build Machine, has the Wrapper for Office 2003 "unloaded" and viceversa.

提前致谢.

推荐答案

当 .NET 程序集解析器无法在运行时找到引用的程序集时(在这种情况下,它无法找到应用程序链接的特定包装 DLL 版本),它的默认行为是失败并基本上使应用程序崩溃.但是,可以通过挂钩 AppDomain.AssemblyResolve 事件来覆盖此行为.只要找不到引用的程序集,就会触发此事件,它使您有机会替换另一个程序集来代替丢失的程序集(前提是它们兼容).因此,例如,您可以替换自己加载的旧版本包装器 DLL.

When the .NET assembly resolver is unable to find a referenced assembly at runtime (in this case, it cannot find the particular wrapper DLL version the application was linked against), its default behavior is to fail and essentially crash the application. However, this behavior can be overridden by hooking the AppDomain.AssemblyResolve event. This event is fired whenever a referenced assembly cannot be found, and it gives you the opportunity to substitute another assembly in place of the missing one (provided that they are compatible). So, for instance, you could substitute an older version of the wrapper DLL that you load yourself.

我发现最好的方法是在挂钩事件的应用程序的主类上添加一个静态构造函数,例如:

The best way I've found to do this is to add a static constructor on the main class of the application that hooks the event, e.g.:

using System.Reflection;

static Program()
{
    AppDomain.CurrentDomain.AssemblyResolve += delegate(object sender, ResolveEventArgs e)
    {
        AssemblyName requestedName = new AssemblyName(e.Name);

        if (requestedName.Name == "Office11Wrapper")
        {
            // Put code here to load whatever version of the assembly you actually have

            return Assembly.LoadFile("Office11Wrapper.DLL");
        }
        else
        {
            return null;
        }
    }
}

通过将它放在主应用程序类的静态构造函数中,它可以保证在任何代码尝试访问包装器 DLL 中的任何内容之前运行,确保钩子提前到位.

By putting this in a static constructor of the main application class, it is guaranteed to run before any code attempts to access anything in the wrapper DLL, ensuring that the hook is in place ahead of time.

您也可以使用策略文件来进行版本重定向,但这往往更复杂.

You can also use policy files to do version redirection, but that tends to be more complex.

这篇关于在 .NET 中编译与版本无关的 DLL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆