Python for .NET “无法找到程序集”错误

21

我正在使用CPython,并拥有一个C# dll。 我想使用Python for .NET使它们通信。 由于需要将其集成到现有的CPython系统中,因此无法使用IronPython。

我完全不了解Python for .NET,实际上对Python几乎没有经验,对C#更是一窍不通。 因此,请原谅如果我的问题似乎非常基础。

我正在使用Python 2.7.3,并下载了pythonnet-2.0-alpha2-clr2.0_131_py27_UCS2并将其解压缩到名为pyfornet_test的文件夹中,该文件夹还包含我正在尝试使用的dll(名为DotNet4Class.dll)。

然后我运行了这个:

import sys

import os

import clr

sys.path.append(r"C:\pyfornet_test")

clr.AddReference("DotNet4Class.dll")

这让我出现了这个错误:

System.IO.FileNotFoundException: Unable to find assembly 'DotNet4Class.dll'.
   at Python.Runtime.CLRModule.AddReference(String name) in C:\Users\Barton\Documents\Visual Studio 2008\Projects\PyShar
p\trunk\pythonnet\src\runtime\moduleobject.cs:line 375
任何建议都将不胜感激。谢谢!
7个回答

19

一个可能的原因是Windows未启用从“外部来源”加载。要解决此问题:

  • 右键单击.dll文件
  • 选择“属性”
  • 在“常规”下,点击“取消阻止”

这也是我的问题!这是一个令人沮丧的静默和隐藏属性的dll。 - chanban
这也是我的问题。不幸的是,在检查之前,我尝试了一个不必要的32位Python版本。 - RexBarker
祝福你! - Christoph

17

试试这个(不带扩展名.dll):

clr.AddReference(r"C:\pyfornet_test\DotNet4Class")

7

DotNet4Class.dll是否构建在.NET 4上?根据dll的命名,我认为是这样的。

请注意这里的问题:http://sourceforge.net/tracker/?func=detail&aid=3293169&group_id=162464&atid=823891

当程序集是使用.NET 4.0构建时,clr.AddReference会失败 - ID:3293169

我已经看过解决方案了,但基本上,您需要在.NET 4下重新构建和重新编译Python for .NET项目。

我还要提到,像这样没有被大量开发和使用的项目通常有一些细微的特殊性质,使得了解平台对于解决此类问题至关重要。听起来您正在尝试在不太了解Python或.NET的情况下解决此问题,这将始终存在问题。


我尝试了你发布链接中的解决方案。我已经在Subversion中下载了这些项目,但是它们没有在VS中正确加载。这个问题可能需要比我拥有的时间更多的时间来解决。 - Annie
1
我正在自动化一件实验设备。提供的唯一dll是C#。我试图将其集成到使用CPython的现有系统中。我知道的两个解决方案是1)Python for .NET和2)将C#功能导出为COM对象。我对第二种方法只有最模糊的了解,因此我选择了第一种。我很愿意听取其他想法。 - Annie
1
我看到有两个选项.. 1:使用C或Python编写设备驱动程序。我们在大学项目中不得不为医疗设备做这件事,可能需要一些时间。第二个也可能更容易的解决方案是创建一个小的.NET服务,并使用HTTP或某种消息代理(RabbitMQ或ZeroMQ或Redis)在Python应用程序和设备服务之间进行通信。 - Josh Smeaton
我更新了VS,现在已经成功解决了最初发布的问题,所以我将其标记为解决方案。谢谢,Josh。 - Annie
3
PythonNet 2.3可以成功加载.NET 4的DLL。但是,在使用我的.NET 4 DLL时,我也遇到了“无法找到程序集”的错误。问题出在我的DLL是为x86构建的,而我的CPython是x64的。将Python更改为x86后,问题得到解决。“无法找到程序集”错误的意思是“无法_加载_该程序集”。 - David Ching
显示剩余4条评论

5

你尝试过使用clr.FindAssembly吗?

import clr
import sys
assemblydir = r"C:\pyfornet_test"
assemblypath = r"C:\pyfornet_test\DotNet4Class.dll"
sys.path.append(assemblydir)
clr.FindAssembly(assemblypath)

我不知道为什么它能够正常运行,但这段代码在我的电脑上可以运行(Python 2.7,.NET4)。


2
它对我不起作用。 - G M

5
我有这样的代码(我将MyRightClickMenuService.dll复制到与我的script.py相同的目录中)。它建立在.NET 4.0之上。
# script.py
import clr
import os
import sys
sys.path.append(os.path.dirname(__file__))

clr.AddReference('MyRightClickMenuService')
clr.AddReference('System')
clr.AddReference('System.Security')

from MyRightClickMenuService import (
    AclSecuredNamedPipeBinding,
    MyMenuItem,
    MyContextMenuService,
    etc
)

这是唯一可行的解决方案。只要将.dll文件添加到sys.path中并使用sys.path.append(dll_folder),您也可以将其放置在任何其他文件夹中。 - Niko Pasanen

4

检查清单

  1. 在加载之前,将包含DLL文件的文件夹添加到sys.path中。您可以附加或使用sys.path.insert(0, dll_folder)将其放在列表中的第一位。
  2. 在将文件夹添加到sys.path之后,调用clr.AddReference('my_dll') 不需要dll扩展名(对于my_dll.dll),而是要不要加上它。
  3. DLL目标架构与CPython版本的位数相同。也就是说,如果Architecture为x64,则使用64位python,如果Architecture为x86,则使用32位python。(以下是此操作的说明)

如何检查DLL的目标架构?

  • 我使用了ILSpy(免费和开源)->打开DLL->检查输出。下面是示例输出。

ILSpy示例


感谢 @np8 提供的清单。我仍然无法加载程序集。我有一个 x64 C# dll。我可以在 Visual Studio 的 C# 项目中加载此 dll。运行代码 print(clr.FindAssembly(Myassembly)) 将指向 dll 所在的正确文件夹。运行 clr.AddReference(Myassembly) 将导致以下错误。System.IO.FileNotFoundException: 找不到程序集 'Myassembly'。有什么想法吗? - Lama
在调用 clr.Addreference(Myassembly) 之前,你的 sys.path 是什么样子的?它是否包含一个包含 Myassembly DLL 的文件夹? - Niko Pasanen
第一个条目将是Myassembly所在文件夹的路径。我使用以下命令添加它:sys.path.insert(0, assemblydir),其中assemblydir是指向Myassembly的路径。因此,我认为clr软件包能够找到Myassembly。因此,命令 clr.FindAssembly(Myassembly) 将提供正确的Myassembly路径。如果我不将文件夹添加到sys.path中,则函数 clr.FindAssembly(Myassembly) 将失败。另一个应用程序是否加载了dll并因此被阻止?我还没有尝试通过ctypes加载dll。 - Lama
你尝试运行在故障排除指南中找到的测试了吗?也就是说,Pythonnet是否能够与其他DLL(例如Python.EmbeddingTest.dll)一起工作? - Niko Pasanen
@pn8,你指引了我正确的方向。我误以为我在使用一个 .Net dll,实际上它是一个 ActiveX dll。因此,我使用了 import win32com.client 包来运行这个 ActiveX 对象。我在 Python 中使用的代码如下:dll_ref = System.Reflection.Assembly.LoadFile(Myassembly)。我从这里 链接 得到了这个代码。然后我才发现它不是一个有效的 .Net dll。这可能会成为你清单上的一个新点。 - Lama

0

对我有效的方法是解除 dll 文件的阻止。

如果您下载了 dll 文件或从其他计算机上获取它,可能会被阻止。因此,解除阻止对我解决了问题。

要解除阻止,请右键单击 dll 文件的属性,然后在底部勾选“解除阻止”框。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接