First let me say Tapiscode, that I have been totally unable to get any of my examples working on 64 bit Windows 7. When I first became interested in this topic of calling unmanaged code from VB.NET was back in 2008 or so. And at that time I was using PowerBASIC for my tests. PowerBASIC isn’t anything at all like VB.NET. Its much closer to C or C++ than .NET. So what my code works on at this point is Windows XP or 32 bit Windows 7. I’m simply not knowledgable enough in .NET to know why my code won’t work on 64 bit machines, so I’m going to have to leave that up to you to figure out.
The Microsoft link I used to learn what I did is this …
http://msdn.microsoft.com/en-us/library/42b9ea93%28v=vs.110%29.aspx
It uses a MessageBox() example. MessageBox() is the Win32/64 function in the Windows Api. What I did was create the following PowerBASIC Dll…
1 2 3 4 5
|
#Compile Dll
Function AddOne Alias "AddOne" (Byval x As Long) Export As Long
AddOne = x + 1
End Function
| |
The function is called AddOne(), and all it does is increment and return the ‘x’ parameter passed in the parameter list. In other words, if you pass in 5 it returns 6.
Here is my VB.NET program that creates a GUI Window and calls AddOne() from the PowerBASIC Dll…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
'vbc /r:System.dll,System.Windows.Forms.dll,System.Drawing.dll /t:winexe PInvoke.vb
Imports System
Imports System.Drawing
Imports System.Windows.Forms
Imports System.Runtime.InteropServices
Public Class PowerBasic
Declare Function AddOne Lib "ADDONE.DLL" Alias "AddOne" (Byval x As Long) As Integer
End Class
Class PInvoke
Inherits Form
Sub New()
Me.Text="Using PowerBASIC In VB.NET"
Me.BackColor = SystemColors.Window
Me.ForeColor = SystemColors.WindowText
End Sub
Protected Overrides Sub OnPaint(ByVal pea As PaintEventArgs)
Dim br As SolidBrush
Dim iNum As Integer
iNum=5
iNum=PowerBasic.AddOne(5)
br=New SolidBrush(SystemColors.WindowText)
pea.Graphics.DrawString("iNum=" & iNum.ToString(),Me.Font,br,0,0)
End Sub
End Class
Module Main
Sub Main()
Application.Run(New PInvoke())
End Sub
End Module
| |
Note that the key to doing this is the three lines at top as so…
1 2 3
|
Public Class PowerBasic
Declare Function AddOne Lib "ADDONE.DLL" Alias "AddOne" (Byval x As Long) As Integer
End Class
| |
As my link above describes, you have to wrap a VB Declare Statement within a ‘Class’, and I arbitrarily named the Class PowerBASIC. And you can see in the OnPaint() message handler for my Pinvoke Class how I called the function, and I used the DrawString member of the Graphics Class to output the incremented number to the form. This works perfectly on XP or 32 bit Windows 7.
Note I don’t use the Visual Studio IDE to compile .NET programs. Basically I dislike Visual Studio and I hate .NET. I compiled the above program from the command line using vbc.exe which is the VB.NET compiler. On my computer it can be found here…
C:\Windows\Microsoft.NET\Framework\v3.0
C:\Windows\Microsoft.NET\Framework\v3.5
C:\Windows\Microsoft.NET\Framework\v4….
Etc.
To compile I make a batch file like so …
1 2 3 4 5 6
|
CD\
CD C:\Code\MS.NET\vb.net\PInvoke
Path C:\Windows\Microsoft.net\framework\v3.5
cls
C:\Windows\system32\cmd.exe
Cls
| |
In my case above my project directory where I’m working on this stuff is…
C:\Code\MS.NET\vb.net\Pinvoke
What the above code blurb does is change the current directory to my project directory, and add a temporary PATH to the vbc compiler, so that when I try to compile the system can find vbc. Here is the command line to compile the above vb.net program if the file is named Pinvoke.vb and it is in the above directory…
vbc /r:System.dll,System.Windows.Forms.dll,System.Drawing.dll /t:winexe PInvoke.vb
You can see I have that command line remmed out at the top of PInvoke.vb. And like I said, that works perfectly. But I had great reservations about getting that to work in C or C++ because of the Calling Convention issue. I’ll discuss that next…