6

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

问题是当我尝试添加到 .NET 项目并重建时,DLL 被锁定,我无法覆盖它。 NI 声称 LabView 使用影子复制。但如果这是真的,我的 DLL 不应该被锁定。

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

4

6 回答 6

5

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

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

这是我的建议:

在 LabView 中,而不是直接加载您的 dll,正如 Chris Sterling 所建议的那样,您需要创建一个“包装器”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。

于 2013-07-24T01:53:08.840 回答
4

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

于 2013-07-24T07:26:49.903 回答
2

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

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

您可以通过转到 Project->Properties->Debug->Start External Program 让 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#。

于 2013-07-21T16:13:38.500 回答
1

The terminology there is a little unclear, because it's talking about LV "calling" an assembly, and I don't know if that refers to accessing the assembly at edit time or actually calling it at run-time. If it's the second, that would probably explain why it's locked.

I'm not a .NET programmer, so I have no idea what the actual solution is, but I'm guessing that you don't actually need to fully close LV to release the lock. It's possible that closing the project is enough, although I know that's not necessarily any better and it probably won't help if the lock happens at the process level.

于 2013-06-27T11:32:12.893 回答
1

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

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

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

简单如

Unlocker mydllpath.dll /s /d

于 2013-07-24T12:41:42.457 回答
1

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

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

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

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

我在此处包含了有关加载程序集的官方 Labview 帮助指南。

于 2019-09-09T14:32:26.827 回答