17

我正在为另一个应用程序 Autodesk Revit 开发一个插件,它是作为单独的 DLL 类库构建的。我正在尝试在我的一个 WPF 窗口中使用Wpf 工具包属性网格。属性网格在 Visual Studio 中显示良好,智能感知也能正常工作。但是当我尝试在加载我的加载项的情况下启动 Revit 时,我得到了以下异常。

System.Windows.Markup.XamlParseException occurred
  HResult=-2146233087
  Message=Could not load file or assembly 'Xceed.Wpf.Toolkit, PublicKeyToken=3e4669d2f30244f4' or one of its dependencies. The system cannot find the file specified.
  Source=PresentationFramework
  LineNumber=133
  LinePosition=27
  StackTrace:
       at System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri)
  InnerException: System.IO.FileNotFoundException
       HResult=-2147024894
       Message=Could not load file or assembly 'Xceed.Wpf.Toolkit, PublicKeyToken=3e4669d2f30244f4' or one of its dependencies. The system cannot find the file specified.
       Source=mscorlib
       FileName=Xceed.Wpf.Toolkit, PublicKeyToken=3e4669d2f30244f4
       FusionLog==== Pre-bind state information ===
LOG: User = GLOBAL\eric.anastas
LOG: DisplayName = Xceed.Wpf.Toolkit, PublicKeyToken=3e4669d2f30244f4
 (Partial)
WRN: Partial binding information was supplied for an assembly:
WRN: Assembly Name: Xceed.Wpf.Toolkit, PublicKeyToken=3e4669d2f30244f4 | Domain ID: 1
WRN: A partial bind occurs when only part of the assembly display name is provided.
WRN: This might result in the binder loading an incorrect assembly.
WRN: It is recommended to provide a fully specified textual identity for the assembly,
WRN: that consists of the simple name, version, culture, and public key token.
WRN: See whitepaper http://go.microsoft.com/fwlink/?LinkId=109270 for more information and common solutions to this issue.
LOG: Appbase = file:///C:/Program Files/Autodesk/Revit 2014/
LOG: Initial PrivatePath = NULL
Calling assembly : PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\Program Files\Autodesk\Revit 2014\Revit.exe.Config
LOG: Using host configuration file: 
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\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:/Program Files/Autodesk/Revit 2014/Xceed.Wpf.Toolkit.DLL.
LOG: Attempting download of new URL file:///C:/Program Files/Autodesk/Revit 2014/Xceed.Wpf.Toolkit/Xceed.Wpf.Toolkit.DLL.
LOG: Attempting download of new URL file:///C:/Program Files/Autodesk/Revit 2014/SDA/bin/Xceed.Wpf.Toolkit.DLL.
LOG: Attempting download of new URL file:///C:/Program Files/Autodesk/Revit 2014/SDA/bin/Xceed.Wpf.Toolkit/Xceed.Wpf.Toolkit.DLL.
LOG: Attempting download of new URL file:///C:/Program Files/Autodesk/Revit 2014/Xceed.Wpf.Toolkit.EXE.
LOG: Attempting download of new URL file:///C:/Program Files/Autodesk/Revit 2014/Xceed.Wpf.Toolkit/Xceed.Wpf.Toolkit.EXE.
LOG: Attempting download of new URL file:///C:/Program Files/Autodesk/Revit 2014/SDA/bin/Xceed.Wpf.Toolkit.EXE.
LOG: Attempting download of new URL file:///C:/Program Files/Autodesk/Revit 2014/SDA/bin/Xceed.Wpf.Toolkit/Xceed.Wpf.Toolkit.EXE.

       StackTrace:
            at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
            at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
            at System.Reflection.Assembly.Load(AssemblyName assemblyRef)
            at System.Windows.Baml2006.Baml2006SchemaContext.ResolveAssembly(BamlAssembly bamlAssembly)
            at System.Windows.Baml2006.Baml2006SchemaContext.ResolveBamlTypeToType(BamlType bamlType)
            at System.Windows.Baml2006.Baml2006SchemaContext.ResolveBamlType(BamlType bamlType, Int16 typeId)
            at System.Windows.Baml2006.Baml2006SchemaContext.GetXamlType(Int16 typeId)
            at System.Windows.Baml2006.Baml2006Reader.Process_ElementStart()
            at System.Windows.Baml2006.Baml2006Reader.Process_OneBamlRecord()
            at System.Windows.Baml2006.Baml2006Reader.Process_BamlRecords()
            at System.Windows.Baml2006.Baml2006Reader.Read()
            at System.Windows.Markup.WpfXamlLoader.TransformNodes(XamlReader xamlReader, XamlObjectWriter xamlWriter, Boolean onlyLoadOneNode, Boolean skipJournaledProperties, Boolean shouldPassLineNumberInfo, IXamlLineInfo xamlLineInfo, IXamlLineInfoConsumer xamlLineInfoConsumer, XamlContextStack`1 stack, IStyleConnector styleConnector)
            at System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri)
       InnerException: 

通常,当我想从 Revit 插件引用第 3 方程序集时,我只需确保将第 3 方 DLL 复制到与我的插件 DLL 相同的位置。我检查Xceed.Wpf.Toolkit.dll并被复制到包含我的插件 DLL 的目录中。

我从错误中的日志消息中注意到它正在 Revit 程序目录中查找 DLL。复制Xceed.Wpf.Toolkit.dll到此目录后,我不再收到错误。

但是,我有现有的插件部署工具,它们依赖于位于它们自己的隔离文件夹中的插件文件。

那么,有谁知道如何让插件找到 WPF Toolkit 库?

4

10 回答 10

25

因此,我从 2014 年开始为我的这个问题找到了一个新的更好的解决方案。

今天我遇到了同样的问题,从程序集中加载 WPF 控件会引发 XamlParseException,但这次是我创建的 WPF 控件库程序集。

我尝试将 DLL 移动到与 EXE 相同的文件夹中,并且像以前一样解决了问题。

经过一番搜索,我在 Telerik.com 论坛上找到了这个问题: http ://www.telerik.com/forums/xamlparseexception-could-not-load-file-or-assembly

事实证明,如果您只是为控件命名,通过添加一个x:Name属性,这将在代码隐藏中添加对控件的引用,并且由于某种原因解决了加载程序集的问题。

  <!--This causes a XamlParseException -->
  <mylib:MyCustomControl />

  <!-- This works -->
  <mylib:MyCustomControl x:Name="foobar"/>
于 2017-01-12T04:51:13.613 回答
11

我是这种方法的粉丝。您可以在 AppDomain 上为 AssemblyResolve 事件注册一个事件,该事件在无法加载程序集时捕获。

它看起来像这样:

// using System.Reflection and System.IO

AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);

private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args )
{
    if (args.Name.ToUpper().StartsWith("XCEED.WPF"))
    {
       string asmLocation = Assembly.GetExecutingAssembly().Location;

       string asmName = args.Name.Substring(0, args.Name.IndexOf(','));
       string filename = Path.Combine( asmLocation, asmName );

       if (File.Exists(filename)) return Assembly.LoadFrom(filename);
    }
}

你可以让它比这更完整一点,但你明白了......

于 2014-03-01T21:40:01.150 回答
9

我知道这是一个非常古老的问题,但不久前我碰巧遇到了这个确切的错误。如果您的 Visual Studio 应用程序使用两个项目或一个项目引用另一个项目,我会检查以确保两个项目都安装了扩展工具包。

右键单击您的两个项目并单击“管理 NuGet 包”,然后在对话框的左侧浏览到“已安装的包”。如果您在两个项目上都没有看到扩展工具包,那么您可以使用管理器在线搜索并为您安装它们。

我的问题是我只在一个项目上安装了扩展工具包,而不是两个项目。

希望这可以帮助将来的人。

于 2014-08-21T15:06:59.173 回答
8

尽管这可能已经解决,但一个常见的原因是未能将 Xceed.Wpf.Toolkit dll 添加到您的入口点项目。您可能将它添加到您的类库项目之一,并将其​​“复制本地”属性设置为 true。还必须将对此 dll 的引用添加到您的主项目中,该项目包含您的 App.xaml.cs,其“复制本地”属性设置为 true。

我很惊讶 Visual Studio 2013 没有自动处理这个问题。

于 2014-11-15T14:02:28.403 回答
1

虽然我个人认为您应该按照接受的答案(@Matt)中的说明进行操作,但我想提一下,将 dll 复制到 Autodesk Revit 安装中的“程序”文件夹可能也可以解决问题。如果我没记错的话,他们还建议您将插件部署到该文件夹​​的子文件夹中,以确保它正常工作。我怀疑,这是由于像你所拥有的那样的影响。

于 2014-03-03T08:30:41.800 回答
0

System.Reflection命名空间中,有Assembly类。这可用于将新程序集加载到当前 AppDomain 中。

Assembly.LoadFrom("FileLocation");

尽管这仍然很烦人,但我认为这可能是让它加载不在主目录中的库的唯一方法。

于 2014-03-01T04:54:45.787 回答
0

确保您“解除阻止”Xceed 程序集。右键单击该文件并选择属性,然后选择“取消阻止”。VS 将编译代码而不会出现任何错误,但是当您运行时,Windows 不会加载程序集。我的甚至被合并到一个程序集中。

于 2015-07-13T10:33:01.780 回答
0

我见过有人将这种变通方法用于 Visual Studio 扩展。然而 VS 提供了一个更好的解决方案,使用“ProvideCodeBaseAttribute”:

https://docs.microsoft.com/en-us/dotnet/api/microsoft.visualstudio.shell.providecodebaseattribute

于 2019-10-13T08:22:08.397 回答
0

从 XAML 加载控件时,从中Xceed.Wpf.Toolkit.dll加载您的调用程序集是PresentationFramework.dll. 因此,在这种情况下,CLR 不会查看您的插件文件夹(当从插件的主程序集加载另一个类时,它会做什么,因为它会查看调用程序集的文件夹)。

因此,您可以如您所见,在代码隐藏中放置对控件的引用,或者您可以使用AppDomain.CurrentDomain.AssemblyResolve强制 CLR 在您的插件文件夹中查找。

将 dll 放在 Revit 安装文件夹中是可行的,但在我看来,这是一种不好的做法,因为它可能被另一个插件安装覆盖,其后果难以衡量。

于 2017-10-03T12:25:08.767 回答
0

我使用Fody CosturaXceed.Wpf.Toolkit.dll编译后的.dll. 只需使用 NuGet 安装它并输入Install-CleanReferencesTarget您的Packet Manager Console内容即可。

于 2015-10-09T14:29:57.780 回答