Tạo standard DLL từ VB6

tuhocvba

Administrator
Thành viên BQT
Chắc các anh em đều đã biết Delphi hay VC đều có thể tạo được API.
Theo lý thuyết thì VB6 không làm được điều này.
Do đó, ở topic này, tôi sẽ hướng dẫn anh em làm điều này.
Lợi ích: File DLL anh em tạo ra sẽ không cần đăng ký. Có nghĩa là khi chia sẻ ra bên ngoài sẽ vô cùng thuận lợi.
Kết hợp với (dự kiến công khai 28/10/20201), tôi hi vọng anh em sẽ có thêm một sự lựa chọn tốt để bảo mật code của mình.


1. Tạo file Link.exe
Mở VB6 với quyền admin. Chọn standard exe.
Remove form vì không cần.
Trên đó tạo module bất kỳ, ghi code như sau:
Mã:
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 Sub
Build ra file Link.exe, copy vào thư mục ngoài Destop .
Mình có chia sẻ file Link.exe do mình tạo ra, các bạn có thể dùng luôn.
2. Đổi tên file Link.exe thành LinkLnk.exe
File này trên máy tính của mình nó nằm ở đây:
Mã:
C:\Program Files (x86)\Microsoft Visual Studio\VB98
Việc đổi tên thành như trên là rất quan trọng, tốt nhất hãy copy tên kẻo nhầm lẫn.

Sau đó copy file Link.exe mà bạn đã tạo ở bước 1 vào thư mục VB98 ở trên.

3. Tạo DLL
3.1 Tạo file def

Tôi muốn tạo ra file Fibonacci.dll
Do đó trước hết tôi sẽ tạo ra file Fibonacci.def
Nội dung của nó như sau:
Mã:
NAME MathLib
LIBRARY MathMod
DESCRIPTION "Add-on Library of Mathematical Routines"
EXPORTS DllMain @1
        Fibo @2
3.2 Tạo file dll
Tạo ActiveX DLL project
Class1 để đó, không có nội dung gì.
Chèn Module mới, trên đó viết code:
Mã:
Public Const DLL_PROCESS_DETACH = 0
Public Const DLL_PROCESS_ATTACH = 1
Public Const DLL_THREAD_ATTACH = 2
Public Const DLL_THREAD_DETACH = 3

Public Function DllMain(hInst As Long, fdwReason As Long, _
    lpvReserved As Long) As Boolean
   Select Case fdwReason
      Case DLL_PROCESS_DETACH
         ' No per-process cleanup needed
      Case DLL_PROCESS_ATTACH
         DllMain = True
      Case DLL_THREAD_ATTACH
         ' No per-thread initialization needed
      Case DLL_THREAD_DETACH
         ' No per-thread cleanup needed
   End Select
End Function

' Return a Fibonacci number.
Public Function Fibo(ByVal N As Integer) As Long
    If N <= 1 Then
        Fibo = 1
    Else
        Fibo = Fibo(N - 1) + Fibo(N - 2)
    End If
End Function
Lưu project cùng đường dẫn với file .def mà bạn tạo ở trên.
Tiếp theo build ra dll.

Vậy là xong. Bây giờ mình sẽ test thử DLL này.
Tạo project standard exe, trong form 1 viết code như sau:
Mã:
Private Declare Function Fibo Lib "C:\Users\user\Desktop\TEST1\Fibonacci.dll" (ByVal N As Integer) As Long
Private Sub cmdCalculate_Click()
    lblFibo.Caption = Format$(Fibo(CInt(txtN.Text)))
End Sub
Bạn cần đăng nhập để thấy đính kèm


Như vậy là thành công. Nói cách khác, DLL này cũng có thể thông qua Exe và chạy trên .
Nguồn tham khảo :
 

Đính kèm

B

bvtvba

Guest
Hay thật. Em đã làm được. function thì hoạt động rất tốt. Còn sub thì chưa được như ý muốn.
MyDLLX.def:
NAME THVBALib
LIBRARY ToolX
DESCRIPTION "Add-on Library of Mathematical Routines"
EXPORTS DllMain @1
        tinhtong @2
        pheptru @3
        thongbao @4
MyDLL.Xdll:
Public Const DLL_PROCESS_DETACH = 0
Public Const DLL_PROCESS_ATTACH = 1
Public Const DLL_THREAD_ATTACH = 2
Public Const DLL_THREAD_DETACH = 3

Public Function DllMain(hInst As Long, fdwReason As Long, _
    lpvReserved As Long) As Boolean
   Select Case fdwReason
      Case DLL_PROCESS_DETACH
         ' No per-process cleanup needed
      Case DLL_PROCESS_ATTACH
         DllMain = True
      Case DLL_THREAD_ATTACH
         ' No per-thread initialization needed
      Case DLL_THREAD_DETACH
         ' No per-thread cleanup needed
   End Select
End Function

Public Function tinhtong(ByVal a As Integer, ByVal b As Integer) As Integer
    tinhtong = a + b
End Function
Public Function pheptru(ByVal sobitru As Integer, ByVal sotru As Integer) As Integer
    pheptru = sobitru - sotru
End Function
Public Sub thongbao(ByVal s As String)
    MsgBox s
End Sub
Tiến hành thực nghiệm
Mã:
Private Declare Sub thongbao Lib "D:\VBA\MyDLLX.dll" (ByVal s As String)

Private Sub Command1_Click()
    thongbao ("xxx")
End Sub
Bạn cần đăng nhập để thấy hình ảnh

Các hàm tinhtong, pheptru đều hoạt động tốt. Chắc phải xem lại cấu trúc DEF để cho Sub hoạt động.
 

tuhocvba

Administrator
Thành viên BQT
Chắc do phần này quy định nên thấy function thì hoạt động rất tốt, còn sub thì chưa. hi.
Bạn cần đăng nhập để thấy đính kèm
 

NhanSu

SMod
Thành viên BQT
Các bạn thử dùng hàm StrConv(s,128) để truyền tham số cho DLL xem, do chuỗi trong VBA là unicode 2 bytes còn DLL đang dùng chuỗi 1 byte.
 
B

bvtvba

Guest
Các bạn thử dùng hàm StrConv(s,128) để truyền tham số cho DLL xem, do chuỗi trong VBA là unicode 2 bytes còn DLL đang dùng chuỗi 1 byte.
Bạn cần đăng nhập để thấy hình ảnh
 

PTHhn

Yêu THVBA như điếu đổ
Cái này trước kia trên clbvb cũng có bàn tới, nhưng cũng không thấy đưa ra vấn đề dùng cho Sub.
Với cách này, thường chỉ thấy mọi người dùng cho hàm (function).
Xin trích dẫn:
Nguồn:
Mã:
https://caulacbovb.com/forum/viewtopic.php?t=14308
========================
1. Một số khái niệm:
  • +DllMain: Là hàm khởi tạo (và cũng là hàm huỷ) trong DLL. Windows sẽ gọi hàm DllMain trong DLL mỗi khi DLL được sử dụng đến hoặc ngưng sử dụng. Vì vậy hàm DLLMain sẽ được sử dụng để khởi tạo và huỷ các biến cần thiết. DllMain có thể có hoặc không cũng được (tuỳ vào DLL mà bạn viết có cần khởi tạo và dọn dẹp hay không)
    +Module Definition File: Là tệp tin mô tả các module ở trong file DLL. File DLL kiểu Standard khi viết ra có thể có nhiều hàm ở trong. Tệp mô tả sẽ chỉ ra thứ tự các hàm, nó tham gia vào quá trình biên dịch mã nguồn thành tệp DLL. Tệp mô tả có phần mở rộng là DEF
[Phần này đáng tham khảo thêm]
2. Mod lại file Link.exe:
  • A. File Link.exe đóng vai trò gì?
    + Trong IDE của Vb6, khi ta chọn Make chương trình của ta thành file DLL (kể cả khi ta make chương trình thành file EXE) thì IDE sẽ trước tiên gọi file C2.exe để dịch code của chúng ta thành các file *.OBJ. Sau đó nó gọi tiếp file Link.exe để liên kết các file *.OBJ lại tạo ra file DLL hoặc file EXE. Vậy file Link.exe đóng vai trò liên kết các file OBJ để tạo ra tệp dạng binary (Exe hoặc DLL) cuối cùng. Cả file C2.Exe và file Link.exe đều nằm trong C:\Program Files\Microsoft Visual Studio\VB98
    B. Vì sao phải Mod lại file Link.exe?

    + Trong VB6, khi IDE gọi file Link.exe để liên kết các file *.OBJ lại, nó truyền cho file Link.exe một loạt các tham số như: đường dẫn của các file *.OBJ, kiểu file đích sẽ tạo ra (DLL hay EXE), đường dẫn của đích sẽ được tạo ra, và 1 số các tham số khác nữa. Tuy nhiên, trong rất nhiều tham số này, lại thiếu mất một tham số là "/DEF". Tham số /DEF chính là tham số chỉ ra đường dẫn của các tệp Module Definition (các tệp *.DEF) ở phần 1. Thiếu các tệp này, DLL tạo ra sẽ không thể sử dụng được các hàm Public bằng phương pháp Declare. Chính vì vậy, ta phải Mod lại file Link.exe để thêm tham số này vào lúc biên dịch
    C. Mod lại file Link.exe như thế nào?
    + Phương pháp ở đây là tạo ra 1 file Link.exe giả đặt trong thư mục VB98, còn file Link.exe thật thì đổi tên thành 1 file khác (ví dụ là LinkThat.exe). Khi IDE gọi file Link.exe giả (do ta mod lại) thì file giả của chúng ta sẽ làm nhiệm vụ đọc các tham số được IDE truyền sang, thêm tham số /DEF vào và gọi file LinkThat.exe với tham số mới (đã có /DEF). Tất nhiên là phải kiểm tra, nếu có tồn tại các file *.DEF và project cần tạo là project kiểu DLL thì mới thêm tham số
    + Tiến hành Mod lại file Link.exe
    - Mở Vb6, tạo 1 Project mới dạng EXE application
    - Xoá Form1 mà Vb đã tự tạo ra cho ta, thêm vào 1 Module mới, đặt tên bất kỳ
    - Add Reference vào tệp SCRRUN.DLL trong System32 để sử dụng được đối tượng FileSystemObject
    - Copy đoạn code sau, Paste vào Module vừa thêm:
[Đoạn này giống với bài viết #1 nên tôi lược bỏ]
- Dịch chương trình trên thành file Link.exe
- Đổi tên file Link.exe vốn đã có của Vb6 (trong C:\Program Files\Microsoft Visual Studio\VB98) thành linklnk.exe LinkThat.exe
[Phần này giống với #1 đã nêu. Phụ thuộc vào code mà chúng ta viết ở trên.]
Dòng code 91 ở #1 :
Mã:
Shell "linklnk.exe " & strCmd
nên chúng ta thống nhất dùng linklnk.exe
- Copy file Link.exe mà ta vừa tạo được ở trên vào thư mục Vb98

3. Cùng tạo DLL nào
  • - Tạo 1 Project mới trong Vb6, kiểu Project là ActiveX DLL
    - Để nguyên Class1 mà Vb6 đã tạo sẵn cho bạn. Không cần Code gì vào đó cả, nhưng vẫn phải giữ nó lại vì Vb6 cần phải có 1 Class trong Project kiểu ActiveX DLL thì nó mới chạy
    - THêm 1 Module mới với tên tuỳ ý. Bạn có thể bắt đầu viết các hàm cho riêng mình vào Module này. Tôi đưa ra 1 ví dụ đơn giản với các hàm tính toán. Module của tôi có dạng như sau:
    Trừ hàm DllMain, các hàm khác các bạn có thể thêm bớt tuỳ ý
[Phần này cũng giống #1 đã nêu, tôi trích dẫn lại mang tính bổ sung thông tin]
4. Tạo tệp Module Definition File (.DEF)
- Dùng Notepad, soạn với nội dung sau:
Mã:
NAME TenTuyY
LIBRARY TenTuyY
DESCRIPTION "Mo ta cua tep DLL- gi cung duoc"
EXPORTS DllMain @1
        Add @2
        Subtract @3
        Square @4
  • - Phần nội dung sau NAME, LIBRARY, DESCRIPTION bạn có thể đặt tuỳ ý
    - Theo sau EXPORTS là tên các hàm. Nhớ là tên hàm phân biệt hoa-thường nha
    - Con số sau ký tự @ là thứ tự của hàm mà bạn đã viết trong Module ở trên
    - Lưu tệp soạn thảo này vào thư mục chứa file Project DLL mà ta đã tạo ở bước 3 với tên trùng với tên DLL mà ta muốn tạo, phần mở rộng là .DEF. Ví dụ: nếu ta muốn tạo ra 1 dll có tên là MyLibrary.DLL thì file DEF này sẽ phải lưu với tên là MyLibrary.DEF
[Phần này giống với #1 đã nêu, tôi trích dẫn để bổ sung thông tin]

5. Dịch thành file DLL và sử dụng
- Bây giờ bạn có thể Make cái Project bạn đã tạo ở bước 3 được rồi. từ menu File, chọn Make như với các Project bình thường khác
- Sau khi được file DLL rồi thì chắc là các bạn đã biết cách sử dụng nó như thế nào:
+ Copy file DLL vào cùng thư mục với Project muốn sử dụng nó
+ Khai báo như sau để Import hàm của DLL vào Project
Mã:
Private Declare Function Add Lib "MyLibrary.dll" (ByVal a As Integer, ByVal b As Integer) As Integer
[Phần này đáng tham khảo thêm]
 

NhanSu

SMod
Thành viên BQT
Mình cài VB6 báo lỗi lung tung hết nên không thử được. Mình vẫn nghi lỗi khi truyền tham số là chuỗi. Các bạn thử dùng hàm với tham số chuỗi xem có lỗi không?
 

tuhocvba

Administrator
Thành viên BQT
Với activeX DLL thì cũng vẫn truyền tham số như VBA đâu có lỗi gì đâu .
Với stamdard DLL thì sub chưa hoạt động đúng .
 
B

bvtvba

Guest
Em xin tóm tắt lại quy trình tạo standard DLL từ VB6.
Xác nhận đã hoạt động tốt với Function.
Bạn cần đăng nhập để thấy đính kèm
 

tuhocvba

Administrator
Thành viên BQT
Cái này không liên kết trực tiếp với Excel được đâu, phải qua Exe, tức là chúng ta vẫn phải .
Smod @NhanSu tìm cách khắc phục cài đặt VB6 thôi. Xem lỗi ở đâu thì để mọi người hỗ trợ.
 

NhanSu

SMod
Thành viên BQT
Exe và dll thì dịch ngược cũng như nhau mà. Chú ý khi build cần chọn Compile to native code để khó dịch ngược hơn pcode.
 

tuhocvba

Administrator
Thành viên BQT
Exe và dll thì dịch ngược cũng như nhau mà. Chú ý khi build cần chọn Compile to native code để khó dịch ngược hơn pcode.
Cho mình xin cụ thể bằng hình ảnh, chọn ở đâu, như nào.
 
D

Deleted member 199

Guest
Exe và dll thì dịch ngược cũng như nhau mà. Chú ý khi build cần chọn Compile to native code để khó dịch ngược hơn pcode.
Theo em, bác thực sự biết thì nói. Hoặc thực sự làm thực tế rồi ấy.
 

Euler

Administrator
Thành viên BQT
Bảo các bạn viết thì các bạn bảo không có khả năng viết. Kẻ thì bảo chỉ chuyên về thực hành.
Người khác viết thì các bạn ngồi như ông kễnh nói sao với răng.
Sao với răng nếu biết thì viết, khi viết thì dẫn chứng bằng hình ảnh cho dễ hiểu. Admin cũng không phải là thánh.
 
Top