如何让LabView停止锁定我的.NET DLL?

时间:2013-06-26 19:26:19

标签: c# .net labview

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

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

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

6 个答案:

答案 0 :(得分:5)

我认为您的申请中发生的事情如下:

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

以下是我的建议:

在LabView中,不是像Chris Sterling所建议的那样直接加载你的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。

答案 1 :(得分:4)

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

答案 2 :(得分:2)

我正在LV2012中使用C#类进行测试,其中一个新的自定义类位于Labview VI的单独文件夹中。我能够在VS2010中重新编译C#代码而无需关闭Labview,但Labview没有看到DLL的更改(如果有的话)。要让Labview查看我的测试用例中的更改,需要将其完全关闭并重新打开。

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

您可以让VS自动在C#项目中生成Labview.exe,方法是转到Project-&gt; Properties-&gt; Debug-&gt;启动外部程序。当您在VS中点击F5时,DLL会编译并生成Labview。但是,VS不会自动将DLL附加到进程,这实际上是非常令人讨厌的。 Dunno,如果这有帮助或没有。

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

答案 3 :(得分:1)

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

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

答案 4 :(得分:1)

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

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

如果只解锁无法使用解锁+删除。

简单如

Unlocker mydllpath.dll /s /d

答案 5 :(得分:1)

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

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

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

最近在2017年就曾有关于该主题的知识库文章,但现在似乎已丢失。

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