How to quit MATLAB process using C# and COM? - c#

I have a this code that calls a MATLAB function (displayFigure.m) from a C# client. Each time I update the .m file, the changes are not reflected when the C# program is rerun.
public void CallMLfunc(){
MLApp.MLApp matlab = new MLApp.MLApp();
matlab.Feval("displayFigure", 0, out result, input);
matlab.Quit();
}
Tried to terminate the MATLAB.exe process using
matlab.execute("quit;");
and will get the following an unhandled exception: System.Runtime.InteropServices.COMException.
After force quitting the program I rerun it again an displayFigure.m (version 2) is reflected. Is there another to quit the MATLAB process?

There's a MATLAB.exe in the process list for the COM object. Sometimes there's a visible window you can close. Sometimes there isn't. You may have more than one MATLAB.exe, especially if you are debugging and the MATLAB editor is open, you'll have that instance running as well. The matlab.Quit(); should terminate the MATLAB.exe associated with the COM object, but if there is an Exception during the matlab.Feval(), or breakpoint, etc., it might not execute. When I have that problem, I terminate the MATLAB.exe with the highest PID.

Related

Starting [detached] external application from C#

When start another process using Process() class, newly created process is still associated with the one invoked the start command, which is in turn causing issues with monitoring software or even within the stirted application itself.
So the question is if it is possible to start an external binary detachad from the caller, as a fully standalone instance? (Like started directly)
Update:
There are some processes expected to be a subprocesses of a specific process.
Like IE usually a subprocess of explorer.exe.
But started from C# app.exe with Process().start(#"path/to/iexplere.exe") it is a subprocess of app.exe
So is it possible to attach it to expected explorer.exe?
The most common approach is to start an intermediate process (let's call it the child) that in turn starts the binary you want to detach (the grandchild).
The intermediate process is then terminated, leaving the grandchild without direct parents.
You are not showing any code, so we can't help you more than that. You can start from here.
I've found a workaround for it.
It includes two applications. Lets call them handle.exe and detacher.exe
handle code:
static void Main(string[] args)
{
Process.Start(AppDomain.CurrentDomain.BaseDirectory + "detacher.exe");
Console.ReadLine();
}
detacher code:
static void Main(string[] args)
{
Process.Start("IExplore.exe", "google.com");
}
handle starts detacher and proceeds.
detacher starts IE and terminates.
IE drops to process root and proceeds.

running matlab m-file from c# console application no longer working

I have a c# console application.
The program is very simple. It simply opens a Matlab application & specifies the directory of the m-file I wish to run, supplying one parameter (code is below). The code in the m-file basically uploads some data to a datbase. After this an excel report is created from the data uploaded to the database.
I have this task scheduled to run at 4am. The code worked fine for the first two months. However (without any changes I'm aware of) the code is not working. I come in the morning to see that it has opened an instance of matlab & it has changed the matlab directory but it does not appeared to have run the matlab function. Its strange as the c# code then runs the excel code afterwards which reprots there is no data in the database. When I come in and run the code manually though the code works fine. I don't know what is happening or how to find out what is going on?
In windows scheduled the task has the message "the operation completed successfully. (0x0)
public void CalculateFundDrift()
{
try
{
// create matlab instance
_matlab = new MLApp.MLApp();
// change to the directory where the function is located
_matlab.Execute(#"cd c:\my_directory\");
// define the output
object result = null;
// call the matlab function upload_data
_matlab.Feval("my_func_name", 0, out result, "my_para");
// quit matlab
Console.WriteLine(Environment.NewLine + "Closing Matlab");
_matlab.Quit();
}
catch(Exception ex)
{
_matlab.Quit();
throw;
}
}
Update
One thing I do no notice when running the code is that it opens a matlab command window (looks more like a text file). In the morning when I come in its an actual matlab application that has been left open.

Determining when a process has finalized initialization

I'm building an IronPython module that initializes an instance of AutoCAD and I need to return 1 to the module calling it after AutoCAD has finished initializing, entered its message loop and is in a stable (not loading dependencies/anything) state. I've tried using System.Diagnostics.Process.WaitForInputIdle() with no luck.
Here's what I have so far:
import System.Diagnostics as sysdiag
def start_autocad(self):
print("\"C:\\Program Files\\Autodesk\\Autodesk AutoCAD Civil 3D 2014\\acad.exe\" /b \"C:\\Temp\\C3DAutoScript.scr\"")
for process in sysdiag.Process.GetProcessesByName("acad"):
process.Kill()
try:
acad_process = sysdiag.Process.Start("C:\\Program Files\\Autodesk\\Autodesk AutoCAD Civil 3D 2014\\acad.exe", " /b \"C:\\Temp\\C3DAutoScript.scr\"")
acad_process.WaitForInputIdle()
return 1
except:
return 0
Unfortunately, this function as it stands returns as soon as the process begins opening, not after it's done. Does anyone know a way to handle this either in classic cPython, IronPython or C# (without using an overkill sleep function to wait for it)?
A process can start processing messages almost immediately after start up. There is no requirement that the main window is displayed before this is done. This can be done to avoid being displayed as hanging, in case loading is slow.
You can either try interacting with the process after WaitForInputIdle returns — it may eventually respond even while "loading". If it doesn't work, wait for the main window to appear (using FindWindow). If the application is COM server, you try establishing COM connection.
P.S. Killing processes is not the best idea and may result in corrupted data or configuration. Try closing application properly be sending close event to its main window.
In the title of your question you ask for "a process". In the text of your question you ask specifically for Autocad.
I can tell you how to do it for a process in general, not specifically for Autocad.
I had the same problem and came to the solution to use the API
GetModuleFileNameEx(HANDLE h_Process, ....)
MSDN says:
If the module list in the target process is corrupted or is not yet
initialized, or if the module list changes during the function call as
a result of DLLs being loaded or unloaded, GetModuleFileNameEx may
fail or return incorrect information.
And in deed when you try to get the executable path of the process with this function while the process is still loading it's DLL's the function fails and GetLastError() returns ERROR_INVALID_HANDLE. This does not mean that the process handle that you pass to the function is invalid. But this is the error code you get when the process is still starting up.
I tested it with several applications. It works perfectly.
int WaitForProcess(HANDLE h_Process, int Timeout)
{
for (int T=0; T<=Timeout; T+=50)
{
if (GetModuleFileNameEx(h_Process, NULL, ...) > 0)
return 0;
int Err = GetLastError();
if (Err != ERROR_INVALID_HANDLE) // = 6
return Err;
Sleep(50);
}
return ERROR_TIMEOUT;
}
Why does it work? What GetModuleFileNameEx() does internally is to read the memory of the process (for that you must open the process with access permission PROCESS_VM_READ). But this is not allowed while the process is in the loader lock. The loader lock is active while a process is loading DLL's.
This code is general and works for any application. It waits until the application is ready with it's basic initialization. If this is not enough for you I recommend to wait for the main window of the application to appear.

Conditions for running the program

I wrote a main program in C#, and I worte also a small tool program also in C#.
I want that the tool program will be able to execute under some conditions:
When called from my main program.
When called from open some suffix of file (e.g. "*.abc")
But if the user open my program directory he can run the tool program, and I do not want him to be able to do it. I want him to be able to run the program under the conditions above. And if he ran the program manually, the program automatically shut.
Is there any way to do that?
To check if your main program called it, you could pass the main program's ProcessID as a commandline argument, then in your small program, check if that ProcessID exists and if its process name is the name of your main program. This isn't spoof-proof, but might be a bit trickier to fake than just passing a static number/string.
In addition, you could encrypt the number and pass that, then decrypt it and check the above. It's pretty much impossible to prevent a determined hacker from running your program on its own, but you can raise the bar of how tricky it is to do it. You'd also want to obfuscate your code, otherwise a quick Reflector call will show exactly what characters are being passed.
Alternatively, if possible, you could just make the small program a DLL and call it from your main program like that. This would need a bit of refactoring, but would force your program to be open. As for opening a *.abc file, your program can check the command line arguments to see if a filename was passed through. This can then be processed automatically by your app and the DLL calls can be made.
There is nothing exposed to the process/executing environment that tells it how it was invoked, so there is no foolproof way to do this.
You can have your main program pass in a flag on the command line - this and the suffix are things that you can check for and if either one does not exist you terminate immediately.
However, if the user ever guesses the flag, they can still call the application directly.
Other mechanisms could involve writing a value to a file from your main program just before invoking the second program and checking that file from your second program (and deleting it after execution), as a messaging mechanism. There are other messaging mechanisms that would do similar things (private MSMQ queues for instance).
You can use a named mutex with some hard-to-guess name to make sure that the "small tool" program was called by the main program. So, you create a Mutex in your parent program:
bool requestInitialOwnership = true;
bool mutexWasCreated;
Mutex m = new Mutex(requestInitialOwnership,
"MyMutex",
out mutexWasCreated);
Then in your child program you write the exact same code to check if the parent program executed it. If mutexWasCreated==true, then it was not called by the parent program. Otherwise, it was.
Checking the arguments passed to the program will help to determine whether the filename's extension is .abs or not.

Stalling program until JSFL file finishes

I am trying to run a JSFL script from within a C# project, where the JSFL script opens up a .fla file, modifies it n times, and exports n .swf files before closing. From the C# project, I am starting up the JSFL script through the Process class. I try to wait for the JSFL process to finish through the myProcess.WaitForExit() command, but it doesn't work. The remainder of my code C# executes before the JSFL process finishes exporting its .swf files. Is there any way I can throw something that the C# project can catch from the JSFL file or some other solution?
One solution (although most likely not the best one) would be for your C# code to look for the SWF files being created. Only once they've been updated/created will the JSFL script have finished, so you know that it will be safe for your C# to move on. In case there is no way of knowing how many SWF files the C# program needs to look for, you could instead let the JSFL script write to a log file of some sort, and to have the C# program read that log on a interval, looking for some sort of token to indicate that the JSFL script has completed it's task.
Granted, this may be far from the best method (and I don't know C# well enough to know whether what you're seeing is by design or a sign of something being wrong). But it may just be the case that running JSFL/Flash is completely asynchronous and if so, maybe the log file approach is the quickest path to solving the problem.
I have the same problem with another application that calls an external JSFL script.
What I do is write a file once finished to a target directory, and in the calling application, poll for that file. As soon as the file appears, I know the task has finished, and I delete the temp file, and carry on. Oh - and before starting I look for and delete any temp files so I don't get a false positive.
It's not so nice as events, but you have to work with what you've got.
Have you tried to set a custom Listener that will execute a function when the JSFL done. Don't forget that it's still based on ECMA which is a procedual language.
By the way, JSFL has a LOW-LEVEL C API.
C LEVEL API
This is absolutely possible, and I've already posted a solution here on stack overflow, complete with a detailed problem description and all the C# and JSFL source code necessary to implement it: Automating publishing of FLA files; calling Process.Start multiple times
To summarize... first of all, waiting on the JSFL script process is useless, because you're actually calling Flash.exe, which will remain open/running after the JSFL completes, so you'd be waiting on a process exit event that will never occur.
The trick is to use a JSFL function at the end of the JSFL script which executes a windows command line command, and it's that call which will signal your C# app that the JSLF script has completed. So basically you'll have your main instance of your C# app, but you want to modify your C# app so that a 2nd instance can be run from a command line with a particular switch. When you're C# app is called with a particular switch (from the JSLF file), then instead of running normally, you want your program to simply signal a wait handle in the main instance of your application and then close. I use a simple third-party open-source library called XDMessaging, which facilitates such inter-process communication. It lets you open a named channel in your C# app, which can receive a command from the 2nd instance, signaling the main instance that the JSFL script has finished and it's safe to continue.
But involving file watcher like this is not the best solution so I catch the Flash process and keep watch on the process title and tell the JSFL render some window title for the flash window after finish the execution.

Categories

Resources