Creating a Windows DLL with Visual Basic
Pages: 1, 2, 3
Creating the Windows DLL
So, after examining an ActiveX DLL's export table, intercepting Visual Basic's call to the compiler, intercepting Visual Basic's call to the linker, and comparing the arguments passed to the linker with those required by a C/C++ compiler to generate a Windows DLL, we've finally identified why we aren't able to successfully create a Windows DLL with Visual Basic. And fortunately, we can work around that restriction. We should be able to create a standard Windows DLL if we do the following:
Create a .def file for our project. We can specify our exported functions in the .def file in several ways, but it's best to keep it simple:
NAME MathLib LIBRARY MathMod DESCRIPTION "Add-on Library of Mathematical Routines" EXPORTS DllMain @1 Increment @2 Decrement @3 Square @4The
NAMEstatement defines the name of the DLL. TheLIBRARYstatement must either precede the list of exported functions or appear on the same line as the first function. The .def file should also list the ordinal position of each exported function preceded by an@symbol.Decide how we want to intercept the call to the linker. Two major techniques are available to do this:
Patching the Import Address Table (IAT), which requires that we build a Visual Basic add-in that modifies the IAT in order to intercept particular calls by Visual Basic to the Win32 API. Although it's certainly the most elegant method, its complexity makes it a worthy subject for a separate article.
Building a proxy linker that intercepts the call to the real linker, modifies the command-line arguments to be passed to the linker, and then calls the linker with the correct command-line arguments. This is the approach we used to discover what arguments Visual Basic was passing to the compiler and linker, and it's the approach we'll adopt to create a Windows DLL.
In building our proxy linker, we want a sufficiently flexible design so that we can generate other kinds of files, if need be.
Modify the arguments to the linker to add the
/DEFswitch along with the path and filename of our .def file. To do this, you must create a Visual Basic Standard EXE project, add a reference to the Microsoft Scripting Runtime Library, remove the form from the project, and add a code module. The source code for the proxy linker is as follows:Option Explicit Public Sub Main() Dim SpecialLink As Boolean, fCPL As Boolean, fResource As Boolean Dim intPos As Integer Dim strCmd As String Dim strPath As String Dim strFileContents As String Dim strDefFile As String, strResFile As String Dim oFS As New Scripting.FileSystemObject Dim fld As Folder Dim fil As File Dim ts As TextStream, tsDef As TextStream strCmd = Command Set ts = oFS.CreateTextFile(App.Path & "\lnklog.txt") ts.WriteLine "Beginning execution at " & Date & " " & Time() ts.WriteBlankLines 1 ts.WriteLine "Command line arguments to LINK call:" ts.WriteBlankLines 1 ts.WriteLine " " & strCmd ts.WriteBlankLines 2 ' Determine if .DEF file exists ' ' Extract path from first .obj argument intPos = InStr(1, strCmd, ".OBJ", vbTextCompare) strPath = Mid(strCmd, 2, intPos + 2) intPos = InStrRev(strPath, "\") strPath = Left(strPath, intPos - 1) ' Open folder Set fld = oFS.GetFolder(strPath) ' Get files in folder For Each fil In fld.Files If UCase(oFS.GetExtensionName(fil)) = "DEF" Then strDefFile = fil SpecialLink = True End If If UCase(oFS.GetExtensionName(fil)) = "RES" Then strResFile = fil fResource = True End If If SpecialLink And fResource Then Exit For Next ' Change command line arguments if flag set If SpecialLink Then ' Determine contents of .DEF file Set tsDef = oFS.OpenTextFile(strDefFile) strFileContents = tsDef.ReadAll If InStr(1, strFileContents, "CplApplet", vbTextCompare) > 0 Then fCPL = True End If ' Add module definition before /DLL switch intPos = InStr(1, strCmd, "/DLL", vbTextCompare) If intPos > 0 Then strCmd = Left(strCmd, intPos - 1) & _ " /DEF:" & Chr(34) & strDefFile & Chr(34) & " " & _ Mid(strCmd, intPos) End If ' Include .RES file if one exists If fResource Then intPos = InStr(1, strCmd, "/ENTRY", vbTextCompare) strCmd = Left(strCmd, intPos - 1) & Chr(34) & strResFile & _ Chr(34) & " " & Mid(strCmd, intPos) End If ' If Control Panel applet, change "DLL" extension to "CPL" If fCPL Then strCmd = Replace(strCmd, ".dll", ".cpl", 1, , vbTextCompare) End If ' Write linker options to output file ts.WriteLine "Command line arguments after modification:" ts.WriteBlankLines 1 ts.WriteLine " " & strCmd ts.WriteBlankLines 2 End If ts.WriteLine "Calling LINK.EXE linker" Shell "linklnk.exe " & strCmd If Err.Number <> 0 Then ts.WriteLine "Error in calling linker..." Err.Clear End If ts.WriteBlankLines 1 ts.WriteLine "Returned from linker call" ts.Close End SubThis proxy linker modifies only the command-line arguments passed to the linker if a .def file is present in the directory that contains the Visual Basic project; otherwise it simply passes the command-line arguments on to the linker unchanged. If a .def file is present, it adds a
/DEFswitch to the command line. It also determines whether any resource files are to be added to the linked file list. Finally, it examines the export table to determine if a function namedCplAppletis present; if it is, it changes the output file's extension from .dll to .cpl.To install the proxy linker, rename the original Visual Basic linker LinkLnk.exe, copy the proxy linker to the Visual Basic directory, and name it Link.exe.
Once we create our proxy linker, we can reload our MathLib project and compile it into a DLL by selecting the Make MathLib.exe option from the File menu.
Testing the DLL
Once we create our Windows DLL, the final step is to test it to make sure that it works. To do this, create a new Standard EXE project (let's call it MathLibTest) and add a code module. To make sure that code in our project can access the functions exported by the DLL, we use the standard Visual Basic Declare statement. We declare our three exported math routines in the code module as follows:
Option Explicit
Public Declare Function Increment Lib "C:\VBProjects\MathLib\mathlib.dll" ( _
value As Integer) As Integer
Public Declare Function Decrement Lib "C:\VBProjects\MathLib\mathlib.dll" ( _
value As Integer) As Integer
Public Declare Function Square Lib "C:\VBProjects\MathLib\mathlib.dll" ( _
value As Long) As Long
We can then use the following code in the form module to call the routines in the DLL:
Option Explicit
Private Sub cmdDecrement_Click()
txtDecrement.Text = Decrement(CInt(txtDecrement.Text))
End Sub
Private Sub cmdIncrement_Click()
txtIncrement.Text = Increment(CInt(txtIncrement.Text))
End Sub
Private Sub cmdSquare_Click()
txtSquare.Text = Square(CLng(txtSquare.Text))
End Sub
Private Sub Form_Load()
txtIncrement.Text = 0
txtDecrement.Text = 100
txtSquare.Text = 2
End Sub
When we call each of the MathLib functions, the application window might appear as it does in Figure 2, confirming that the calls to the MathLib routines work as expected.

Figure 2: Testing calls to MathLib.dll
Ron Petrusha is the author and coauthor of many books, including "VBScript in a Nutshell."
Return to the Windows DevCenter.
You must be logged in to the O'Reilly Network to post a talkback.
Showing messages 1 through 77 of 77.
-
VB6 Library Options
2009-03-24 14:00:39 TheBursar [Reply | View]
I have vb6 on a tower pc and created a form for a standard exe program. On double clicking the various labels and the text boxes on the form I went to the 'coding' page. However a line such as 'lbl1.BackColor=RGB (0,255,0) returned a compile error indicating that method was missing, it turns out that only four options come up on the list after inserting the '.', on my laptop there are about a 100. How can I populate the library with the other options to chose from? I assume this may be an install issue but any advice would be welcome.
-
DLL Creation
2009-02-10 21:48:24 GopiGrowlogic [Reply | View]
Excelent article. I create my own dll and it's working fuine with vb6.But this dll is not working in PowerBuilder.hope ur help
Thanks & Regards
Gopinath
gopi@c2info.com
-
using this to create descriptions in Excel function wizard
2008-07-31 02:24:53 smallweed [Reply | View]
Thanks for this - I've used it to create a DLL of dummy functions to aliase in the fix (outlined at http://www.jkp-ads.com/Articles/RegisterUDF01.htm) for creating descriptions for individual arguments of UDFs in Excel's function wizard.
Works great until I close and open my add-in and try again to enter a worksheet function by way of the wizard at which point Excel always crashes with an unhandled exception. I'm wondering if this is because there isn't an adequate "clean up" going on in DllMain. Can anyone give me some pointers as to how I could program this into the DllMain?
-
VB6 DLL's and runtime crashes
2007-12-15 15:07:08 Mathimagics [Reply | View]
Important information about the probable cause of most VB6 DLL crashes (no COM initialisation) can be found here:
http://www.xtremevbtalk.com/showthread.php?t=282796
Cheers
Jim White
Australian National University
CANBERRA
-
Compile Error
2007-11-13 15:16:41 MikeH. [Reply | View]
When I try to compile the Linker discussed in the article, I get an error on this line:
Dim oFS As New Scripting.FileSystemObject
The error says "User Defined Type Not Defined". Any ideas? Also can I just download the entire project from somewhere and see how it is done. I am brand new to this and don't understand a lot of it.
-
Great article
2007-10-23 05:44:31 hericksonn [Reply | View]
Excelent article. I create my own dll and it's working smoothly. If someone need help mail me at hericksonn@gmail.com
Thanks a lot
Henrique Brandão
Campinas / Brazil
-
DLL as a reference
2007-06-20 08:56:19 collinsauve [Reply | View]
I would like to be able to use the functions within one of these custom dll's without having to declare every function in every project that uses it. Should it not be possible to include it as a reference to avoid this?? I would think so, so I tried it but it does not work. I did regsvr32 the dll as well, still does not work.
Also, another evolution to this would to have your modified Link.exe to determine the functions in the dll and have it write the .def file... that would again save a lot of time when working on dlls.
Any thoughts?
-
Arrays in DLL
2007-06-19 07:01:20 pontiveros [Reply | View]
Hi,
This is a great article, thanks for it.
I'm creating a Security Key Checker/Generator MD5 based algorithm DLL, and im having troubles dealing with some Status and Byte Buffer arrays. VB6 just crash! The error happens when left side assignation occurs (ie: MyArray(n)=A_Value ). I get rid of one array changing it to 4 vars cause it never needs to be looped through. But then i've a array(64) that get random index values, so i really need it as is. I really apreciate any help
Greetings in advance
-
Dll programically
2007-06-09 03:01:25 MatthewS [Reply | View]
Is there a way of generating DLL's programically, i.e. at run time - which can then be used and destroyed at runtime? (VB.net of course ;)
I had the idea of generating a shortcut math Parser - instead of messing with code for hours working out how to parse 'y = (x + z) / 2*Pi', just compile a little DLL which will do the job!
Thoughts...
Ta
Matt
-
DLL generation and GUID
2007-04-06 09:56:38 Bejoyjohn [Reply | View]
Hello I am doing this DLL job for the first time and I needed some help to set the GUID in earlier version of Visual studio (6.0)
-
Is anyone still interested
2007-01-18 08:05:05 speechguy [Reply | View]
Is anyone still following this thread. I have had moderate success with creating a DLL but with spotty performance with VBA.
Example works but any simple string related function fails. -
Is anyone still interested
2007-01-31 13:16:47 martiniB [Reply | View]
Sorry. my english is bad, but i have the same Problem ;o) Creat DLL in VB6 is ok, and also the call of the functions under VB6, but i need the dll working if i call out of VBA. Return a string from the DLL --> no problem, but if i call the function in VBA with a string (like TextNew("test") excel close with an error. Hope sombody understand and can help ;o)
Greetings from berlin
martini B.
-
Application crashes
2006-10-20 11:16:15 mmdawson [Reply | View]
Everytime I try to access the dll, the application crashes.
Everything else seems to work well. Any thoughts here?
-
Passing strings to a DLL in VB 6.0
2006-06-29 10:42:14 sunnyrock75 [Reply | View]
I am trying to pass a string to a standard Windows DLL I have created for my application following Ron Petrusha's article. Can anyone help me out on this issue, as I am little lost right now. Thanks! -
Passing strings to a DLL in VB 6.0
2006-06-29 11:05:42 sunnyrock75 [Reply | View]
I realized that one the previous posts answered my question. I am also trying to return an array of double datatype (which is what the function returns in the DLL) from the DLL. How does one receive and read the data from the array in the calling program? Would be great if someone can help me out on this problem. Thanks!
-
Classes
2006-06-08 12:07:04 MLxSol [Reply | View]
Anyone know if you can (and how) classes can be used in these windows DLLs? I am aware in ActiveX you use "set = new classname". Is this possible in windows dlls (to get direct access to a class module)? If not how are properties etc handled in a Windows DLL.
Thank you all for your help.
-
Def File
2006-05-30 09:43:18 MLxSol [Reply | View]
I think this is a wonderful piece of code. Well done. I intend to create a source code app soon to help people.
Anyway, does anyone understand how much use VB makes of the def file? After some experimentation it seems that you only need the exports section.
Also, does it matter about what value you actually asign to the ordinal? I have found you can't miss one out but (e.g. 1,2,4) but it doesn't seem to matter (for VB at least) what the values are set to - what effect does this have on the use of the dll.
-
Calling .dll from Delphi app
2006-05-30 06:14:50 archer1960 [Reply | View]
This works great for calling the .dll from another VB app, but when I try to call it from a Delphi app, I get "Access violation at address xxxxxx in MSVBVM60.dll". I've verified that all my calling and return parameters are on 4-byte boundaries, but still no luck. Any suggestions of what to look for? I've also tried various return types and values from DllMain, but nothing changes. Logging shows that it never starts executing the actual function I'm trying to call. -
Calling .dll from Delphi app
2006-05-30 10:10:37 archer1960 [Reply | View]
Some more info: another guy in the office is doing the Delphi piece of this app, and it looks like nothing which requires I/O from the VB .dll is working when running with a Delphi app: I can't write to a log file on disk, nor can I pop up a msgbox. Both of those work when I use the .dll from a VB app.
-
Cannot Creat DLL
2006-05-09 04:20:40 sudintha [Reply | View]
When i try to compile my DLL it says "File Not Found" with "OK" and then when i selected "ok" Button, another message says "Error in Loading DLL".
project name - mathmod.vbp
Modules - mathLib.bas
Class Modules - Class1 (Class1.cls)
.Def file - mathmod.def
(all in same Directory)
Can anyone help me to get rid of this pls
-
Problem with DEF file
2006-04-10 12:21:37 xfile101 [Reply | View]
Ran the above tutorial with minimal problems, however, created my own DLL and get error loading DLL. I suspect it's in the DEF file. If I remove the def file I can create the DLL albeit, the DLL doesn't work when called but if I add the def file and compile I get error in loading DLL. Here's my def file:
NAME aProper
LIBRARY String 'MathMod
DESCRIPTION "Add-on Library String Routines"
EXPORTS DllMain @1
myProper @2
AddrProper @3
I changed LIBRARY serval times to 'String', 'String Library' etc as I suspect this is the problem but not sure. If someone could help I would appreciate it. -
Problem with DEF file
2006-04-11 09:54:32 xfile101 [Reply | View]
Ok, fixed that problem and others and now my DLL works great IF I use VB.exe. If I use it anywhere else, for instance excel or access, it crashes. I see other people have had this problem while others have not. I've been at this all day and really getting frustrated at this whole concept. All I want to do is use a DLL in excel and access. Can someone please point me inthe right direction? I tried to catch the error before it crashes but can't. I did manage to at least get the program not to crash by declaring the DLL in a module in excel like such:
Declare Function MyProper Lib "C:\WINDOWS\System32\ProperCase.dll" _
Alias "C:\WINDOWS\System32\ProperCase.dll MyProper@2" (ByVal var As Variant) As Variant
but if I do this I get the #VALUE error. I'm passing strings and my function takes a Variant I have chaged these to match (function takes a string)but still no luck. If someone can help I would appreciate it.
-
Visual Basic 2005 Classes
2006-03-22 09:42:36 wjh [Reply | View]
Isn't this whole issue resolved by using VB2005? -
Visual Basic 2005 Classes
2006-05-30 09:48:45 MLxSol [Reply | View]
Quite possibly, but many of us are still using VB6 because it is quicker and easier for us rather than learning the quirks of VB 2005. Many target systems also fail to have .NET framework installed so it is not economical to convert to .NET yet. Afterall, if you are installing something, unless programming a dll for another language, why make VB6 produce a windows dll rather than an activex? It is the fact that not everyone has admin rights that makes us want to produce windows dlls using VB!!
-
Good Article!!
2006-01-31 01:06:16 Askatu_83 [Reply | View]
Good article, it's so simple and really good, sorry but my English is so bad, I hope you can help me please!, I must do a Dll to work with parallel por LPT to use in VB but I have not idea How do I'll do this library, please help me.
Thanks and Good Articles, thanks for your help!
Juan Carlos Mercado.
-
DLL not found
2006-01-17 03:54:59 draftsman [Reply | View]
It seems that if the DLL is in the windows\system32 directory then my program works fine, but if the DLL is in the program's directory instead, where the executable is, that there is usually a "file not found" error. Shouldn't it work equally well in either location?
-
source code for the proxy linker
2005-12-27 04:30:56 draagoon [Reply | View]
Anybody can help me to figure out whether the source code for the proxy linker doesn'n work. When I try to run the code a Error "runtime error Nr5 is showed). debug stop at this line
strPath = Left(strPath, intPos - 1)
I did exactly as described..:
create a Visual Basic Standard EXE project, add a reference to the Microsoft Scripting Runtime Library, remove the form from the project, and add a code module...
-
DLL works in VB exe but not in VBA
2005-11-22 06:12:37 mike2508 [Reply | View]
I created the following function within a dll, for getting the value of a key in the registry, for an excel add-in my company uses (I had to use this method for reading the registry because our IT dept has restricted access to the registry for users, and therefore neither windows registry API calls, nor the use of "WScript.Shell" work) :
Public Function GetLastUserName() As String
Const HKEY_CURRENT_USER = &H80000001
Dim objReg As Object
Dim strValue As String, strKeyPath As String, strComputer As String
On Error GoTo EndGetUserFunction
strComputer = "."
Set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _
strComputer & "\root\default:StdRegProv")
strKeyPath = "The registry path to the key"
objReg.GetStringValue HKEY_CURRENT_USER, strKeyPath, "User", strValue
GetLastUserName = StrConv(strValue, vbFromUnicode)
EndGetUserFunction:
Set objReg = Nothing
End Function
The DLL works ok if I use it in a visual basic exe, but when I try to use it in Excel VBA, Excel crashes. I dont know why
How can I resolve this issue?
Regards
Mike
-
DLL Call Back Funciton
2005-09-04 20:34:47 Jeffrey168 [Reply | View]
Dose this VB Windows DLL have callback function, if it has, How do use the callback function to call.
thanks
-
Error in loading DLL
2005-08-14 11:48:14 sourcerer [Reply | View]
When I try to compile a DLL with the DLLMain export in the def file, towards the end of compilation, I receive the "Error in loading DLL" message.
When I remove the DLLMain export in the def file and compile the DLL, it compiles fine.
Any way I can get the DLLMain export to compile? -
Error in loading DLL
2005-10-05 14:25:20 country [Reply | View]
I am trying to access ADO object inside the windows dll .
I am getting the following error message
" Un handled Exception - ACCESS VIIOLATION"
Unhandled Exception Code (0XC0000005) at Address
(0X66024439)
Attempt to WRITE data at address (0x00000098)
Following is the code i used
Dim connstr As String
Dim Conn As Object
Dim rs As Object
Dim ret As Long
Dim sql As String
On Error GoTo ErrLabel
connstr = "***"
Set Conn = CreateObject("adodb.Connection")
Set rs = CreateObject("adodb.Recordset")
sql = "exec dbo.GetVerifyCoupon "
sql = sql + CStr(coupnum) + "," + CStr(cardID) + "," + CStr(siteID)
Conn.Open connstr
Set rs = Conn.Execute(sql)
ret = rs.fields(0).Value
Set Conn = Nothing
status = ret
Exit Sub
ErrLabel:
Set Conn = Nothing
status = 4
-
Is DllMain being Called?
2005-07-27 07:31:57 LaVolpe [Reply | View]
Has anyone been able to prove that DLLMain is being called? I've added some simple logging in that routine in order to to test, but no log ever got created.
I've compiled with several different options with no luck. It appears the DLLMain is not being called; anyone with different results. -
Is DllMain being Called?
2005-08-28 21:19:38 mizanaz [Reply | View]
How can I create a .dll file by Visual Basic or oter software? -
Is DllMain being Called?
2005-08-28 21:14:30 mizanaz [Reply | View]
How can I create a .dll file by Visual Basic or oter software? -
Is DllMain being Called?
2005-07-28 05:56:24 LaVolpe [Reply | View]
I may have answered my own question but am eager to find out if anyone triggered code inside their DllMain routine. What I did was simply compile the DLL without that routine & the exported functions still worked after changing the ordinals in the .Def file -
Is DllMain being Called?
2005-07-29 05:31:23 LaVolpe [Reply | View]
Thanx to Jim White. To trigger DllMain, the /ENTRY switch needs to be modified in the Linker. -
Is DllMain being Called?
2005-08-14 17:32:03 sourcerer [Reply | View]
Modified to what? -
Is DllMain being Called?
2006-02-28 07:42:51 EWBJr [Reply | View]
You need to add the following to the custom linker Main sub, preferably after the check for Control Panel applet:
'*** change Entry point ******
If MsgBox("Set DllMain as the entry point?", vbYesNo) = vbYes Then
strCmd = Replace(strCmd, "/ENTRY:__vbaS", "/ENTRY:DllMain")
End If
Also, the DllMain function needs to return a long, and its arguments must be called byVal, as follows:
Public Function DllMain(ByVal hInst As Long, ByVal fdwReason As Long, ByVal lpvReserved As Long) As Long
Select Case fdwReason
Case DLL_PROCESS_DETACH
' No per-process cleanup needed
Case DLL_PROCESS_ATTACH
' No per-process initialization needed
DllMain = 1
Case DLL_THREAD_ATTACH
' No per-thread initialization needed
Case DLL_THREAD_DETACH
' No per-thread cleanup needed
End Select
End Function
-
Is DllMain being Called?
2007-09-09 10:02:58 Neounk [Reply | View]
I've added this and the entry point is indeed being changed. BUT, when I compile the dll it seems that DllMain is running before the message box in the linkers code. For example I tried this:
Option Explicit
Const DLL_PROCESS_DETACH = 0
Const DLL_PROCESS_ATTACH = 1
Const DLL_THREAD_ATTACH = 2
Const DLL_THREAD_DETACH = 3
Public Function DllMain(ByVal hInst As Long, ByVal fdwReason As Long, ByVal lpvReserved As Long) As Long
Select Case fdwReason
Case DLL_PROCESS_DETACH
Print #1, "This is a test:: Finishing!"
Close #1
' No per-process cleanup needed
Case DLL_PROCESS_ATTACH
' No per-process initialization needed
Open "test.txt" For Output As #1
Print #1, "This is a test:: Starting!" & vbCrLf
DllMain = 1
Case DLL_THREAD_ATTACH
' No per-thread initialization needed
Case DLL_THREAD_DETACH
' No per-thread cleanup needed
End Select
End Function
when compiling it makes the test file and writes to it perfectly. When i try to load the dll in my application LoadLibrary returns 0. So I checked the dll in my debugger, everything is fine until any call (for example vbaOpenFile). As soon as it enters any of these calls it crashes. removing any calls and just leaving DllMain = 1. makes it load fine.
-
How can I return Strings?
2005-07-18 09:20:14 teschste [Reply | View]
This process works great! I've had no problems creating my DLL but I cannot return Strings in the proper format.
Specifically, if I create a function in my DLL that returns a String, or if I create a sub with a String parameter, the value I get back is a Unicode String.
Yes, I could just convert the String from Unicode in the calling program but I have to believe there's a better way and that I should be able to return a normal String.
Any help would be appreciated. -
How can I return Strings?
2005-07-26 14:20:57 teschste [Reply | View]
Thanks to LaVolpe on PlanetSourceCode, I now know how to pass a string to and from a VB DLL compiled as a standard DLL.
Specifically, when passing a string to the DLL, the DLL needs to convert the string as follows:
sValue = StrConv(sValue, vbUnicode)
When returning a string from the DLL, either via a passed variable in a Sub or as the return value of a Function, the DLL needs to convert the string as follows:
sValue = StrConv(sValue, vbFromUnicode)
Or
MyFunction = StrConv(sValue, vbFromUnicode)
Steve Tesch
-
How can I return Strings?
2005-07-27 13:11:34 teschste [Reply | View]
Well, now that I have all of that working great, I have a new problem.
When I try to Raise an error in my DLL, it fails. Specifically, the calling program receives a run-time error zero, with no other information.
I've tried using both of the following methods without success:
Err.Raise Number:=vbObjectError + lMyError, Source:="Test Source", Description:="Test Description"
and
SetErrorInfo "Test Description", vbObjectError + lMyError, 0, "0", "Test Source"
I even tried wrapping the string values in StrConv as used to solve the previous problems but no luck there either.
Any help on how I can raise a real error from a DLL compiled this way would be appreciated.
Steve Tesch -
How can I return Strings?
2006-04-14 08:58:40 darkoverlordofdata [Reply | View]
You don't need the overhead from strconv.
Create an IDL or ODL file to define your API calls, and for your strings , specify LPWSTR instead of the usual LPSTR - after all, you've created a unicode format dll.
This rids 2 perfromance hits: first - interpreting the Declare statment, 2nd - using strconv.
Bruce
-
Fully functional VB6 API dll's - with Forms
2005-07-18 03:14:07 Mathimagics [Reply | View]
I hope the moderators of this site don't mind if I mention a product that I have recently developed, which solves the problem of Form creation and modeless Form display in a VB6 DLL, as I'm sure it will be of interest to readers of this article.
As various questioners above have found, an API dll written in VB6 can not reference any GUI elements - more specifically it can not access the VB6 runtime private class library, which in normally linked EXE's and ActiveX dll's acts as the class factory for the modules's VB Forms and Controls. Any attempt to do so will crash the process (i.e. your client's application).
This problem is actually not just restricted to Forms. It affects other 'Global' objects as well (e.g. the App and Err objects).
In a nutshell, the problem boils down to the fact that the private VB class library (class factory) initialisation is not performed when a VB dll is accessed via an API interface. This initialisation is buried away deep inside the dll's external COM interface.
I have found a way of getting this initialisation performed, thereby enabling a VB6 dll to escape these restrictions, and to create and show Forms when called via the API from a client application written in just about any language.
The only restriction is a fairly reasonable one - if you want to show modeless (asynchronous) Forms, the client application needs to have a window.
You may be familiar with the error that some ActiveX component providers can get if they try to show a modeless Form to a non-VB client: "Only modal Forms can be shown to a non-VB client".
That's because the only way that a Form in an ActiveX dll can receive its window messages is from the message pump in a VB6 EXE client, or the builtin message pump embedded in the "Show vbModal" method.
I demonstrated some years ago now that this was in fact a rather artificial restriction by VB6. Any client that has a window has a message pump and that pump will dispatch messages to any VB Forms in the process, as they are still normal top-level windows.
VB6's restriction appears to be based on the fact that the dll's Form in that case would not be part of the "managed Form" set of the application.
In any case, if an ActiveX DLL wants to show a modeless Form to a non-VB client, it just needs to use the ShowWindow API instead of the VB6 Show method.
And exactly the same thing applies to a VB6 API dll. If the client is not a VB6 exe, it should use ShowWindow instead of the Show method.
Happily this technique works with VB6 clients in any case, so the DLL does not really need to distinguish between them unless it wishes to.
Being able to show Forms, especially modeless ones, opens the way for VB6 developers to provide packaged services that incorporate a GUI through a simple API interface, avoiding the typical deployment hassles of the COM interface, such as the requirement to register the DLL, binary compatibility issues, etc.
I call the product "The VB6 SuperServer DLL Builder", and you can use it with any custom linker like the one described in this article.
Please email me if you'd like further details, I can provide a working demo.
Regards
Jim White
mathimagics@yahoo.co.uk
-
Fully functional VB6 API dll's - with Forms
2007-02-05 00:55:37 Yazoo [Reply | View]
I'd like the demo.
Thanks. -
Fully functional VB6 API dll's - with Forms
2006-05-22 08:42:19 bill.h [Reply | View]
I am trying to develop a vb6.0 dll that can be called from various programs, such as C and powerbuilder.
I was able to get this to work when the client prog is a vb 6.0, however, it doesn't work from the other two sources. I got a "memory could not be read" error.
I've tried creating a function with no args and still get the same error. My function has been created as follows:
Public Function aa2() As Long
aa2 = 100
End Function
Is there anything special I need to do on the C or powerbuilder side?
thanks,
Bill
Los Angeles, CA
-
Can I Creating a Windows DLL with Visual Basic.NET
2005-07-17 11:12:41 tarekafifi [Reply | View]
How Can I Creating a Windows DLL with
Visual Basic.NET ?????
-
How to call exported functions from Visual C++??
2005-07-07 02:54:41 ponian [Reply | View]
I have tried the sample discussed in this article, and trying to call exported functions from Visual C++; but failed.. :(
I declare the exported function in C++ as:
extern int __stdcall Increment(int n);
and I get an unresolved external symbol!
I try to use LoadLibrary, and function is loaded; but I get an access violation exception as the function is called!
Any idea of this??
Thank you in advance.
-
Works GREAT in both VB and VBA
2005-06-14 11:44:28 Lawrence19103 [Reply | View]
I created the project exactly as described and set the functions in both VB (a new test project) and in VBA(a Microsoft Access Database - both MDB and MDE). The function calls are really REALLY good. No problems. Well, when I first tried to MakeDLL, I was trying to save it to a different folder...the system looks in the DESTINATION folder for the components, so...just save it to the project folder and copy it to where ever you need it.
Now that I've mastered getting my functions into DLL's, I want to open a form - yep, I get a 429-ActiveX component Cannot Create Object (it blows out at PT=2 below):
Public Function Test() As Integer
On Error GoTo ERR_Test
Dim PT As Integer
PT = 1
Dim fTest As New Form1
PT = 2
Load fTest
PT = 3
fTest.Show vbModeless
PT = 4
Test=PT
Exit Function
ERR_Test:
MsgBox Err.Number & " - " & Err.Description & " PT: " & PT
Test=PT
Exit Function
End Function
I spent 4-5 days looking for this article. Can't spend another 5 days looking for the solution. Any suggestions???
Lawrence
PS: I've already Registered both DAO360.DLL and this DLL - Still no luck. And, yes the code is sloppy - I'm experimenting...
-
Main vb6 exe crashs by calling a dll function
2005-06-10 02:08:28 Jörg [Reply | View]
Hello,
I created successfully a VB6 dll with one simple function "MyBox" (msgbox) using the Make ActiveX-DLL (see sample).
I build a vb exe program wich call this function
(MyBox "Hello").
When I run the program, it crashs when calling the dll function: "vb6.exe - runtime error
.....cloud not "read" from "0x123131..."
Can everyone help me to solve this problem, please?
Jörg
-
Strange ...
2005-06-02 08:37:41 Jeffi80 [Reply | View]
Hi guys
Can someone please tell me is it possible to to call function from this kind of dll from Delphi or VC project ?
I tried to make plugin for program calld ProgDVB and the program crash all the time when it trys to load my plugin.
This is what I get in error report :
AppName: progdvb.exe AppVer: 4.0.0.0 ModName: msvbvm60.dll
ModVer: 6.0.97.82 Offset: 0010667e
I tryed it with Delphi and it work just fine with this code :
procedure On_Send_Dll_ID_Name(var MyName:array of char );cdecl;
begin
MyName[0]:=char('E');
MyName[2]:=char(0);
end;
And here is my VB6 code which is causing me hard time :
Public Function On_Send_Dll_ID_Name(MyName() As Variant)
MyName(0) = "F"
MyName(1) = "0"
End Function
Can someone please tell me am I doing something wrong/stupid here ?
Anyway, this sample of yours works really great with VB and it is really usefull.
Thanks in advance.
Regards
Jeffi80
-
Showing forms within API DLL
2005-05-31 23:10:17 ijwelch [Reply | View]
Does anyone know how to show a form/use a class from within the windows dll created above?
Any attempt to dim (and use) a private class or form from within the dll generate a windows error.
Eg:
add a form 'Form1' to the dll project
add this code to the dll module
Public Function ShowForm1() As Long
Dim f as New Form1
f.Show
ShowForm1 = 1
End Function
add new line to DEF file
ShowForm1 @5
and compile dll
Any call to ShowForm1 method crashes vb/exe
If I add a public method to the empty class and call that method first then displaying form does not fail (but by then it's a com dll anyway and requires registering and adding to vb references).
Seems that 'something' is not being initialized in the windows dll to allow 'objects'.
-
Showing forms within API DLL
2005-08-01 03:49:36 Hossein.mohammadi [Reply | View]
how can I create and call dll with form in VB
-
Showing forms within API DLL
2005-07-08 07:03:14 JohnDrinkall [Reply | View]
I feel like a stuck record. Have you tried CreateObject instead of New?
There are subtle differences. I have managed to call a VB DLL (from VB) that uses classes successfully after replacing New with CreateObject. Not tried it with forms, only classes so far.
-
Using external resource files with VB exes
2005-05-19 06:11:32 JohnDrinkall [Reply | View]
Fantastic article. I was looking for a way to utilise the unused version information within VBs project settings (so we could have 4 used digits with our exe version numbers rather than 3 used and 1 blank)
After compiling the resource .rc file to get a .res, and intercepting the linker as per your article, I noticed that the commandline argument to the linker needed to specify the resource file before some of the object files (other wise it complained that it already had a resource entry and ignored the new .res file)
I also had to move CVTRES.EXE from the vc98\bin directory into the vb directory to allow it to compile the exe with additional resource file in there. Once again thanks!
Regards
John Drinkall -
Using external resource files with VB exes
2006-03-10 09:12:29 marioavc [Reply | View]
Can you explain how did you do this? I am trying to achieve the same thing, but I can't. It tells me "error in loading DLL", I am assuming it is happening because the .res file with version information is being inserted in the wrong place. I also tried to link it as an .obj using cvtres, but didn't work either. any hint?
Mario.
-
can vb6 class/form be in windows dll ?
2005-05-12 05:13:59 Jeffrey168 [Reply | View]
I fellow the documents to do. It is work,but It is using basic functions and subrutines listed in the exprots of DLL.
next, I created class or Form by the new like
'dim form1 as new form' , after this I do something with class/form1 .. something raised Err... Can we use vb6 class or object in windows dll ? -
can vb6 class/form be in windows dll ?
2005-05-16 07:28:03 Yehuda [Reply | View]
I had the same question. I have a vb class that opens word/excel and I would like to export it to c++, via a windows dll. If anyone has a solution please post it.
Thank You -
can vb6 class/form be in windows dll ?
2005-05-19 07:26:10 JohnDrinkall [Reply | View]
Yes you can. Okay a really simple example.
Create a VB dll (This is Sample.SampleClass.
Option Explicit
Public Sub SayHello(ByVal strVal As String)
MsgBox strVal
End Sub
Since you didn't specify which DLL type, I'm plumping for the regular kind. From memory I think that Active-x's dlls would be easier, but I've not had time to check.
Start C++ (I'm using V7, but you can use V6, just the menu options are different and I've forgottern where they are for 6.)
Create a windows Dll with MFC support called TestConsumer. This is important since we need the COleDispatchDriver class.
Add a new class, select implement MFC from type library and select your VB Dll that you have created (or another object)
It generates the following
class CSampleClass : public COleDispatchDriver
{
public:
CSampleClass(){} // Calls COleDispatchDriver default constructor
CSampleClass(LPDISPATCH pDispatch) : COleDispatchDriver(pDispatch) {}
CSampleClass(const CSampleClass& dispatchSrc) : COleDispatchDriver(dispatchSrc) {}
// Attributes
public:
// Operations
public:
// _SampleClass methods
public:
void SayHello(LPCTSTR strVal)
{
static BYTE parms[] = VTS_BSTR ;
InvokeHelper(0x60030000, DISPATCH_METHOD, VT_EMPTY, NULL, parms, strVal);
}
// _SampleClass properties
public:
};
Export an entry point by adding it into the def file
LIBRARY "TestConsumer"
EXPORTS
; Explicit exports can go here
TestDll
Add the function into the DLL
void __stdcall TestDll(IDispatch* IDisp)
{
CSampleClass cSamp(IDisp);
cSamp.SayHello("Hello there");
cSamp.DetachDispatch(); // Use this so that when the C class falls out of scope it won't take the VB object with it.
}
Build and place in the VB app directory
Write a sample VB app
Private Declare Sub TestDll Lib "TestConsumer" (ByVal oObject As Object)
Private Sub Test_Click()
Dim oSample As sample.SampleClass
Set oSample = New sample.SampleClass
oSample.SayHello "Test"
TestDll oSample
oSample.SayHello "Back again"
Set oSample = Nothing
End Sub
And the message boxes you should see are "Test", "Hello There", and "Back Again" - easy eh?
If you have any questions drop me a mail at JohnDrinkall@yahoo.com
Cheers
John -
can vb6 class/form be in windows dll ?
2005-07-08 07:04:45 JohnDrinkall [Reply | View]
To call a VB class within a VB Windows DLL you should avoid using New to instantiate it. See previous replies. -
can vb6 class/form be in windows dll ?
2007-03-29 19:19:32 draftsman [Reply | View]
I seem to have stumbled across a way to have forms within the vb6 dll, by putting in within a class, and would appreciate any comments. You can get my test from http://ipowermation.com/temp/dlltester.zip. It has the dll and a test program source code. -
can vb6 class/form be in windows dll ?
2007-03-29 19:16:22 draftsman [Reply | View]
I seem to have stumbled across a way to have forms within the vb6 dll, by putting in within a class, and would appreciate any comments. You can get my test from http://ipowermation.com/temp/dlltester.zip. It has the dll and a test program source code.
-
Debugging the finished DLL
2005-04-28 06:15:42 chizzy [Reply | View]
This is a great article and provides a very clever solution. However, I am not able to figure out how to set break points and debug this DLL. I have tried the methods that are used for ActiveX DLL's but they don't seem to work.
Any thoughts???
Thanks,
chiz -
Debugging the finished DLL
2005-07-04 00:38:21 JohnDrinkall [Reply | View]
Compile with create symbolic debug symbols and use a C++ debugger.





