Running Matlab GUI from C# - c#

In my project, I am integrating Matlab GUI application with in a C# application.
The solution I thought about is to create a standalone application from the Matlab GUI and start it via a button in C#:
Process exeProcess = Process.Start("Data_Capture_Direct_call.exe");
if(!exeProcess.HasExited)
{
exeProcess.WaitForExit();
}
exeProcess.Close();
The problem is that after the splash screen of Matlab GUI is closed and before the actual program opens, C# detects that the program has been closed already and carries on to the next line.
In addition, the next few lines of code are not properly executed:
List<String> Movement = new List<String>();
List<String> Repetition = new List<String>();
List<String> Duration = new List<String>();
using (CsvFileReader reader = new CsvFileReader("capture.csv"))
{
CsvRow row = new CsvRow();
while (reader.ReadRow(row))
{
Movement.Add(row[0]);
Repetition.Add(row[1]);
Duration.Add(row[2]);
}
}
for (int i = 1; i < Movement.Count; i++)
{
dataGridView1.Rows.Add(i, Movement[i], Repetition[i], Duration[i]);
}
What happens is that after the C# wrongly detects closure of the process, the capture.csv file becomes empty and data is not loaded into the data grid.
Please let me know where I am making a mistake or if there is a better way to do this!

In my solution you should do some settings before starting code in order to use Matlab instance in a C# application.
Adding neccessary dll :
First we will add dll reference with COM interface. Click RMB on project and choose [Add Reference] option. In new window click COM tab. In search text box write 'Matlab'. Then choose "Matlab Application (Version 7.10) Type Library".
You should get references like below :
Now you can easily do whatever you can do on Matlab in C# . Lets give an basic example :
var acCtx = Type.GetTypeFromProgID("matlab.application.single");
var matlab = (MLApp.MLApp)Activator.CreateInstance(acCtx);
these two lines are creating of matlab instance in code.Now let's make a easy computation on Matlab.
Console.WriteLine(matlab.Execute("1+2")); // This will output 3 on console.
matlab.Quit(); // you should close matlab in order to clean memory
Lets give solution to your actual problem.You want to execute a Matlab GUI program.And I think your Gui is recording some data to CSV file.Then your C# program processes that data.You should note that you can call your GUI in Matlab just writing your name of program as command.Suppose that you have a GUI called myGui.m.You can call that gui by calling myGui in command line as you can write 1+2 to get 3.
Let's call gui.
matlab.Execute("myGui"); // This will execute your Gui. You can use buttons to save data to CSV file
matlab.Quit();
I have extended example on this page :
Source

Related

Stand alone ".exe" matlab file not saving images

I'm trying to create an ".exe" file that will read some sort of data(for a known path), and will plot it one time as "bplot" and the other time as "histogram".
The code works fine as I run it from the editor, and even after I've made an ".exe" file. The problem begins when I try to run it from a "C#" code with the command "Process.Start(#"my_path.exe")". It seems like it runs the code and I can see the figures that are made, but it doesn't save the pictures.
My matlab code is:
clear
clc
P = csvread('my_path\test_csv.csv');
SP = bplot(P);
pause (3);
saveas(figure(1),[pwd '\picture1.jpeg']);
pause (3)
B = csvread('my_path\test2_csv.csv');
histogram(B);
pause (3)
saveas(figure(1),[pwd '\picture2.jpeg']);
pause (3)
close
clear
clc
The "bplot" is an external function that I downloaded.
Any ideas how to save it in other way so the stand alone application will save the images when I call it from C# code?
Try using the syntax with ProcessStartInfo parameter (see here), rather than syntax with the path the file directly.
Indeed if not setting ProcessStartInfo.WorkingDirectory, it will be considered to be %SYSTEMROOT%\System32 (for which you don't have write access as normal user)
var startInfo = new ProcessStartInfo(#"my_path.exe");
startInfo.WorkingDirectory= .... you exe dir or something else....;
Process.Start(startInfo);

Print data from VB.net into c# windows form

I have application made from 2 solutions. One made in Visual Basics other in C# which is console-application.
I'm trying to remake that program into windows form application, however, all output is made using Console.WriteLine() commands. Output from C# I could quite easily get with richTextBox.AppendText().
When trying to output from Visual basic part, I can't do that, as I understand it's due to that fact that it is reference. What I could do to solve this?
You can do it in the VisualBasic part like this (it shows it in C# but it's quite similar in VisualBasic): take a StringBuilder and add all your old statements there and then put it in the TextBox as once:
//// Your old code:
//Console.WriteLine("xyz1");
//// Do anything...
//Console.WriteLine("xyz2");
//// Do anything...
//Console.WriteLine("xyz3");
//// Your new code:
StringBuilder sb = new StringBuilder();
sb.AppendLine("xyz1");
//// Do anything...
sb.AppendLine("xyz2");
//// Do anything...
sb.AppendLine("xyz3");
this.textbox1.Multiline = true;
this.textbox1.Text = sb.ToString();
=> This code will work, if you will need only the results of the Console.WriteLine() Messages: if you need the Messages immediately, you will probably need a splash screen, like this: Making a splash screen, or How to build splash screen in windows forms application? or a ProgressBar maybe could help you: How to use WinForms progress bar?

Calling a Windows Forms Application via C# API

I have a windows form application written in C# that allows me to point to a folder of images and parse those images into a easily view able format for a user. This is a stand alone application and it works fine. I want to extend this application so that instead of it parsing a folder of images, I can hand it a prebuilt data set, with all of the images and meta data preset by an external application via an API.
I have been able to compile the application into a class library and access the classes and structs to actually build the data set without issue, the problem I am having now is launching the application externally with the data set I have built.
For context, I am writing a tool that will allow the user to call this windows form application from Spotfire. Inside of spotfire I am parsing a DataTable object and building the data set from the information I have. Once this data set is built I need to be able to launch the application as a stand-alone process instead of calling the forms explicitly inside of Spotfire. (This is due to a limitation of GUI threads in Spotfire and we can't call a multi threaded process in a single threaded application as well as we want to keep the Spotfire GUI responsive which can't be done if we call the forms directly)
I know I can launch the exe standalone using Process.Start(), however this doesn't let me pass my information to teh application. How can I build this application to allow me to pass information to it? I've been trying to google examples of how to do this and keep coming up empty handed as people will reference ASP.net or things that are over my head.
Thank you in advance!
EDIT: An example of an application that handles this really well is below. We use DPlot Jr to create graphs externally. The dplot.dll exposes the following function:
[System.Runtime.InteropServices.DllImport("dplotlib64.dll")]
public static extern int DPlot_Plot8(
ref DPLOT d, double[] x, double[] y, string cmds);
which I can then use in my code
docNum = dplot.DPlot_Plot8(ref dPlot, X, Y, cmds);
docNums.Add(docNum);
calling this function in this way actually launches the dplot application and passes the object I've built "dPlot" along with the X and Y data in order to plot the information. I would like to build something like this in my windows form application in order to be able to launch it easily from an external application. Unfortunately I don't know how this function works inside the .dll
EDIT2: I have been able to modify the runtime via the commandline as suggested by Aybe. In my desktop application I have created a conditonal in the main program like so.
if (args.Length == 0 && false)
{
Application.Run(new frmWaveFormViewer());
}
else
{
DataSet dataSet = new DataSet();
//dataSet.LoadMetaData(args[0]);
dataSet.LoadMetaData(#"C:\Users\a0273881\AppData\Local\Temp\tmp1141.tmp");
Application.Run(new frmWaveFormViewer(dataSet));
}
the user can then call the forms externally by using the following...
DataSet dataSet = new DataSet(dpList);
dataSet.PrintDatasetMetadataToFile(String.Format(#"C:\Spotfire\DataSetTesting_{0}.csv", DateTime.Now.ToString("yyyyMMdd_HHmmss")));
string args = dataSet.GetMetaData();
ProcessStartInfo starter = new ProcessStartInfo();
starter.FileName = #"C:\Users\a0273881\Desktop\WaveFormViewer.exe";
starter.Arguments = args;
Process.Start(starter);
However, this is not easy to use for other developers.
I am starting to look into WCF, can anyone provide good resources on WCF for dummies? I'm currently reading through: http://www.codemag.com/article/0705041
I have been able to spawn a NamedPipeServer on the application when it is launched. The named pipeserver names itself tagged with the name of the application + the process id that it spawns with. The process number is logged to a ini file in the users appdata folder. The process can be started with an optional command line argument to effect the value of the "callingApplication" which is the INI Header. This way, we can create multiple instances of the application from different callers without interfering and ensuring connection to the correct named pipe.
static void Main(string[] args)
{
string callingApplication = "None";
if (args.Length != 0)
{
callingApplication = args[0];
}
int pId = Process.GetCurrentProcess().Id;
PipeServer.StartPipeServer(pId, callingApplication);
// do things
PipeServer.StopPipeServer();
}
The PipeClient side is accessed through public functions available in a API static class. Functions that connect through the pipe are all housed in a seperate PipeClient class. These functions require a spawned process id in order to connect to the correct pipe. These are api functions to either launch or return the needed pipe from an api
public static class API
{
public static int SendCommand(int aKey, ...)
{
try
{
PipeClient.StartCommandSendClient(input, aKey);
}
catch (TimeoutException)
{
// returns error codes based on exceptions
}
return 0;
}
}
So with this I've managed to create a link between two applications. All that is really required past this is custom implementation of methods exposed through the API class which have custom client methods to call as well. All of this together is pretty simple to call from my calling app...
int aKey = API.GetKey("callingAppName");
API.SendCommand(aKey, "[Reset()][AddPoint(arg1, arg2, arg3)]");

start another .cs file in C#.net console

Im pretty new in C# so i have a question .
I have 2 files in project (Visual Studio).
I have Program.cs file witch is console application what will be ran when executed But then i have included a .cs file because i have a loop and i want it to run a code all the time.
It checks for one procces and if it exists kills it .
while (!File.Exists("C://ProgramData//myfile2.jpg"))
{
Process[] pname = Process.GetProcessesByName("PROCCES NAME");
if (pname.Length == 0) {
Console.Write("The procces doesnt exist!");
}
else
{
foreach (Process proc in Process.GetProcessesByName("procces name "))
{
proc.Kill();
}
}
Now i want it to runn all the time but i have other commands i want to be executed at the same time
How do i call/start another .cs file so it will be ran .
im using net 2.0
Ideally each of your .cs files will contain a single class definition containing functionality - such as your little loop to check for a process. If you want to run this functionality you need to find your Program.cs, and create an instance of your class in there, then call your method with your eternal loop in it.
If you want to be able to execute all of your classes at once, not in sequence, you'll need to learn about threading, but essentially you can do:
var processThread = new Thread(myClass.CheckForProcess);
processThread.Start();
and then if you want to add some extra logic to be run at the same time, you would add that to a separate class in a new .cs file, create another new thread in your Program.cs, and pass in your other eternally-looping-method.
You'll have to add some logic to stop your Program.cs from quitting, but for now you can just make that be a Console.ReadKey until you understand the language better.
caveat: This is not a sensible way to write software in the long run, but it is what you're looking for, I believe.

How to draw Circle via visual studio Exe with Process Dll in Autocad?

I need to create the circle from my button click via process dll(Acdbmgd.dll ,acmgd.dll).
I am able to create the circle via COM interop dll. But i don't know how to create the Circle using process dll.
Here is the sample code:
Database db = HostApplicationServices.WorkingDatabase;
Document doc = Autodesk.AutoCAD.ApplicationServices.
Application.DocumentManager.GetDocument(db);
// Perform our addition
double res = 5 + 9;
// Lock the document before we access it
DocumentLock loc = doc.LockDocument();
using (loc)
{
Transaction tr = db.TransactionManager.StartTransaction();
using (tr)
{
// Create our circle
Circle cir =
new Circle(new Point3d(0, 0, 0), new Vector3d(0, 0, 1), res);
cir.SetDatabaseDefaults(db);
// Add it to the current space
BlockTableRecord btr = (BlockTableRecord)tr
.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
btr.AppendEntity(cir);
tr.AddNewlyCreatedDBObject(cir, true);
// Commit the transaction
tr.Commit();
}
}
While i execute above code in button click means in runtime error throws like "The specified module could not be found".
But if i create one separate dll then i refer that dll in my project and create object for that means it's working
But i need to run the code in debug mode so i need to work with exe.Is there anyway to do via exe?
Thanks in advance..
In process dlls need to be loaded into AutoCAD. Use NetLoad to make the defined commands available to you. The command you intend to call needs to be public, and have the following command flag:
[CommandMethod("MyCircle")]
public static void MyCircle()
{
...
}
Once you've compiled your dll and loaded it into AutoCAD, typing MyCircle into the command line will invoke your defined method.

Categories