【问题标题】:Any other solution for .NET 4 / Crystal Reports issue?.NET 4 / Crystal Reports 问题的任何其他解决方案?
【发布时间】:2014-07-16 15:56:23
【问题描述】:

无法加载文件或程序集 'file:///C:\Program Files\SAP BusinessObjects\Crystal Reports for .NET Framework 4.0\Common\SAP BusinessObjects Enterprise XI 4.0\win32_x86\dotnet1\crdb_adoplus.dll' 或其依赖项之一。系统找不到指定的文件。

我知道这个 Crystal Reports / .NET 4 错误的公认解决方案/hack 是 Visual Studio 项目的 .config 文件中的以下代码。

<startup useLegacyV2RuntimeActivationPolicy="true">
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>

还有其他已知的解决方案吗?有人告诉我,在我们的系统上实施这个是不可接受的。

【问题讨论】:

    标签: .net visual-studio crystal-reports


    【解决方案1】:

    我首先要问为什么这是不可接受的?您的应用程序是从其他一些可执行文件获取其配置的东西,例如需要添加到 mmc.exe.config 的 MMC 管理单元或由 dllhost.exe 加载的 COM+ 应用程序,因此需要修改 dllhost.exe.config?如果不是,我不明白为什么您不能修改自己的应用程序配置。

    我看到的选项

    1.您也许可以按照this blog post 中所述以编程方式设置它

    需要注意的是,作者 (a well respected SO member) 在博文中警告:

    我强烈建议使用官方的方式使用 app.config 来设置这个策略。

    我建议您完整阅读这篇文章,但为了避免发布链接答案并避免在博客移动时链接失效,我们会直接从博客中提取一些亮点。在帖子中提出的解决方案是:

    public static class RuntimePolicyHelper
    {
        public static bool LegacyV2RuntimeEnabledSuccessfully { get; private set; }
    
        static RuntimePolicyHelper()
        {
            ICLRRuntimeInfo clrRuntimeInfo =
                (ICLRRuntimeInfo)RuntimeEnvironment.GetRuntimeInterfaceAsObject(
                    Guid.Empty, 
                    typeof(ICLRRuntimeInfo).GUID);
            try
            {
                clrRuntimeInfo.BindAsLegacyV2Runtime();
                LegacyV2RuntimeEnabledSuccessfully = true;
            }
            catch (COMException)
            {
                // This occurs with an HRESULT meaning 
                // "A different runtime was already bound to the legacy CLR version 2 activation policy."
                LegacyV2RuntimeEnabledSuccessfully = false;
            }
        }
    
        [ComImport]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        [Guid("BD39D1D2-BA2F-486A-89B0-B4B0CB466891")]
        private interface ICLRRuntimeInfo
        {
            void xGetVersionString();
            void xGetRuntimeDirectory();
            void xIsLoaded();
            void xIsLoadable();
            void xLoadErrorString();
            void xLoadLibrary();
            void xGetProcAddress();
            void xGetInterface();
            void xSetDefaultStartupFlags();
            void xGetDefaultStartupFlags();
    
            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void BindAsLegacyV2Runtime();
        }
    }
    

    这篇文章给出了使用它的例子:

    以一个简单的音频播放器为例。下面的代码显示了如何 这可以用于在运行时正确地使用“本机”API,如果 这将成功,如果失败则回退(或引发更好的异常):

    public class AudioPlayer
    {
        private IAudioEngine audioEngine;
    
        public AudioPlayer()
        {
            if (RuntimePolicyHelper.LegacyV2RuntimeEnabledSuccessfully)
            {
                // This will load a CLR 2 mixed mode assembly
                this.audioEngine = new AudioEngineNative();
            }
            else
            {
                this.audioEngine = new AudioEngineManaged();
            }
        }
    
        public void Play(string filename)
        {
            this.audioEngine.Play(filename);
        }
    }
    

    现在 - 警告:这种方法有效,但我会很犹豫 在面向公众的生产代码中使用它,尤其是对于任何东西 除了初始化您自己的应用程序。虽然这应该有效 在图书馆中,使用它有一个非常讨厌的副作用:你改变了 执行应用程序的运行时策略 隐藏且不明显。

    2。您也许还可以针对 .net v2 编译您的应用程序

    那么它应该能够加载旧组件。这个选项会更可接受吗?

    3。获取您尝试加载的组件的更新版本。

    不过,我不知道你能走多远 :)。

    4。尝试在组件上使用反编译器,然后针对较新版本的框架重新编译。

    这可能并不容易,甚至可能不合法。在尝试此操作之前,请检查您的许可协议。它可能也不是很合适,但我只是将其列为一个选项。

    【讨论】:

    • 显然不能轻易跳入,但至少这是我可以与决策者讨论的替代方案,因此它满足了我提出的问题。在我等着看他们是否真的会让我接受测试时,不要让答案无法识别。
    • @LeonardWilson 是的,没有一个选项那么好。按照预期使用 app.config 是最好的选择:)。
    猜你喜欢
    • 2015-10-25
    • 2020-02-08
    • 1970-01-01
    • 2011-03-14
    • 1970-01-01
    • 1970-01-01
    • 2011-02-07
    • 2020-07-01
    • 1970-01-01
    相关资源
    最近更新 更多