【问题标题】:How can I get LabView to stop locking my .NET DLL?如何让 LabView 停止锁定我的 .NET DLL?
【发布时间】:2013-06-24 02:31:29
【问题描述】:

我正在试用 LabView,尝试将其与 .NET 结合使用。我设法创建了一个小应用程序,它可以读取仪表、转换 .NET 中的值并在另一个仪表上显示结果。

问题是当我尝试添加到 .NET 项目并重建时,DLL 被锁定,我无法覆盖它。 NI claims that LabView uses Shadow Copying。但如果这是真的,我的 DLL 不应该被锁定。

有什么方法可以让 LabView 停止锁定 DLL?除了每次我想重建时都退出 LabView,这似乎是一个乏味的修复。

【问题讨论】:

  • afaik 除了关闭 Labview 之外别无他法。至少这是我多年来一直使用的。这也是有道理的:如果使用 dll 的 vi 是打开的,你如何期望它锁定 dll?
  • @stijn,正如我上面提到的,NI 声称 LabView 使用影子复制。如果这是真的,那么原始 DLL 不应该被锁定,因为 LabView 不应该使用它;它应该使用它制作的副本。
  • 您可能已经尝试过,但请确保在您的 LabVIEW.ini 文件(存储在 labview 目录中)中,AppDomainSetup_ShadowCopyFiles INI 标志设置为 True。跨度>
  • @Campari,我没试过。所以我做了。我的 LabView.ini 文件中没有该行,所以我尝试添加它,但它仍然做同样的事情;它锁定 DLL。我把它放在 .ini 的一行上:AppDomainSetup_ShadowCopyFiles=True 我也尝试将它作为字符串 after reading this:AppDomainSetup_ShadowCopyFiles="True" 那也没用。在这方面我可以尝试更多的想法吗?
  • @Kyralessa 这可能是因为您的版本早于 LabVIEW 2011。但从技术上讲,默认行为应该是 .NET Framework 在锁定之前将 DLL 复制到临时目录 \Local Settings\Application Data\assembly\dll2。也许您可以尝试使用不同版本的 LabVIEW。

标签: c# .net labview


【解决方案1】:

我认为您的应用程序中发生的情况如下:

当 Labview 启动时,它会拉入应用程序的 dll,并将其紧紧锁定在内存中。因此,该文件被锁定并且 Visual Studio 将无法覆盖该文件(我在其他应用程序中直接看到了这种行为)。由于在 Labview 退出之前 dll 永远不会被释放,因此您需要找到一种方法来“欺骗” Labview 在每次重新编译时加载新的 dll。

这是我的建议:

在 LabView 中,不要像 Chris Sterling 建议的那样直接加载您的 dll,您需要创建一个“包装器”dll,该 dll 将通过接口加载您的特定 LabView dll

通过使用存储在包装器 dll 中的接口,您可以完全解耦两个 dll,这将防止包装器 dll 了解/锁定您的主 dll。稍后,当您调试完成后,您可以直接将dll链接到LabView。

以下是代码的大致外观:

public class LabViewWrapper : IYourCustomClass
{
    private IYourCustomClass _labViewClass;
    private string labviewPath = "Full Path to labview dll";

    public LabViewWrapper()
    {
        Assembly assembly;

        try
        {
            using (FileStream fs = File.OpenRead(labviewPath))
            {
                using (MemoryStream ms = new MemoryStream())
                {
                    byte[] buffer = new byte[1024];
                    int read = 0;
                    while ((read = fs.Read(buffer, 0, 1024)) > 0)
                        ms.Write(buffer, 0, read);
                    assembly = Assembly.Load(ms.ToArray());
                    ms.Close();
                }
                fs.Close();
            }


            Type t = assembly.GetType(IYourCustomClass);

            _labViewClass= (IYourCustomClass)Activator.CreateInstance(t);
        }
        catch
        {
            // Unable to load dll dynamically
        }
    }


    // Implement all the methods in your interface with something like the following:

    /// <summary>
    /// Your Custom Method
    /// </summary>
    public void CustomLabViewMethod()
    {
        _labViewClass.CustomLabViewMethod();
    }

}

通过这种方式,您从内存中加载 dll,因此 labview 永远不会锁定您编译的原始 dll。唯一真正的缺点是它确实使调试更加困难,如果你想插入断点,你可能需要直接引用源 dll。

注意:我不确定的一件事,但我相信会“解决”的问题是 Labview 是否足够聪明,可以在每次执行代码时重新构建对象,或者它是否只是在整个过程中保留相同的对象会议。如果它最终执行了后者,则每次启动自定义小部件时,您都需要添加代码以从文件系统“重新加载”dll。

【讨论】:

    【解决方案2】:

    您可以创建一个轻量级 DLL 包装器,该包装器本身具有显式运行时加载和卸载主 DLL。这样包装器保持锁定状态,但您可以快速更新经常更改的代码 DLL。

    【讨论】:

    • 同意 - 这就是要走的路。为简化起见,两个 DLL 的接口都可以基于单个接口类,因此包装器 DLL 完全简单,并且编译器可以防止任何简单的错误(例如忘记将添加到“后台”DLL 的新函数添加到包装器中)。
    • ...以后,包装器DLL可以被主DLL无缝替换。非常好! :)
    • 这是一个想法,但与其说是解决方案,不如说是一种变通方法,我对在 LabView 中使用的每个 .NET 项目中都必须这样做并不感到兴奋。另外,这与 Alex Gutierrez 之前回答的有什么不同?
    • 这种方法没有 Alex 提到的潜在麻烦,因为它的工作方式与您的最终生产 DLL 一样。最好的解决方案是让 LabView 更改他们的代码,但实际上这会立即为您工作。
    • 让我说得更具体一些。您的解决方案看起来与亚历克斯提到的完全相同相同,只是您的解决方案细节较少。如果您的答案与他的答案有些不同,您能准确地告诉我那是什么吗?
    【解决方案3】:

    我在 LV2012 中使用 C# 类和 Labview VI 的单独文件夹中的新自定义类进行测试。我可以在 VS2010 中重新编译 C# 代码,而无需关闭 Labview,但 Labview 看不到对 DLL 的更改(如果有的话)。为了让 Labview 看到我的测试用例的变化,它需要完全关闭并重新打开。

    对于 Labview C++ DLL,您必须关闭调用 VI,因为对 DLL 的引用保持打开状态。不过,您只需要关闭 Labview 启动窗格即可。

    您可以通过转到项目->属性->调试->启动外部程序,让 VS 在 C# 项目中自动生成 Labview.exe。当您在 VS 中按 F5 时,DLL 编译并生成 Labview。但是,VS 不会自动将 DLL 附加到进程,这非常非常令人讨厌。不知道这是否有帮助。

    就个人而言,我喜欢 C# 方法与 Labview 集成的方式,但发现 C++ 更强大。使用 C++,您也可以通过与上述类似的方式生成 Labview,但它会自动将 DLL 附加到 Labview.exe 进程,从而使调试成为只需按 F5 的一步过程。您仍然可以在 C++ 中使用类等,您只需包装 C 函数即可在 Labview 中调用它们。鉴于 C++ 的一步调试和强大功能,我发现在 Labview 中使用外部代码时它优于 C#。

    【讨论】:

      【解决方案4】:

      那里的术语有点不清楚,因为它是在谈论 LV“调用”程序集,我不知道这是指在编辑时访问程序集还是在运行时实际调用它。如果是第二个,那可能就可以解释为什么它被锁定了。

      我不是 .NET 程序员,所以我不知道实际的解决方案是什么,但我猜你实际上并不需要完全关闭 LV 来释放锁。关闭项目可能就足够了,尽管我知道这不一定更好,而且如果锁定发生在进程级别,它可能无济于事。

      【讨论】:

      • 好吧,我已将 .NET 类添加到我的 LabView 图表中,但目前 LabView 项目实际上并未运行。不幸的是,似乎只需将类添加到图表就足以锁定 DLL。这就是我要解决的问题。
      【解决方案5】:

      获取http://www.emptyloop.com/unlocker/ unlocker -h 的命令行选项

      在预构建中运行。在相关 dll 上使用解锁命令。

      如果仅解锁无济于事,请使用解锁+删除。

      简单

      Unlocker mydllpath.dll /s /d

      【讨论】:

      • 我已经知道如何解锁:我退出 LabView。我正在寻找一种方法来防止它首先被锁定。
      • 好吧。退出很难,我的解决方案很简单。
      【解决方案6】:

      您会发现此行为会根据 dll 的分发方式而有所不同。 如果 Labview 通过磁盘上的静态位置(由路径输入指定)调用程序集,您会发现在 Labview 应用程序打开时无法重建 dll。

      但是,如果 dll 已注册并且 Labview 通过名称访问它,您可以重建并重新安装到您想要的内容,一旦关闭并重新打开,Labview 将更新其对 DLL 的引用。

      我在通过 COM Interop 共享 .Net 程序集以及将其安装到 GAC 时偶然发现了这一点。

      早在 2017 年就有关于此主题的知识库文章,但现在似乎不见了。

      我已包含有关加载程序集here 的官方 Labview 帮助指南。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多