6

I'm trying out LabView, experimenting with how to use it in conjunction with .NET. I've managed to create a small app that reads a gauge, converts the value in .NET, and displays the result on another gauge.

The trouble is that when I try to add to the .NET project and rebuild, the DLL is locked and I can't overwrite it. NI claims that LabView uses Shadow Copying. But if that's true, my DLL shouldn't be locked.

Is there some way I can get LabView to stop locking the DLL? Other than exiting LabView every time I want to rebuild, which seems like a tedious fix.

Ryan Lundy
  • 204,559
  • 37
  • 180
  • 211
  • afaik there is no way apart from closing Labview. At least that's what I have been using for ages. It also makes sense: if the vi using the dll is open, how do you expect it to _not_ lock the dll? – stijn Jul 23 '13 at 09:15
  • 1
    @stijn, as I mentioned above, NI claims that LabView uses Shadow Copying. If that's true, then the original DLL shouldn't be locked, because LabView shouldn't be using it; it should be using the copy it made. – Ryan Lundy Jul 23 '13 at 09:55
  • 1
    You've probably already tried this, but make sure that in your LabVIEW.ini file (which is stored in the labview directory) the `AppDomainSetup_ShadowCopyFiles` INI flag is set to `True`. – federico-t Jul 24 '13 at 04:52
  • @Campari, I haven't tried that. So I did. My LabView.ini file didn't have that line in it, so I tried adding it, but it still does the same thing; it locks the DLL. I put this on a line of the .ini: `AppDomainSetup_ShadowCopyFiles=True` I also tried it as a string [after reading this](http://stackoverflow.com/questions/1862434/why-is-appdomainsetup-shadowcopyfiles-a-string): `AppDomainSetup_ShadowCopyFiles="True"` That didn't work either. Any more thoughts along this line that I can try? – Ryan Lundy Jul 24 '13 at 20:24
  • @Kyralessa That's probably because you have an earlier version than LabVIEW 2011. But still, technically the default behavior should be the .NET Framework copying the DLL to a temporary directory `\Local Settings\Application Data\assembly\dll2` before locking it. Maybe you could try with a different version of LabVIEW. – federico-t Jul 24 '13 at 22:39
  • @Campari, actually, I have the trial version of LabView 2012 that I downloaded a month or so ago. – Ryan Lundy Jul 25 '13 at 05:38

6 Answers6

5

What I believe is happening in your application is the following:

When Labview launches, it pulls in the dll of your application, tightly locking it into memory. As such, the file is locked and Visual Studio won't be able to overwrite this file (I have directly seen this behavior in other applications). Since the dll never gets freed until Labview exits, you need to find a way to "trick" Labview into loading a fresh dll every time you re-compile.

Here is what I recommend:

In LabView, instead of loading your dll directly, as suggested by Chris Sterling you'll want to create a "wrapper" dll that will load your specific LabView dll through an interface

By utilizing an interface stored in your wrapper dll you fully decouple the two dlls, which will prevent the wrapper dll from knowing about/locking your primary dll. Later, when you are finished with the debugging, you can directly link the dll to LabView.

Here is roughly how the code should look:

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();
    }

}

By doing it this way, you are loading the dll from memory, and therefore labview never locks your original dll that you compiled. The only real downside with this is that it does make debugging harder, if you want to insert breakpoints, you'll likely need to directly reference the source dll.

Note: One thing I am not sure about, but I believe will "work out" is whether Labview is smart enough to re-construct the object every time it executes your code, or whether it just keeps the same object throughout the session. If it does end up doing the later, you'll need to add code to "reload" the dll from the file system every time you launch your custom widget.

Community
  • 1
  • 1
Aerophilic
  • 885
  • 2
  • 9
  • 22
4

You could create a light DLL wrapper that itself has explicit runtime loading and unloading of your main DLL. That way the wrapper stays locked, but you can update your frequently changing code DLL quickly.

  • Agree - that's the way to go. To simplify things, both DLL's interface can be based on a single interface class, so that the wrapper DLL is completely straightforward and any simple mistakes (like forgetting to add to wrapper a new function added to "background" DLL) are prevented by compiler. – DarkWanderer Jul 24 '13 at 08:40
  • ...And later, the wrapper DLL can be seamlessly replaced by the main DLL. Really nice! :) – DarkWanderer Jul 24 '13 at 08:41
  • It's an idea, but it's more of a workaround than a solution, and I'm not thrilled about having to do this in every .NET project used in LabView. Also, how is this different from what Alex Gutierrez answered earlier? – Ryan Lundy Jul 24 '13 at 20:26
  • This approach doesn't have the potential headaches Alex mentions as it works in the same was as your final production DLLs will. The best solution is to get LabView to change their code, but practically this will work for you straight away. – Chris Sterling Jul 25 '13 at 07:08
  • Let me be more specific. Your solution looks to be *exactly* the same as what Alex mentioned, only yours has less detail. If there's some way in which your answer differs from his, can you tell me precisely what that is? – Ryan Lundy Jul 25 '13 at 11:18
  • As I understand it LabView loads and locks your DLL (as you don't want to exit LabView, this lock remains so you can't compile and update your DLL). Alex's solution as I read it looks to load LabView itself as a DLL/assembly? I'm not a user of LabView so apologies if I've got this upside down. – Chris Sterling Jul 25 '13 at 15:10
  • Functionally, I don't believe there *is* a difference, even by using a separate dll approach, you would still need to use in this new dll the guts I detailed. Kyralessa, I assume you are using an interop library to talk to Labview? or are you using something else? – Aerophilic Jul 25 '13 at 20:19
  • I'm calling a .NET assembly from within LabView. LabView calls the C# method and uses the result. – Ryan Lundy Jul 26 '13 at 08:58
  • Got it, in that case I believe you really will want to do as they suggest here, combining it with the code mentioned below. If you don't do something like this, you won't actually get your freshly compiled dll. I will update my answer with this new information. – Aerophilic Jul 27 '13 at 04:48
2

I'm doing a test in LV2012 with a C# class with a new custom class in a separate folder from the Labview VI. I'm able to recompile the C# code in VS2010 without having to close out Labview, but Labview doesn't see the changes to the DLL (if any are made). For Labview to see the changes in my test case, it needs to be fully closed and reopened.

For Labview C++ DLLs, you for sure have to close down the calling VIs, as the reference to the DLL is left open. You only need to close down to the Labview Start-up pane though.

You can have VS automatically spawn Labview.exe in a C# project by going to Project->Properties->Debug->Start External Program. When you hit F5 in VS, the DLL compiles and spawns Labview. However, VS doesn't automatically attach the DLL to process, which is really, really obnoxious. Dunno if that helps or not.

Personally, I like the way C# methods integrate with Labview, but find C++ more powerful. Working with C++, you can also spawn Labview in a similar way as above, but it automatically attaches the DLL to the Labview.exe process, making debugging a one step process of just hitting F5. You can still use classes and such in C++, you just have to wrap C functions to call them in Labview. Given the one step debugging and power of C++, I find it superior to C# when using external code in Labview.

Austin
  • 1,018
  • 9
  • 20
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.

Yair
  • 2,266
  • 12
  • 12
  • Well, I've added the .NET class to my LabView diagram, but the LabView project isn't actually running at the moment. It seems that just adding the class to the diagram is sufficient to lock the DLL, unfortunately. That's what I'm looking to solve. – Ryan Lundy Jun 27 '13 at 17:37
1

get http://www.emptyloop.com/unlocker/ unlocker -h for its comand line options

run in prebuild. with unlock command on relevante dlls.

if only unlock doesn't help use unlock+delete.

simple as

Unlocker mydllpath.dll /s /d

Nahum
  • 6,959
  • 12
  • 48
  • 69
1

You'll find that this behavior changes depending on how the dll is distributed. If Labview is calling the assembly by a static location on disc (specified by a path input), you'll find that you cannot rebuild the dll while the Labview application is open.

However, if the dll is registered and Labview accesses it by name, you can rebuild and reinstall to your heart's content, and Labview will update its reference to the DLL once it is closed and reopened.

I accidentally stumbled across this when sharing a .Net assembly through COM Interop, as well as installing it to the GAC.

There used to be KnowledgeBase articles on this topic as recently as 2017, but they appear to be missing now.

I've included the official Labview help guide on loading assemblies here.

Community
  • 1
  • 1