Error in MATLAB COM Automation - vb.net

Anyone knows how to do MATLAB COM autiomation in VB.NET? Since I really can't make my program works using the NE builder. I tried using the COM automation as documented here: http://www.mathworks.com/help/matlab/matlab_external/call-a-matlab-function-from-visual-basic-net-client.html
Again, my program is so simple. Here's the matlab code:
function out = addMe(a,b)
out = a + b;
end
Here's the VB code:
Public Class Form1
Dim a As Integer = 4
Dim b As Integer = 10
Dim result As String
Dim Matlab As Object
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Matlab = CreateObject("Matlab.Application")
result = Matlab.Execute("cd C:\Users\Elvin Gentiles\Desktop\Program")
result = Matlab.Execute("addMe(a,b)")
TextBox1.Text = result
End Sub
End Class
The result that I'm getting that is showing in the textbox is: ??? Undefined function or variable 'a'. I already made sure that the COM reference is already added.
But when I tried changing the code to this it is working. By the way, version is a matlab command used to show the version of the MATLAB.
result = Matlab.Execute("version")
I hope you can help me with this. I really needed this. Thanks

Everythings working perfect - COM-wise.
Ask yourself: what did you expect the function to return?
If the code above is complete, you defined neither a nor b in the matlab-session, so matlab of course complains about a not being defined.
Try
result = Matlab.Execute("addMe(1,2)")
instead.

Related

Creating a new IUI Automation Handler object in order to subscribe to an automation event

So, here it goes. To start, A disclaimer, I understand that MS Access is not built for this kind of work. It is my only option at this time.
I have done just a bit of Automation using UIAutomationClient and I have successfully used its other features, however I cannot for the life of me get it to subscribe to events.
Normally, it is supposed to be a bit like this:
Dim CUI as new CUIAutomation
Dim FocusHandler as IUIAutomationFocusChangedEventHandler
Set FocusHandler = new IUIAutomationFocusChangedEventHandler(onFocusChanged)
C.AddFocusChangedEventHandler(Element,TreeScope_Children, null, FocusHandler)
end function
'
'
Function onFocusChanged(src as Object, args as AutomationEventArgs)
''my code here
end function
Yet when I attempt this, I get the error "expected end of statement" on the line:
FocusHandler = new IUIAutomationFocusChangedEventHandler(onFocusChanged)
additionally, if I leave off the (onFocusChanged) I get the error "Invalid use of new Keyword".
It seems like I am missing a reference somewhere. The usual drop down when using "new" does not contain the IUI handler classes though they are in the object library.
I am not sure if there is just some piece I am not accounting for in the code since I am using vba, but all examples seem to be for .net or C#/C++. Any help would be appreciated.
Additionally, I have no problem finding the element in question and all other pieces work fine. If you need any other pieces of the code let me know.
Edit: added set to line 3. No change in the problem though.
After two years this probably isn't relevant any more, but perhaps somebody else encounters this problem... The answer is to create a new class that implements the HandleAutomationEvent method.
Here I created a class named clsInvokeEventHandler and (importantly) set the Instancing property to PublicNotCreatable:
Option Explicit
Implements IUIAutomationEventHandler
Private Sub IUIAutomationEventHandler_HandleAutomationEvent(ByVal sender As UIAutomationClient.IUIAutomationElement, ByVal eventId As Long)
Debug.Print sender.CurrentName
End Sub
And to use it:
Sub StartInvokeHandler()
Dim oUIA As New CUIAutomation8
Dim oRoot As IUIAutomationElement
Dim InvokeHandler As clsInvokeEventHandler
Set InvokeHandler = New clsInvokeEventHandler
Set oRoot = oUIA.GetRootElement
oUIA.AddAutomationEventHandler UIA_Invoke_InvokedEventId, oRoot, TreeScope_Descendants, Nothing, InvokeHandler
End Sub

ActiveReports not allowing overwrite of jpg after report generation. Windows. VB.NET

Currently, I am utilizing ActiveReports to implement a dynamic image via pathname into a report that is generating.
The Images are being automatically generated as .jpg to a server folder. The Active Reports module imports the files using this code.
Sub ActiveReport_ReportStart
Picture1.Image = System.Drawing.Image.FromFile("path\filename.jpg")
End Sub
The problem I am running into is that this report locks out the jpgs from being overwritten.
I am unsure what could be going wrong, but it seems that the report is still using the image files after the report has been generated.
Am I missing a "disconnect" code piece to ensure that an import doesn't allow for continued contact to the file?
I apologize if this is simple, but I can't find anything for this specific instance.
Thank you.
EDIT:
I attempted to get around the lockout by copying them into their own variable. But this didn't work either.
Sub ActiveReport_ReportStart
dim TempImage as Image = Image.FromFile("path\filename")
Picture1.Image = TempImage
End Sub
You can use "Using" block to make sure that the object of the image is disposed as soon as its usage is completed.
Using statement basically marks a boundary for the objects specified in the statement. So when code block using Using – End Using is exited either after normal execution or some exception cause, the framework invokes the Dispose method of these objects automatically.
Here is the suggested code which can be helpful for you in resolving the issue:
Private Sub SectionReport1_ReportStart(sender As Object, e As EventArgs) Handles MyBase.ReportStart
Dim img As Image
Using bmpTemp = New Bitmap("path\filename.jpg")
img = New Bitmap(bmpTemp)
End Using
Picture1.Image = img
End Sub
I was able to get this to work by creating a function that used the Graphics.FromImage method and disposed the original file.
Public Function GetImageFile(ByVal pathfn As String) As Image
Dim tempImg As Image = Image.FromFile(pathfn)
Dim tempBtm As New Bitmap(Width:=img.Width*CorrectFactor, Height:=img.Height*CorrectFactor, Format:=tempImg.PixelFormat)
Using g As Graphics = Graphics.FromImage(bm)
g.DrawImage(tempImg, Point.Empty)
End Using
tempImg.Dispose()
Return tempBtm
End Function
The item that would be placed in the report would be as follows.
Sub ActiveReport_ReportStart
Picture1.Image = GetImageFile("Path\Filename")
End Sub

Getting A NullRefrenceException And Cannot Find Out Why?

My goal here is to create a web browser that has a tab system in VB. Since I cannot explicitly name every single new tab the user will use, I have to make more generalized callings. Here's the conflicting code (my btnGo):
Dim thisBrowser As newWebBrowser = Me.tabBrowser.SelectedTab.Tag
If txtAdressSearch.Text.Contains(".com") Or txtAdressSearch.Text.Contains(".net") Or txtAdressSearch.Text.Contains(".gov") Or txtAdressSearch.Text.Contains(".edu") Or txtAdressSearch.Text.Contains(".org") Then 'More to be checked for
thisBrowser.Navigate(txtAdressSearch.Text)
Else
thisBrowser.Navigate("https://www.google.com/search?sourceid=chrome-psyapi2&rlz=1C1ASAA_enUS445&ion=1&espv=2&ie=UTF-8&q=" + txtAdressSearch.Text)
End If
And here's the newWebBrowser code:
Public Class newWebBrowser
Inherits WebBrowser
Private Sub webBrowserComplete() Handles Me.DocumentCompleted
Dim newTab As TabPage = frmBrowser.Tag()
Dim frmSK As New frmBrowser
Dim hi As String
newTab.Text = Me.DocumentTitle
frmSK.txtAdressSearch.Text = Me.Url.ToString
End Sub
End Class
Any time I enter something into txtAdressSearch, Visual Studio raises a NullRefrenceException and highlights thisBrowser.Navigate(txtAdressSearch.Text). As a side note, it says "Object reference not set to an instance of an object."
Anyone know whats the problem here? Thank you.
After debugging for more than an hour, I looked over my code and saw I was missing a big part of it. I wrote it all in and it worked fine. The issue was the tags weren't being defined correctly (and in some cases, not at all) so .Tag was returning Nothing.
Thanks to all who helped.

How to send a class through named pipe in VB.net

Using VB2008, I have 2 applications on 2 computers that needs to communicate. I setup a named pipe and so far, it's working. I can send strings, back and forth between those 2 programs.
Now, I need to be able to send a class, or an object. I have read somewhere that Serialization is the way to go. So, on the client, I have:
Public Class cTest
Dim Var1 As Boolean
Dim Var2 As String = "a test"
Dim Var3 As New Collections.ArrayList
Public Sub AddItem(ByVal Item As String)
Var3.Add(Item)
End Sub
End Class
Private Sub Button8_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button8.Click
Dim oClasse As New cTest
oClasse.AddItem("StarWars")
oClasse.AddItem("StarTrek")
oPipe.SendToPipe(oClasse)
End Sub
End Class
Public Sub SendToPipe(ByVal test As cTest)
Dim xmlTest As New Xml.Serialization.XmlSerializer(GetType(cTest))
xmlTest.Serialize(pipeClient, test)
End Sub
On the server side (on the remote computer):
Public Function ReadString() As String
Dim len As Integer = 0
len = CType(ioStream.ReadByte(), Integer) * 256
len += CType(ioStream.ReadByte(), Integer)
Try
Dim serializer As New Xml.Serialization.XmlSerializer(GetType(cTest))
Dim Test As cTest
Test = CType(serializer.Deserialize(ioStream), cTest)
Catch ex As Exception
End Try
End Function
The serializer.Deserialize throw an exception saying the XML format is not correct.
what I'm doing wrong?
thanks for your time and help
finally, after a lot of testing and googling, I figured it out:
when using the following code on the client side it works:
Dim oClasse As New cTest
oClasse.AddItem("StarWars")
oClasse.AddItem("StarTrek")
Using PStream As IO.Pipes.NamedPipeClientStream = New IO.Pipes.NamedPipeClientStream(".", "VisionEnginePipeRead1", PipeDirection.Out, PipeOptions.None, TokenImpersonationLevel.None)
PStream.Connect()
Dim xmlTest As New Xml.Serialization.XmlSerializer(GetType(cTest))
xmlTest.Serialize(PStream, oClasse)
End Using
and this, on the server side:
Dim Test As cTest
Using PStream As NamedPipeServerStream = New NamedPipeServerStream(pipeName, PipeDirection.In, 1, PipeTransmissionMode.Byte, PipeOptions.None)
PStream.WaitForConnection()
Dim serializer As New Xml.Serialization.XmlSerializer(GetType(cTest))
Test = CType(serializer.Deserialize(PStream), cTest)
End Using
If I were you I would use WCF Self Hosted Services and let the two communicate using callbacks
This started as a comment but I was running out of room. I am no expert on named pipe communications but, it has been a couple hours, and it may be that that is not really the problem.
You need to first test the serialization/deserialization in the same application. In other words start by taking the pipes out of the picture. This will isolate whether this is a serialization issue or a named pipe issue. Assuming that you code will work when done in the same application, then you need to compare the xml generated by the two applications - have them both do a Serialize. If the xml is identical (which I doubt) then pass it through the pipe and compare it again.
Going further out on a limb here but you may see that the namespace is different for the ctest object. If this is the case it may help to define your shared classes in a library which is shared between the two applications.

Visual Basic: dynamically create objects using a string as the name

Is there a way to dynamically create an object using a string as the class name?
I've been off VB for several years now, but to solve a problem in another language, I'm forced to develop a wrapper in this one. I have a factory method to dynamically create and return an object of a type based on input from elsewhere. The provided input is meant to be the class name from which to create an object from. Normal syntax means that the entire class has to be explicitly spelled out. To do it this way, there could literally be hundreds of if/then's or cases to handle all the available class/object choices within the referenced libs:
If c_name = "Button" then obj = new System.Windows.Forms.Button
If c_name = "Form" then obj = new System.Windows.Forms.Form
....
I'm hoping instead to reduce all this case handling to a single line: IE...
my_class_name = "whateverclass"
obj = new System.Windows.Forms.my_class_name()
In PHP, this is handled like so...
$my_class_name = "whateverclass";
$obj = new $my_class_name();
Edit: Looking at some of the answers, I think I'm in way over my head here. I did manage to get it working using this CreateInstance method variation of the Assembly class, even though I'm more interested in this variation giving more options, including supplying construct parameters...
my_type_name = "System.Windows.Forms.Button"
asmb_name = "System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
button1 = Reflection.Assembly.Load(asmb_name).CreateInstance(my_type_name)
In other words, it takes a method to do this, and not any inherent language syntax? This Activator variation also worked when the full assembly string and class path is used. I'm suspicious CreateInstance may not have the full ability to let me treat objects as if they were called normally, ie obj = new System.Windows.Forms.Button. This is why I can't use simply CreateObject. If there is no natural language feature allowing you to substitute a class name for a string, does anyone have any insight into what sort of limitations I can expect from using CreateInstance?
Also, is there even a difference between basic Activator.CreateInstance (after Unwrap) and Assembly.CreateInstance methods?
This will likely do what you want / tested working; switch the type comment at the top to see.
Imports System.Reflection
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
' Dim fullyQualifiedClassName as String = "System.Windows.Forms.TextBox"
Dim fullyQualifiedClassName As String = "System.Windows.Forms.Button"
Dim o = fetchInstance(fullyQualifiedClassName)
' sometime later where you can narrow down the type or interface...
Dim b = CType(o, Control)
b.Text = "test"
b.Top = 10
b.Left = 10
Controls.Add(b)
End Sub
Private Function fetchInstance(ByVal fullyQualifiedClassName As String) As Object
Dim nspc As String = fullyQualifiedClassName.Substring(0, fullyQualifiedClassName.LastIndexOf("."c))
Dim o As Object = Nothing
Try
For Each ay In Assembly.GetExecutingAssembly().GetReferencedAssemblies()
If (ay.Name = nspc) Then
o = Assembly.Load(ay).CreateInstance(fullyQualifiedClassName)
Exit For
End If
Next
Catch
End Try
Return o
End Function
I'm pretty sure Activator is used for remoting. What you want to do is use reflection to get the constor and invoke it here's an example http://www.eggheadcafe.com/articles/20050717.asp
EDIT: I was misguided about Activator until jwsample corrected me.
I think the problem your having is that your assembly is the one that GetType is using to try and find Button. You need to call it from the right assembly.
This should do it
Dim asm As System.Reflection.Assembly = System.Reflection.Assembly.LoadWithPartialName("System.Windows.Forms")
Dim obj As Object = Activator.CreateInstance(asm.GetType("System.Windows.Forms.Button"))
Take a look at the Activator.CreateInstance(Type) method.
If your input is the name of a class you should be able do this:
Dim obj As Object = Activator.CreateInstance(GetType("Name_Of_Your_Class"))
You'll have to fiddle with the GetType call to make sure you give it enough information but for most cases just the name of the class should work.
Here is a really easy way I have found while rummaging through the internet:
dynamicControl = Activator.CreateInstance(Type.GetType("MYASSEMBLYNAME." + controlNameString))