Visual Studio 在哪里寻找程序集?

发布于 2024-11-27 19:40:22 字数 3430 浏览 0 评论 0原文

我有一个框架,其中包含许多基类,可以派生这些基类来开发许多应用程序。在这些类中,有一个 System.Windows.Forms.Panel 的子类,我为其编写了自己的设计器。使用 Visual Studio 2005 一切正常,但当我尝试迁移到 VS2010 时出现问题。这是我正在做的事情的一个简化版本:

我有一个名为 CoreClasse 的项目,其中包含一个接口和两个类:

public interface IConf
{
    string foo { get; set; }
    void InitFoo();
}

public class SimpleClass
{
    public string foo;
}

public class ConfLoader
{
    public static IConf LoadConf()
    {
        AssemblyName anAssemblyName = new AssemblyName("ConfClasses");
        Assembly anAssembly = Assembly.Load(anAssemblyName);
        IConf result = (IConf)anAssembly.CreateInstance("ConfClasses.ConfClass");
        result.InitFoo();
        return result;
    }
}

然后有一个项目 ConfClasses,它引用 CoreClasses 并仅包含一个实现 IConf 的类:

public class ConfClass : IConf
{
    public SimpleClass confVal;

    public string foo
    {
        get { return confVal.foo; }
        set { confVal.foo = value; }
    }

    public void InitFoo()
    {
        confVal = new SimpleClass();
        confVal.foo = "bar";
    }
}

最后有一个项目仅引用 CoreClasses 并包含 Panel 子类和关联设计器的控件:

[Designer("MyControls.Design.SimplePanelDesigner", typeof(IRootDesigner))]
public class SimplePanel : Panel
{
    public SimpleClass dummy = new SimpleClass();
}

public class SimplePanelDesigner : DocumentDesigner
{
    public IConf DesignerConf;

    public SimplePanelDesigner()
        : base()
    {
        DesignerConf = ConfLoader.LoadConf();
    }
}

现在我创建另一个解决方案,它引用所有这些 dll 并包含 SimplePanel 的空子类。当我在 SolutionExplorer 中双击此类时,将执行 SimplePanelDesigner 的构造函数并调用 ConfLoader 的 LoadConf 方法。这意味着 ConfClasses.dll 被动态加载并创建 ConfClass 的实例。到目前为止,一切都很好,但是当调用 InitFoo 时,会引发此异常:

无法加载文件或程序集“CoreClasses,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null”或其依赖项之一。系统找不到指定的文件。

让事情变得更困难的是,在此示例中实际上并未引发异常,但这正是我的真实应用程序正在执行的指令类型以及我收到的异常。我不知道这里发生了什么。 VS正在执行CoreClasses中的方法。为什么它试图再次加载它?它在哪里寻找它?我也检查了当前的 AppDomain,但它加载的程序集中有 CoreClasses,而且它似乎没有改变。

只是为了添加更多细节,每个项目都构建在一个公共文件夹中(而不是项目文件夹内通常的 obj/debug 文件夹),并且在我开始测试时,PC 上没有我的 dll 的其他副本。然后,在我的用户配置文件的 AppData\Local\Microsoft\VisualStudio\10.0\ProjectAssemblies 文件夹中的一系列文件夹中完成所有引用的 dll 的副本,这似乎是 VS 在 Assembly.Load 时寻找程序集的地方执行后,我可以在那里找到 CoreClasses 的副本。我尝试清理所有文件夹,重建所有内容,并在每种组合中保持不同的解决方案打开/关闭,但没有任何改进。

编辑:

正如 GranMasterFlush 所建议的,这是异常生成的 FusionLog:

=== Pre-bind state information ===
LOG: User = FCDB\fc0107
LOG: DisplayName = XEngine.Core, Version=1.0.0.1, Culture=neutral, PublicKeyToken=null (Fully-specified)
LOG: Appbase = file:///C:/Program Files (x86)/Microsoft Visual Studio 10.0/Common7/IDE/
LOG: Initial PrivatePath = NULL
Calling assembly : (Unknown).
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.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: The same bind was seen before, and was failed with hr = 0x80070002.
ERR: Unrecoverable error occurred during pre-download check (hr = 0x80070002).

编辑 2

只是为了添加一些信息,我查看了我的简单示例生成的融合日志,发现在尝试时生成了完全相同的日志加载 CoreClasses,但 VisualStudio 找到了一种方法来应对它。

I've got a framework which consists of many base classes that can be derived to develop many apps. Among these classes there is a subclass of System.Windows.Forms.Panel for which I wrote its own designer. Everything is working fine with Visual Studio 2005, but something goes wrong when I try to move to VS2010. This is a much simplified version of what I am doing:

I have a project called CoreClasse which contains an interface and two classes:

public interface IConf
{
    string foo { get; set; }
    void InitFoo();
}

public class SimpleClass
{
    public string foo;
}

public class ConfLoader
{
    public static IConf LoadConf()
    {
        AssemblyName anAssemblyName = new AssemblyName("ConfClasses");
        Assembly anAssembly = Assembly.Load(anAssemblyName);
        IConf result = (IConf)anAssembly.CreateInstance("ConfClasses.ConfClass");
        result.InitFoo();
        return result;
    }
}

Then there is a project ConfClasses which references CoreClasses and contains just one class implementing IConf:

public class ConfClass : IConf
{
    public SimpleClass confVal;

    public string foo
    {
        get { return confVal.foo; }
        set { confVal.foo = value; }
    }

    public void InitFoo()
    {
        confVal = new SimpleClass();
        confVal.foo = "bar";
    }
}

And finally there is a project for the controls which references only CoreClasses and contains a subclass of Panel and the associated designer:

[Designer("MyControls.Design.SimplePanelDesigner", typeof(IRootDesigner))]
public class SimplePanel : Panel
{
    public SimpleClass dummy = new SimpleClass();
}

public class SimplePanelDesigner : DocumentDesigner
{
    public IConf DesignerConf;

    public SimplePanelDesigner()
        : base()
    {
        DesignerConf = ConfLoader.LoadConf();
    }
}

Now I create another solution which references all these dlls and contains an empty subclass of SimplePanel. When I double click on this class in SolutionExplorer the constructor of SimplePanelDesigner is executed and the method LoadConf of ConfLoader is called. This means that ConfClasses.dll is loaded dinamically and an instance of ConfClass is created. Everything is fine up to this moment, but when InitFoo is called this exception is raised:

Could not load file or assembly 'CoreClasses, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.

To make things harder, the exception is not actually raisedin this example, but this is exactly the kind of istructions my real app is executing, and the exception I am getting. I haven't got a clue of what's happening here. VS is executing a method which IS in CoreClasses. Why is it trying to load it again? And where is it looking for it? I checked the current AppDomain, too, but it has CoreClasses among its loaded assemblies, and it does not seem to change.

Just to add some more details, every project is build in a common folder (not the usual obj/debug folder inside the project folder), and there is no other copy of my dlls on the PC at the moment I start my test. Then a copy of all the referenced dlls is done in a series of folders in the AppData\Local\Microsoft\VisualStudio\10.0\ProjectAssemblies folder of my userprofile, and this seems to be the place VS is looking for the assemblies when Assembly.Load is executed, and I can find a copy of CoreClasses there. I tried to clean all the folders, to rebuild everything, and to keep the different solutions opened/closed in every combination, but without any improvement.

EDIT:

As GranMasterFlush suggested, this is the FusionLog generated by the exception:

=== Pre-bind state information ===
LOG: User = FCDB\fc0107
LOG: DisplayName = XEngine.Core, Version=1.0.0.1, Culture=neutral, PublicKeyToken=null (Fully-specified)
LOG: Appbase = file:///C:/Program Files (x86)/Microsoft Visual Studio 10.0/Common7/IDE/
LOG: Initial PrivatePath = NULL
Calling assembly : (Unknown).
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.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: The same bind was seen before, and was failed with hr = 0x80070002.
ERR: Unrecoverable error occurred during pre-download check (hr = 0x80070002).

EDIT 2

Just to add some info, I took a look at the fusion logs generated by my simple example and found out that exactly the same log has been generated while trying to load CoreClasses, but someway VisualStudio finds a way to cope with it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

川水往事 2024-12-04 19:40:22

我刚刚知道发生了什么事。简单示例与真实示例之间的区别在于涉及一个 AddIn。
这是一个相当日志的故事,但就是这样。

正如您从代码示例中看到的,我通过反射加载 ConfClasses dll,以避免添加对其的引用。这在运行时很好,但设计者抱怨说它无法将 IConf 转换为 IConf。发生这种情况是因为设计器启动时CoreClasses.dll是从AppData\Local\Microsoft\VisualStudio\10.0\ProjectAssemblies加载的,但是ConfClasses.dll是从我的bin文件夹加载的,它的引用也是如此,所以CoreClasses.dll有两个版本以及 IConf 的不同版本。

为了绕过这个问题,我开发了一个 AddIn,当在设计时使用 Assembly.Load 加载程序集时,会添加对该程序集的引用,然后在关闭最后一个设计器窗口时清除这些引用。

VS2005 一切正常,但使用 ProcMon.exe 我发现 VS2010 添加了一个新文件夹,插件在其中查找程序集:Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\CommonExtensions\DataDesign

我在那里复制了我的程序集,一切又恢复正常了。现在只需找到一种手动添加内容的方法即可。

I've just found out what's happening. The difference between the simple example and the real thing is the fact that there is an AddIn involved.
It's quite a log story, but this is it.

As you can see from the code sample, I load the ConfClasses dll via reflection in order to avoid to add a reference to it. This is fine at runtime, but the designer complains saying that it's not able to cast IConf to IConf. This happens because CoreClasses.dll is loaded from AppData\Local\Microsoft\VisualStudio\10.0\ProjectAssemblies when the designer starts, but ConfClasses.dll is loaded from my bin folder and so are its references, so there are two versions of CoreClasses.dll and different versions of IConf.

To bypass the problem I developed an AddIn that, when an assembly is loaded with Assembly.Load at design time, adds a reference to that assembly, and then cleans the references when the last designer window is closed.

Everything was OK with VS2005, but using ProcMon.exe I found out that VS2010 added a new folder where the addins look for assemblies: Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\CommonExtensions\DataDesign

I copied my assembly there and everything works again. Now it's only a matter of finding a way to add things there manually.

挖个坑埋了你 2024-12-04 19:40:22

您是否尝试过使用程序集绑定日志查看器来调查加载程序集失败的原因?

http://msdn.microsoft.com/en -us/library/e74a18c4%28v=vs.71%29.aspx

这里还有另一篇关于使用它的文章:

http://blogs.msdn.com/b/suzcook/archive /2003/05/29/57120.aspx

编辑:

DLL 存储在哪里?此论坛帖子详细说明了类似的问题,该问题是由于所引用的 DLL 不在 GAC、可执行目录或可执行文件的子文件夹中目录:

Have you tried using the Assembly Binding Log Viewer to investigate why this failure to load the assemblies?

http://msdn.microsoft.com/en-us/library/e74a18c4%28v=vs.71%29.aspx

There's another article here about using it:

http://blogs.msdn.com/b/suzcook/archive/2003/05/29/57120.aspx

EDIT:

Where are the DLL's stored? This forum post details a similar problem and the problem was down to the DLL's being referenced not being in either the GAC, executable directory or a sub-folder from the executable directory:

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文