Creating a user control object in runtime - vb.net

please help me on creating a user control object in runtime using createobject function or whatever better function in vb.net.
here is my code:
Dim b As New Security.Sec_Role
b.Name = "Sec_Role"
b.visible = true
but i want to use this code:
dim b as object
b = createobject("Security.Sec_Role")
but it always return an error:
Cannot create ActiveX component.
EDIT: i figure it out..thanks a lot..i use this codes:
Dim asm As System.Reflection.Assembly = Assembly.Load("Security")
Dim b As Object = Activator.CreateInstance(asm.GetType("Security.Sec_Role"))

If it is an .Net UserControl you will not be able to use CreateObject unless it has been exposed as a Com object according to the MSDN page for CreateObject. Using New would be the proper way to create a .Net UserControl.
From above link:
Creates and returns a reference to a COM object. CreateObject cannot
be used to create instances of classes in Visual Basic unless those
classes are explicitly exposed as COM components.
From this MSDN Forum try something like this using System.Activator.CreateInstance:
Dim oType As System.Type = Type.GetType("MyNamespace.ClassName")
Dim obj = System.Activator.CreateInstance(oType)

.Net classes are not ActiveX controls.
You can't do that.
You may be looking for Reflection or a dictionary.

You will want to use Activator.CreateInstance:
Dim b as object
b = Activator.CreateInstance(Nothing, "Sec_Role")
It will be easiest if this method is in the assembly which has the controls. Otherwise, you will need to provide the assembly name in the first parameter.

Related

Create an object in Visual Basic (not VB.NET) without using "New"

I've been told to think outside the box, and think of a way to create an object in VB without using the new keyword. I was told it is possible but i'm having trouble figuring it out. I know primitive data gets stored on the stack and the reference to the objects get stored there too but the actual memory space for the object is in the heap and that new does that for us. When i try it without new i mostly get null reference exception, any ideas on how this is possible?
Dim objTest as TestOne()
'some class named TestOne with empty Constructor
In VB you can use the CreateObject function if you have an existing class defined in a COM library that you've created - or a COM library that already exists.
As an example, create a project reference to the Microsoft Scripting Runtime COM library (scrrun.dll). To do this in the VB IDE select Project, References, then pick the reference 'Microsoft Scripting Runtime'. You can then write the following code:
Dim fso As Object
fso = CreateObject("Scripting.FileSystemObject")
I haven't done VB for quite a while now, but the Activator exists in both C# and VB. Here's couple lines of C# that you can convert to VB:
var newThing = (TestOne)Activator.CreateInstance(typeof(TestOne));
newThing.ID = 5;
The CreateInstance method returns an object, which I convert to the correct class with
(TestOne)
which is the C# syntax for type conversion. Sorry, I forgot how to do this in VB.
Where class 'TestOne' looks like:
class TestOne {
public int ID { get; set; }
}
Note that 'Activator' is part of .NET reflection.

Marshalling a .Net function that returns Double() to consume in VBA

Here is my function in .Net:
<Runtime.InteropServices.ComVisibleAttribute(True)>
Public Function Unhex(hex As String) As Double()
Dim GetArr As Double() = HexStringToDoubleArray(hex)
Return GetArr
End Function
Here is how I would like to use it in VBA:
Dim ret() As Double
ret = LinkToComLib.Unhex("EDC531...")
There are hundreds of examples of how to pass arrays into .Net (eg), but the only one I found showing the opposite is this MS page, and it doesn't show it being used on the VBA (or even COM) side. Perhaps I am using the wrong search terms. In any event:
Can I use the MarshalAs to export the Double() from .Net, or will I need to use Marshal.Copy or similar (as I suspect, as it is managed)?
If I do have to Copy, is the proper return type then IntPtr?
Am I correct in thinking that Dim ret() As Double is a pointer to a malloc'ed array or perhaps SAFEARRAY? Is that the proper type to use in VBA in this case?
Would creating the array with the proper size (it's always 492!) in VBA and then passing that to the function help in any way? Deallocing perhaps?
If anyone has a pointer to an example of this - a double (or int) array being passed out of .Net along with the corresponding VBA code, I can likely take it from there. But if someone has answers for the above, VB.Net or C# as they like, I'd appreciate it.
You need to decorate the return with <MarshalAs(UnmanagedType.SafeArray)> attribute.
VB.Net Example:
Imports System.Runtime.InteropServices
<ComClass(ArrayExample.ClassId, ArrayExample.InterfaceId)> _
Public Class ArrayExample
' These GUIDs provide the COM identity for this class and its COM interfaces.
Public Const ClassId As String = "e510d899-dad1-412b-94ea-6c726fe9f9da"
Public Const InterfaceId As String = "ef3498f0-22b4-4c2a-aeb1-22936c9757eb"
Public Function Unhex(hex As String) As <MarshalAs(UnmanagedType.SafeArray)> Double()
Dim GetArr As Double() = {2.0R, 5.0R}
Return GetArr
End Function
End Class
VBA Usage:
Sub t()
Dim c As ExampleComArrayReturn.ArrayExample
Set c = New ExampleComArrayReturn.ArrayExample
Dim arr() As Double
arr = c.Unhex("AABB")
End Sub
Edit: Forgot to mention that this uses the ComClassAttribute Class to have the compiler generate the interfaces for your class.
Edit 2 in response to follow-up question.
To debug your COM library project, go to the Debug tab of project properties. Select "Start External Program" and set it to run Excel. You can also specify the Workbook to open in the "Command line Arguments". Now when you click on the "Start" button, Excel will be launched and break points in your code will be triggered.
Edit 3:
To address the issue of targeting .Net 3.5, you can use a slightly less convenient method of attaching the debugger to the Excel process. If you are using VS2008, the method described above will work. New VS versions will need to attach to the process. There may be a way to specify this info in the vproj.user file, but I have not found the magic property type to allow direct launching using a specific framework version.
Depending on your VS version the "Attach To Process" item will either be under the Tools (VS2013) or the Debug (VS2017) menu or you can use the shortcut cntrl-alt-p.
Obviously start Excel and load your Workbook. Then in VS launch the Attach to Process dialog. Click the "Select" button and then click on the "Debug these type" radiobutton. Select the "Managed (v3.5, v3.0, v2.0) code" type and click the "OK" button. Then select the Excel process and click "Attach".

Get a list of Interface properties

I am working with a COM library in Visual Basic (VB.NET). I am trying to get a list of properties associated with an Interface; however, I am not able to get a list of interface properties. Can someone direct me on the best way to list properties on an Interface?
Below is some sample code that loops over all the properties of a class called "TextBox". The output from this code is a list all the class properties.
This particular code doesn't seem to work for interfaces. By this I mean that this code doesn't return the properties of an interface.
Dim txt As New TextBox
Dim type As Type = txt.GetType()
Dim properties() As PropertyInfo = type.GetProperties()
For Each p As PropertyInfo In properties
OutputWindow(p.Name)
Next
Image of COM Library with Interface HYSYS.Valve
Just replace txt.GetType() with the GetType() operator to specify type names instead:
Dim type As Type = GetType(HYSYS.Valve)
You would only use <object>.GetType() when you already have an existing instance of an object. To get the properties of a type in general, for instance a TextBox, it is better to do GetType(TextBox).

How to access this variable?

I'm new to VB and I'm currently migrating a vb6 app I did not write to .net and I'm struggling with this error,
If TypeOf Application.OpenForms.Item(i) Is frmAddChangeDelete Then
'UPGRADE_ISSUE: Control ctrlAddChangeDelete1 could not be resolved because it was within the generic namespace Form. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="084D22AD-ECB1-400F-B4C7-418ECEC5E36E"'
If **Application.OpenForms.Item(i).ctrlAddChangeDelete1.ParentFormNumber = intFormNumber** Then
If Application.OpenForms.Item(i).Text = "Add Proofed Expense Items" Then
boolAddProofed = True
Exit For
ctrlAddChangeDelete1 is supposedly calling the friend class ctrlAddChangeDelete from a separate VB file, so I'm not sure why it's saying that
"'ctrlAddChangeDelete1' is not a member of 'System.Windows.Forms.Form'."
Any help is appreciated, thank you !
Application.OpenForms is a collection not strongly typed.
When you reference elements there you get back a generic Form.
In a generic Form there is no control named ctrlAddChangeDelete1
If you have a form derived class named frmAddChangeDelete and this class has a control named ctrlAddChangeDelete1 then you need to cast the reference stored in the OpenForms collection to your specific form class before trying to reference that control.
Moreover, to access that control from external code, you should also have the Modifiers property set to Public instead of the default Internal. Otherwise you will not be able to access the control from any code external to the class.
To retrieve correctly your form you can write
Dim delForm = Application.OpenForms.
OfType(Of frmAddChangeDelete)
FirstOrDefault()
If delForm Is Nothing Then
' No form of type frmAddChangeDelete is present in the collection
' write here your message and exit ?
Else
' Now you can use delForm without searching again in the collection
......
The code above uses the IEnumerable.OfType extension and this requires the Imports System.Linq.
If you don't want to use this then you can always use the TryCast operator to get the reference to the correct class
' Still you need a for loop up ^^^^ before these lines
Dim delForm = TryCast(Application.OpenForms(i), frmAddChangeDelete)
if delForm Is Nothing then
....
else
....

Get Reference to an object from external application

Hi all
I have handle of a usercontrol on external application in vb.net.
I know class type of that user control.
I want to get refrence to that object to check some properties of that object.
Is it possible and how?
thanks
I hope I do understand your question right...
You may try to insert a reference to your library (I assume your userControl is in this library). As a prerequisite this external application must be written in .Net or have some kind auf COM interface!
Then you may try to access the userControl class by
NAMESPACE.CLASS myReference = new NAMESPACE.CLASS();
hth
You can get some info by using interop, with some functions like GetWindowText and SendMessage, however this won't allow you to get all properties, and won't work on every type of application (WPF or Java come to mind).
The Control Class has a method FromHandle:
Dim myCtrl As knownType = Control.FromHandle(knownHandle)
'then get the known property using Reflection
Dim oProp As System.Reflection.PropertyInfo = myCtrl.GetType.GetProperty("KnownProperty")
Dim oValue As Object = oProp.GetValue(myCtrl, Nothing)
'or directly:
Dim oValueD as Object = myCtrl.knownProperty
I don't know if it works between processes.