From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Exe not working with VI server.

I'm trying to force an ARINC function to stay in memory. 

 

My primary need is to set up a bunch of function to run as separate executables with the parameters as the functions of each. Discrete_Set(Channel) would equate to "Discrete.exe Set 'Channel'" in the DOS prompt. 

 

ARINC

Analog

Discrete

Power

 

The Analog, Discrete, & Power aren't so bad because you can initialize, set, and close the function within one call and the information stays on the hardware (6723 & GPIB Power Supply). The problem comes when you need to make a call to ARINC to initialize. Then go do something else, then tell ARINC to schedule some data, then do something else, then read some data, then do something else, etc. 

 

The problem is that I'm losing the memory for the ARINC card and by the time I go schedule data, the card returns a 'Board not loaded' error, which basically means it wasn't initialized, which isn't true because it's been loaded in a previous function. I'm trying to force the ARINC.vi to stay in memory while I go off and do other things. I initially had it set up as an action engine but the closing of the run-time engine flushed the memory anyways. Now that I have it set up as a VI server, it forces the action engine to stay in memory so I can make multiple calls at various times, however that isn't working for some reason. Everything seems to work on my PC but not on the PC with the run-time engine installed.

0 Kudos
Message 11 of 21
(1,271 Views)

I thought I had it working when I added 

 

 

server.tcp.enabled=True
server.tcp.access=127.0.0.1
server.tcp.port=3363
to the end of the .ini file, but instead of saving everything in the VI server, it just went back to the old way of dumping all the memory in-between function calls.

 

0 Kudos
Message 12 of 21
(1,269 Views)

It is interesting that you are having problems with this. I do not know any reason for a connection to a peice of hardware to drop and cause it to think you didn't initialise it except if the thread that it was initialised in was terminated.  However, if this is the reason for it to reset, then puting it into its own thread would definitely fix the problem, but only if the thread has a lifetime that meets or exceeds the time that you are going to be accessing it.  I.e. if you execute it, wait for it to complete and then move on, then try executing it again, it will NOT work as the thread had terminated which would result in returning all resources assigned to that thread (including the board's driver) back to the void.  You would need a state engine that would respond to events or some other communication mechinism for it to do things of use.

 

But given your current code, I'm going to ask again, and I would like it if you would answer these questions:

1. Did you add the vi that you are executing to the build as a dynamic VI?

2. OR are you trying to have this module as a seperate Executable?

0 Kudos
Message 13 of 21
(1,256 Views)

 


@NelsonUWP wrote:

I thought I had it working when I added 

 

 

server.tcp.enabled=True
server.tcp.access=127.0.0.1
server.tcp.port=3363
to the end of the .ini file, but instead of saving everything in the VI server, it just went back to the old way of dumping all the memory in-between function calls.

 


try this: right click on My Computer in the LV project and enable TCP there.  This ought to be the same as changing the .ini file, but it might not, and you may not have all the right ini flags there (I see 'server.tcp.serviceName="My Computer/VI Server"' in the first one I looked at, built in LV9sp1)

 

-Barrett
CLD
0 Kudos
Message 14 of 21
(1,246 Views)

I added it as a dynamic VI, so what I was trying to was do was keep a DLL in memory because it was getting flushed at the end of every EXE function. I wanted to do an ARINC_Initialize which initialized the function and called to ARINC - Action Engine.vi (my func. global) then make a call to ARINC_Schedule, which used the same ARINC - Action Engine.vi to schedule message to the ARINC card. while the ARINC - Action Engine is open, the DLL should stay loaded in memory.

0 Kudos
Message 15 of 21
(1,244 Views)

 


@NelsonUWP wrote:

I added it as a dynamic VI, so what I was trying to was do was keep a DLL in memory because it was getting flushed at the end of every EXE function. I wanted to do an ARINC_Initialize which initialized the function and called to ARINC - Action Engine.vi (my func. global) then make a call to ARINC_Schedule, which used the same ARINC - Action Engine.vi to schedule message to the ARINC card. while the ARINC - Action Engine is open, the DLL should stay loaded in memory.


 

So the dynamic VI was added to the build???????????????  Does the executable run on your development machine as well as in the LV development environment?  Also, what do you mean by "at the end of every EXE function"?

 

Seems we are having a failure to communicate. 😞

0 Kudos
Message 16 of 21
(1,241 Views)

Ok, let's start over

 

ARINC.exe is a shell which contains some functions: Initialize, Schedule, & Read. These functions will be exercised with calls from the command line ARINC.exe Initialize will send the first parameter ("Initialize") to a case statement and run the "Initialize" case which will run the initialization routine. ARINC.exe Schedule ..... will send the first parameter ("Schedule") to the case statement for "Schedule" which will schedule data to the channel. ARINC.exe Read .... will send the first parameter ("Read") the the same case statement and run the "Read" case, which reads data on a certain channel. I also have functions for Discrete, Analog, and Power in Discrete.exe, Analog.exe, and Power.exe, respectively. When I run the ARINC routines in my project, everything works perfectly, the card initializes, schedules and reads data as you should expect.

 

When I build my executables, the Analog, Discrete, and Power routines work perfectly, while the ARINC executable does not. This is because I'm making explicit use of the ARINC's DLL (compared to the NI stuff which initializes, sets, and closed for each call because the output is static) which gets unloaded after the "ARINC.exe Initialize" finishes and by the time I get to "ARINC.exe Schedule ......" the DLL has been unloaded since the Initialize call and no longer recognizes the card. I'm trying to force the DLL to stay in memory by using a functional global. Because the functional globals get unloaded as soon as the EXE is finished running (because run-time engine shuts down) I need to use VI server to dynamically call the functional global. I'm adding this functional global "ARINC - Action Engine.vi" to my project by 'Always Including' it in my project and using the proper folders when I'm referencing it.

 

The problem I'm running into is when I try to use the VI server to access the same functional global (across the same EXE, just different instances, none of which are at the same time, always open/do something/close/next exe) it either hangs because I don't close the reference or pretends like it's the first instance each time. 

 

My main goal is to try to find a way to keep the DLL loaded in memory. I've tried creating a background program that just makes a call to a status DLL function and keeps the program open until I explicitly close it. This doesn't work because the program creates a different instance of the DLL. I'm trying the Action Engine route because the same program should stay open and retain the memory for each dynamic call to it.

0 Kudos
Message 17 of 21
(1,233 Views)

Ahh, so this is to be run from the command line to interact with this DLL? For use in a shell script/batch file?

 

I am surprised that works for the others (Discrete.exe, Analog.exe, and Power.exe) if they are referencing DLLs to control a piece of HW.  But anyway, now that I (think I) understand what you are trying to accomplish, yes, that shouldn't work (at least in my mind it shouldn't the way you are doing it).  I would think you need to use the same DLL reference that you initialised on.  Using it on another EXE instance will most likely fail unless it was designed to do so (which seem to be the case for your other executables if they use DLLs for accessing the HW).

 

Oh, but wait, is that what your VI server is doing?  Having a VI Server just so that you can run some VI passing parameters to it?  If so this could work but the DLL may shut down as soon as the VI has finished executing.  Not sure how DLL binding works in LV, but if it is similar to other LV objects, it may do cleanup if the thread stops.  So you can do one of two things:

 

1. Make it do the initialise, call, shutdown like the other DLLs you are describing.  You can do this by storing the initialisation in the USR (type 2 global) or a regular global, which is then sent every time.  This is slower, but may not be an issue for your application.

 

2. Don't make it stop.  Make it into an event server instead.  I've used FP objects to pass events to event severs.  To do this, your code will need to find the Parameters control and then signal it.  That's pretty easy:

Signal Another VI.PNG

 

Panel's refnum input is the remote VI's refnum.  This will allow you to talk to your event server so then you just make your event server wait on a change of value on it's Parameter string input box and execute stuff as appropriate.

 

Is this what you are looking for?

 

Mind you, I'm thinking that you be having some other problem.  Could it be you don't have a server running?  Do you see it in the process list?  You MUST have the server running or at least not terminate on you.  If your server is not running, you will not be able to communicate with it.  If you are going to try the way you have it currently to see if it works (because it might), you will have to execute it and have it not exit when it is done.  To do this, you would open a reference to the Top Level VI so that if the window is closed, it will not terminate.  That reference could then be closed using your communication scheme.  You will have to work out the legistics though.

 

Personally, I prefer just having an event server, having something just sit there in a non running state is not, er, elegant IMHO, but if it works, it works.

 

 

A

0 Kudos
Message 18 of 21
(1,223 Views)

 


@Been bitten by LabVIEW wrote:

Ahh, so this is to be run from the command line to interact with this DLL? For use in a shell script/batch file?


Correct, which is why I need to make separate calls to the executables.

 

 


@Been bitten by LabVIEW wrote:

I am surprised that works for the others (Discrete.exe, Analog.exe, and Power.exe) if they are referencing DLLs to control a piece of HW.  


This is because the Discretes & Analog use the 6723 and the software supplied with DAQmx, also because they are static updates. Get the handle of the hardware (Dev1/ao0, Dev1/line0/port0), write the static output, close the handle. The Power is just a GPIB SCPI command to an Agilent supply. All of the actions are done in a single function, unlike ARINC which initializes in one call and then needs to schedule in another.


@Been bitten by LabVIEW wrote:

Oh, but wait, is that what your VI server is doing?  Having a VI Server just so that you can run some VI passing parameters to it?  If so this could work but the DLL may shut down as soon as the VI has finished executing.  Not sure how DLL binding works in LV, but if it is similar to other LV objects, it may do cleanup if the thread stops.  So you can do one of two things:

 

1. Make it do the initialise, call, shutdown like the other DLLs you are describing.  You can do this by storing the initialisation in the USR (type 2 global) or a regular global, which is then sent every time.  This is slower, but may not be an issue for your application.

 

2. Don't make it stop.  Make it into an event server instead.  I've used FP objects to pass events to event severs.  To do this, your code will need to find the Parameters control and then signal it.  That's pretty easy:

 

Mind you, I'm thinking that you be having some other problem.  Could it be you don't have a server running?  Do you see it in the process list?  You MUST have the server running or at least not terminate on you.  If your server is not running, you will not be able to communicate with it.  If you are going to try the way you have it currently to see if it works (because it might), you will have to execute it and have it not exit when it is done.  To do this, you would open a reference to the Top Level VI so that if the window is closed, it will not terminate.  That reference could then be closed using your communication scheme.  You will have to work out the legistics though.

 

Personally, I prefer just having an event server, having something just sit there in a non running state is not, er, elegant IMHO, but if it works, it works.


Those were some good ideas, however I got an email from NI stating that you can't pass information between two separate executables, this causes a problem because ARINC.exe won't open the same application reference as ARINC.exe the next time it is called (at least thats how support explained it). This completely undermines my ARINC action engine idea because each call to VI server will be different than the last, which is what I was seeing when I added the info I talked about earlier to ARINC.ini.

 

 

What I ended up doing was creating a wrapper around all my ARINC commands (ARINC_Client.exe) which is always kept running and use TCP/IP from ARINC.exe to execute the functions (see attachment). This forces the DLL to stay loaded in memory (because it is never unloaded) and I can still make calls from my script. The only thing I need to do now is pass back some sort of response from the Client signaling that operation is complete.

 

0 Kudos
Message 19 of 21
(1,177 Views)

 


@NelsonUWP wrote:

 


Those were some good ideas, however I got an email from NI stating that you can't pass information between two separate executables, this causes a problem because ARINC.exe won't open the same application reference as ARINC.exe the next time it is called (at least thats how support explained it). This completely undermines my ARINC action engine idea because each call to VI server will be different than the last, which is what I was seeing when I added the info I talked about earlier to ARINC.ini.

 

 

What I ended up doing was creating a wrapper around all my ARINC commands (ARINC_Client.exe) which is always kept running and use TCP/IP from ARINC.exe to execute the functions (see attachment). This forces the DLL to stay loaded in memory (because it is never unloaded) and I can still make calls from my script. The only thing I need to do now is pass back some sort of response from the Client signaling that operation is complete.

 


 

Well, what do they mean by "you can't pass information between two separate executables"?  Of course you can!!  However, if they are referring to if you can pass an event to a control in a separate executable, well, I tried and though it worked, it was flaky with the signaling part IIRC. But that was in LV 7.0, I would have thought they would have fixed that by now.  I had to write my own TCP interface to signal to a control.  Anyway, what you have done looks about right (though I would call it the server not the client and will be referring to it as such from here on), but did you know that a TCP connection is bidirectional?

 

In your server, you can write back to the same connection and in your client you can wait for a response making this synchronous.  Also, I would close the TCP connection on your server or you may get memory leaks.  Also, maybe it would be good to have a command to shutdown your server too instead of or in addition to a stop button?

 

When I do a generic connection, I pass a cluster of two strings, first is a command and the second is the parameters or data.  This way, I have a way of controlling what happens more easily.

 

Also, I HATE POLLING!  I don't know why everyone does it when it is not necessary.  Perhaps it is more intuitive?  I dunno.

 

Here is an example of a non polling system:

 

TCP-client-server.PNG

 

I used to use that TCP Listen.vi block but found it restrictive in that I couldn't shutdown my server.  I mentioned in the diagram that you don't have to write back and just close the connection.  This is true, but if you do that, the TCP Read block will give an error.  You would just have to code for that if you were not to send any information back but still wait.

 

Hope this helps.

 

 

A

0 Kudos
Message 20 of 21
(1,166 Views)