java 工厂assembly.load怎么用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java 工厂assembly.load怎么用相关的知识,希望对你有一定的参考价值。

参考技术A 当一个Assembly被加载到AppDomain之后,静态数据被加载,在其中创建的对象GC会负责回收 但是除非这个AppDomain被卸载,否则这个Assembly不会被单独卸载 如果你需要动态运行环境,你可以创建一个AppDomain,然后在其中加载Assembly并运行,用完之

如果在 Windows 服务 .net 可执行文件中调用 .NET Assembly.Load/LoadFrom 会失败

【中文标题】如果在 Windows 服务 .net 可执行文件中调用 .NET Assembly.Load/LoadFrom 会失败【英文标题】:.NET Assembly.Load/LoadFrom fails if calling it within a windows service .net executable 【发布时间】:2019-12-13 11:57:24 【问题描述】:

各位开发者好!

我目前在运行时在我的 WPF 应用程序中使用“Assembly.Load”或“Assembly.LoadFrom”加载特定程序集时有点迷失了。 p>

如果我只运行可执行文件,则在运行时加载程序集就可以了!

但是它会抛出异常“FileNotFoundException,无法加载文件或程序集..或其依赖项之一..” 如果我以相同的方式加载相同的程序集,而我的 WPF 应用程序作为 windows 服务(在 LocalSystem 下)运行。

processInstaller.Account = ServiceAccount.LocalSystem;
processInstaller.Username = null;
processInstaller.Password = null;

导致异常的程序集称为“Siemens.Sinumerik.Operate.Services.Wrapper.dll”,由“Siemens.Sinumerik.Operate.Services.dll”。

-> 3rd 方程序集 - 没有可用的源,对我来说,包装器似乎是一个混合的 cli/c++ 程序集。

现在,在对这个问题进行一些研究后,我发现 .e.g 可能程序集的查找目录是“C:\windows\system32”,而不是存储可执行文件的文件夹。或者采取“fuslogvw”来缩小问题范围。

然而,它不是我的第一个项目在运行时加载程序集以执行某些操作。唯一的事情是我在运行时从未加载过混合的“cli/c++”程序集 -> 可能有任何已知问题或我可能会错过正确加载“cli/c++”程序集的内容?

这是我用来加载程序集的代码(来自文件或 gac)

LoadAssembly("Siemens.Sinumerik.Operate.Services"); // this assembly references the wrapper
LoadAssembly("Siemens.Sinumerik.Operate.Services.Wrapper, Version=4.8.2.0, Culture=neutral, PublicKeyToken=bdd90fa02fd1c4ee", false); // load the wrapper from GAC using AssemblyName -> Exception only in service
LoadAssembly("Siemens.Sinumerik.Operate.Services.Wrapper"); // load the wrapper from file using AssemblyName -> Exception only in service

LoadAssembly 正在检查 AssemblyName 是否已经加载到当前 AppDomain 中,如果没有,则使用 GAC 或 FileSystem 加载它(取决于函数 LoadAssembly 的第二个参数“loadFromFile”)。

因此它使用"Assembly.Load(assemblyName); // from gac""Assembly.LoadFrom(file); // from file"

我尝试解决的问题:

将动态加载的程序集引用到主项目,希望应用程序能够在启动期间将包装程序集加载到 AppDomain -> 失败

将当前目录更改为存储包装程序集 dll 的路径 -> 失败

连接所有 AssemblyLoad 和 Resolve 事件并尝试使用“Assembly.Load”加载 -> fail

比较了用于服务和普通可执行文件的 AppDomains -> 似乎两者都一样,没有看到它们之间有任何特殊区别)-> 失败

李>

使用“fuslogvw”获取一些可能指示任何错误的程序集绑定信息 -> 失败(请参阅下面的日志)

此外,我使用“fuslogvw”来找出包装器到底出了什么问题,但我没有得到任何线索,因为日志显示的结果与我只是运行正常的可执行文件一样(不能作为服务工作) 这是日志“Siemens.Sinumerik.Operate.Services.Wrapper, Version=4.8.2.0, Culture=neutral, PublicKeyToken=bdd90fa02fd1c4ee.HTM”

*** Protokolleintrag für Assembly-Binder  (13.12.2019 @ 12:12:21) ***

Der Vorgang wurde durchgeführt.
Ergebnis der Bindung: hr = 0x0. Der Vorgang wurde erfolgreich beendet.

Der Assemblymanager wurde geladen aus:  C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Als EXE-Datei ausgeführt.  C:\Projekte\MTF\trunk\MTFMain\MTF\bin\Debug\MTF.exe
--- Ein detailliertes Fehlerprotokoll folgt. 

=== Zustandsinformationen vor Bindung ===
LOG: DisplayName = Siemens.Sinumerik.Operate.Services.Wrapper, Version=4.8.2.0, Culture=neutral, PublicKeyToken=bdd90fa02fd1c4ee
 (Fully-specified)
LOG: Appbase = file:///C:/Projekte/MTF/trunk/MTFMain/MTF/bin/Debug/
LOG: Ursprünglicher PrivatePath = NULL
LOG: DynamicBase = NULL
LOG: CacheBase = NULL
LOG: AppName = MTF.exe
Aufruf von Assembly : MTF, Version=2.0.7286.21871, Culture=neutral, PublicKeyToken=null.
===
LOG: Diese Bindung startet im default-Load-Kontext.
LOG: Die Anwendungskonfigurationsdatei wird verwendet: C:\Projekte\MTF\trunk\MTFMain\MTF\bin\Debug\MTF.exe.Config
LOG: Die Hostkonfigurationsdatei wird verwendet: 
LOG: Die Computerkonfigurationsdatei von C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config wird verwendet.
LOG: Verweis nach der Richtlinie: Siemens.Sinumerik.Operate.Services.Wrapper, Version=4.8.2.0, Culture=neutral, PublicKeyToken=bdd90fa02fd1c4ee
LOG: Die Assembly wurde bei Suche im GAC gefunden.
LOG: Die Bindung war erfolgreich. Assembly wird zurückgegeben von C:\Windows\assembly\GAC_32\Siemens.Sinumerik.Operate.Services.Wrapper\4.8.2.0__bdd90fa02fd1c4ee\Siemens.Sinumerik.Operate.Services.Wrapper.dll.
LOG: Die Assembly wird im default-Load-Kontext geladen.

这里是“WhereRefBind!Host=(LocalMachine)!FileName=(Siemens.Sinumerik.Operate.Services.Wrapper.dll).HTM”:

*** Protokolleintrag für Assembly-Binder  (13.12.2019 @ 12:14:00) ***

Der Vorgang wurde durchgeführt.
Ergebnis der Bindung: hr = 0x0. Der Vorgang wurde erfolgreich beendet.

Der Assemblymanager wurde geladen aus:  C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Als EXE-Datei ausgeführt.  C:\Projekte\MTF\trunk\MTFMain\MTF\bin\Debug\MTF.exe
--- Ein detailliertes Fehlerprotokoll folgt. 

=== Zustandsinformationen vor Bindung ===
LOG: Where-ref-Bindung. Speicherort = C:\Projekte\MTF\trunk\MTFMain\MTF\bin\Debug\dll\Siemens.Sinumerik.Operate.Services.Wrapper.dll
LOG: Appbase = file:///C:/Projekte/MTF/trunk/MTFMain/MTF/bin/Debug/
LOG: Ursprünglicher PrivatePath = NULL
LOG: DynamicBase = NULL
LOG: CacheBase = NULL
LOG: AppName = MTF.exe
Aufruf von Assembly : (Unknown).
===
LOG: Diese Bindung startet im LoadFrom-Load-Kontext.
WRN: Das native Image wird nicht im LoadFrom-Kontext durchsucht. Das native Image wird nur im Standard-Load-Kontext durchsucht, z. B. Assembly.Load().
LOG: Die Anwendungskonfigurationsdatei wird verwendet: C:\Projekte\MTF\trunk\MTFMain\MTF\bin\Debug\MTF.exe.Config
LOG: Die Hostkonfigurationsdatei wird verwendet: 
LOG: Die Computerkonfigurationsdatei von C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config wird verwendet.
LOG: Download von neuem URL file:///C:/Projekte/MTF/trunk/MTFMain/MTF/bin/Debug/dll/Siemens.Sinumerik.Operate.Services.Wrapper.dll.
LOG: Der Assembly-Download wurde durchgeführt. Datei-Setup wird begonnen: C:\Projekte\MTF\trunk\MTFMain\MTF\bin\Debug\dll\Siemens.Sinumerik.Operate.Services.Wrapper.dll.
LOG: Die von der Quelle ausgeführte Setup-Phase beginnt.
LOG: Der Assemblyname ist: Siemens.Sinumerik.Operate.Services.Wrapper, Version=4.8.2.0, Culture=neutral, PublicKeyToken=bdd90fa02fd1c4ee.
LOG: Die Richtlinie wird für where-ref-Bindung erneut angewendet.
LOG: Verweis nach der Richtlinie: Siemens.Sinumerik.Operate.Services.Wrapper, Version=4.8.2.0, Culture=neutral, PublicKeyToken=bdd90fa02fd1c4ee
LOG: Die Assembly wurde bei Suche im GAC gefunden.
LOG: Wechseln vom LoadFrom-Kontext zum Standardkontext.
LOG: Die Bindung war erfolgreich. Assembly wird zurückgegeben von C:\Windows\assembly\GAC_32\Siemens.Sinumerik.Operate.Services.Wrapper\4.8.2.0__bdd90fa02fd1c4ee\Siemens.Sinumerik.Operate.Services.Wrapper.dll.
LOG: Die Assembly wird im default-Load-Kontext geladen.

我希望有人可以帮助我缩小 Wrapper 程序集的加载问题 :) 或者有任何其他想法我可以做什么..

到目前为止谢谢! 如果您需要更多信息,请告诉我!

【问题讨论】:

您可能需要在 Windows 服务在其他位置运行的 AppDomain.CurrentDomain.BaseDirectory 中找到 DLL 嘿,我已经将基目录设置为可执行文件的路径。就像你在“fuslogvw”中看到的那样LOG: Appbase = file:///C:/Projekte/MTF/trunk/MTFMain/MTF/bin/Debug/ 【参考方案1】:

根本原因: 该问题是由于并非所有本机 dll(使用提及包装器)都可以为“LocalSystem”帐户解决。

重点是 Wrapper 需要设置 3 个特定路径来查找本机 dll,例如“QT”库,.. 我在第一次安装这个“Siemens”API 时做了一次,但是当安装映射它的安装文件夹和一个额外的驱动器号时,我在 %PATHS% 变量中添加了这 3 个额外的路径使用新创建的驱动器号-> 这是一个大问题,因为用户“LocalSystem”无法访问我的虚拟机?驱动器“D:” -> 因此 %PATH% 变量中的路径无法“解析”,因为驱动器“D:”没有退出。

解决方案:更改了 %PATH% 变量中的 3 个特定路径,以确保它现在指向“C:..”下的安装文件夹!

附加: 工具“procmon”是查看无法解析那些原生 c/c++ 库的唯一方法。 我在搜索时检查了工具列出的所有路径,例如“QtCore4.dll”(作为服务运行时)。

-> 通常:如果无法解析本机库,则使用“Assembly.Load”加载的 .NET 程序集不会引发任何“AssemblyResolve”事件。

-> Fuslogvw 在这个级别无法提供帮助,因为它没有提供有关本机库的详细信息。

结案:)

【讨论】:

以上是关于java 工厂assembly.load怎么用的主要内容,如果未能解决你的问题,请参考以下文章

Assembly.LoadFrom() 或 Assembly.Load() 能够删除文件

多个 Assembly.Load(Byte[]),相同的实例或泄漏?

C# Assembly.Load() 方法加载了错误的 dll?

反射使用反射

Assembly.Load* 的奇怪问题

如果在 Windows 服务 .net 可执行文件中调用 .NET Assembly.Load/LoadFrom 会失败