Не удалось загрузить файл или сборку - PullRequest
4 голосов
/ 27 июля 2011

У меня есть простой исполняемый файл, в котором я хотел бы использовать DLL. Я добавил его в качестве ссылки.Я создал файл app.config, потому что DLL в конечном итоге не будет находиться в каталоге исполняемых файлов.Если я выполняю свою программу из IDE, все в порядке, b / c dll копируется локально, но как только я вытаскиваю свой исполняемый файл, происходит сбой.Мой журнал слияния подразумевает, что он не может найти указанный файл.

Мой метод Main ():

AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);

Assembly assembly = null;
String dllLocation = @"C:\BMS_ACTD\bin\DX\Tools\BmsReplayAnalysis.dll";
IToolsInterface myProgram = null; //from ToolsInterface.dll
try
{
    assembly = Assembly.LoadFrom(dllLocation);
}
catch
{
}

foreach (Type myType in assembly.GetTypes())
{
    if (myType.GetInterface(typeof(IToolsInterface).FullName) != null)
    {
        myProgram = (IToolsInterface)assembly.CreateInstance(myType.Namespace + "." + myType.Name, true);
        myProgram.RunTool();
        break;
    }
}

Вот мой конфигурационный файл:

<runtime>
    <dependentAssembly>
        <assemblyIdentity name="ToolsInterface" publicKeyToken="null" culture="neutral" />
        <codeBase version="1.0.0.0" href="file://C:/BMS_ACTD/bin/DX/Globals/ToolsInterface.dll"/>
    </dependentAssembly>
</runtime>

Iне хочу беспокоиться о сильных именах.У меня будет только 1 версия этого dll, и это все, что меня волнует.

Вот выдержка из журнала fusionlog:

The operation failed.
Bind result: hr = 0x80070002. The system cannot find the file specified.

Assembly manager loaded from:  C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Running under executable  C:\Users\greenj\Desktop\BmsReplayLauncher.exe
--- A detailed error log follows. 

=== Pre-bind state information ===
LOG: User = BMS-JMGREEN\greenj
LOG: DisplayName = ToolsInterface, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
 (Fully-specified)
LOG: Appbase = file:///C:/Users/greenj/Desktop/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = BmsReplayLauncher.exe
Calling assembly : BmsReplayLauncher, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\Users\greenj\Desktop\BmsReplayLauncher.exe.Config
LOG: Using host configuration file: 
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file:///C:/Users/greenj/Desktop/ToolsInterface.DLL.
LOG: Attempting download of new URL file:///C:/Users/greenj/Desktop/ToolsInterface/ToolsInterface.DLL.
LOG: Attempting download of new URL file:///C:/Users/greenj/Desktop/ToolsInterface.EXE.
LOG: Attempting download of new URL file:///C:/Users/greenj/Desktop/ToolsInterface/ToolsInterface.EXE.
LOG: All probing URLs attempted and failed.

Ответы [ 2 ]

2 голосов
/ 27 июля 2011

Вещи всегда становятся сложными с .net, если вы пытаетесь загрузить из папки, которая не находится в папке или подпапках, где находится EXE-файл вашего приложения. Я бы порекомендовал попробовать две вещи. Во-первых, используйте атрибут <probing>, чтобы указать, где искать свою пользовательскую DLL, см. Этот ответ , а не то, как вы это делаете.

Во-вторых, если это не сработает, попробуйте использовать событие AppDomain.AssemblyResolve вместо использования файла конфигурации. Затем вы можете загрузить сборку из любого места.

Редактировать : Джей Уокер отмечает, что ..NET 4 и новее изменили AssemblyResolve, так что если DLL-библиотека отсутствует в пользовательской папке, верните ноль, чтобы сохранить поведение по умолчанию.

Вот пример кода для AssemblyResolve:

Assembly currentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
    if (args.Name == THE_DLL_I_WANT_TO_CUSTOM_LOAD)
    {
        // Load from our custom path
        string finalPath = null;
        try
        {
            finalPath = MyCustomPath + args.Name.Substring(0, args.Name.IndexOf(",")) + ".dll";
            return Assembly.LoadFrom(finalPath);
        }
        catch ()
        {
        }
    }

    // Not our custom, use the default loading
    return null;
}
0 голосов
/ 28 июля 2011

Цитирование MSDN для <codebase>:

Если сборка имеет строгое имя, настройка кодовой базы может быть в любом месте локальной интрасети или Интернета.Если сборка является частной сборкой, параметр кодовой базы должен представлять собой путь относительно каталога приложения.

У вашей сборки нет строгого имени, поэтому вы не можете использовать эту директиву, указавполный путь.Подпишите свою сборку (для этого требуется три щелчка, используя Visual Studio) или используйте AssemblyResolve, как предложено AresAvatar.

...