Reputation: 82
Could not load file or assembly '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' or one of its dependencies. The system cannot find the file specified.
I know that the acknowledged solution/hack for this Crystal Reports / .NET 4 error is the following code in the Visual Studio project's .config file.
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
Is there any other known solution? I'm told that implementing this one will not be acceptable on our system.
Upvotes: 1
Views: 898
Reputation: 32936
I would start with asking why is this not acceptable? is your application something that gets its config from some other executable, like an MMC snapin which requires addition to the mmc.exe.config or a COM+ application that is loaded by dllhost.exe and so requires dllhost.exe.config to be modified? If not I don't see why you can't modify your own applications config.
Options as I see them
it should be noted that in the blog post the author (a well respected SO member) warns:
I strongly recommend using the official approach of using app.config to set this policy.
I suggest that you read the post in full, but to avoid posting a link answer and to avoid link rot if the blog ever moves, some highlights lifted straight from the blog are included. In the post the solution that is proposed is:
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();
}
}
The post gives and example of using it:
As an example, take a simple audio player. The code below shows how this can be used to properly, at runtime, only use the “native” API if this will succeed, and fallback (or raise a nicer exception) if this will fail:
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);
}
}
Now – the warning: This approach works, but I would be very hesitant to use it in public facing production code, especially for anything other than initializing your own application. While this should work in a library, using it has a very nasty side effect: you change the runtime policy of the executing application in a way that is very hidden and non-obvious.
then it should be able to load the older component. Would this option be any more acceptable?
I don't know how far you'll get with this though :).
This might not be easy and is probably not even legal. Please check your license agreements before attempting this. Its probably not very appropriate either, but I'm just listing it as an option.
Upvotes: 3