PowerBuilder (PB) không thể trực tiếp gọi các file DLL được biên dịch bằng .NET Framework vì chúng sử dụng mô hình đối tượng khác nhau. Để tích hợp, cần đóng gói chức năng C# dưới dạng thành phần COM (Component Object Model). Bài viết này hướng dẫn quy trình tạo, đăng ký và gọi một thư viện C# từ PB.
1. Thiết lập dự án C# cho tương thích COM
Trước khi viết mã, cấu hình dự án Class Library trong Visual Studio cần được điều chỉnh để hỗ trợ COM Interop:- Kích hoạt thuộc tính COM Visible: Nhấp chuột phải vào Project -> Properties -> tab Build. Tích chọn ô Register for COM interop.
- Cấu hình AssemblyInfo.cs: Mở file
AssemblyInfo.csvà đảm bảo thuộc tính sau được đặt làtrue:
[assembly: ComVisible(true)]
Lưu ý quan trọng: Mỗi Interface và Class sẽ được gán một GUID (Globally Unique Identifier) riêng biệt. Nếu không chỉ định thủ công, trình biên dịch sẽ tự sinh ra, nhưng việc quản lý thủ công giúp ổn định phiên bản khi tái triển khai.
2. Viết mã nguồn C#
Dưới đây là ví dụ về một lớp tiện ích thực hiện phép cộng hai số nguyên. Cấu trúc bao gồm một Interface (để định nghĩa hợp đồng giao tiếp) và một Class (để cài đặt logic).using System;
using System.Runtime.InteropServices;
namespace NetInteropLib
{
// Định nghĩa Interface với GUID duy nhất
[Guid("A1B2C3D4-E5F6-7890-ABCD-EF1234567890")]
public interface ICalculatorService
{
// DispId giúp ánh xạ phương thức sang COM ID
[DispId(1)]
int CalculateSum(int value1, int value2);
[DispId(2)]
string GetVersionInfo();
}
// Cài đặt Interface vào Class cụ thể
[Guid("F9E8D7C6-B5A4-3210-FEDC-BA0987654321")]
[ClassInterface(ClassInterfaceType.None)] // Không tự động xuất các interface kế thừa
public class CalculatorImpl : ICalculatorService
{
public int CalculateSum(int value1, int value2)
{
return value1 + value2;
}
public string GetVersionInfo()
{
return "v1.0.0";
}
}
}
3. Đăng ký thư viện COM trên hệ thống
Sau khi build ra file `.dll`, bạn cần đăng ký nó vào Registry Windows để PB có thể tìm thấy. Sử dụng công cụ `RegAsm.exe` đi kèm với .NET Framework.Cách 1: Dùng dòng lệnh (Command Prompt)
Mở Command Prompt với quyền Administrator và chạy lệnh sau (thay đổi đường dẫn cho phù hợp):
# Đăng ký
C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe YourLibrary.dll /tlb:YourLibrary.tlb
# Hủy đăng ký (khi cần cập nhật hoặc gỡ bỏ)
C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe /u YourLibrary.dll
Tệp `.tlb` (Type Library) được sinh ra sẽ chứa metadata mô tả các hàm và kiểu dữ liệu của COM component.
Cách 2: Gọi từ PowerBuilder
Bạn cũng có thể tự động hóa việc đăng ký ngay trong code PB nếu đã sao chép `RegAsm.exe` vào thư mục ứng dụng:
// Lệnh đăng ký lại
Run("regasm MyLib.dll /tlb:MyLib.tlb", minimized!)
4. Code gọi từ PowerBuilder
Sử dụng đối tượngOLEObject để khởi tạo kết nối tới COM Component. Dưới đây là mẫu code xử lý lỗi và giải phóng tài nguyên đúng cách.
OLEObject oleCalc
long ll_ret_code
int li_result
string ls_version
// 1. Khởi tạo đối tượng OLE
oleCalc = Create OLEObject
// 2. Kết nối đến Class đã đăng ký
// Lưu ý: Chuỗi tham số phải khớp với namespace.classname trong C#
ll_ret_code = oleCalc.ConnectToNewObject("NetInteropLib.CalculatorImpl")
IF ll_ret_code <> 0 THEN
MessageBox("Lỗi", "Không thể kết nối tới COM Object. Mã lỗi: " + String(ll_ret_code))
// Xử lý phục hồi: Thử hủy đăng ký và đăng ký lại nếu cần thiết
Run("regasm /u NetInteropLib.dll", minimized!)
Run("regasm NetInteropLib.dll /tlb:NetInteropLib.tlb", minimized!)
// Thử kết nối lại
ll_ret_code = oleCalc.ConnectToNewObject("NetInteropLib.CalculatorImpl")
END IF
IF ll_ret_code = 0 THEN
// 3. Gọi phương thức
li_result = oleCalc.CalculateSum(10, 20)
ls_version = oleCalc.GetVersionInfo()
MessageBox("Kết quả", "Tổng: " + String(li_result) + "~nPhiên bản: " + ls_version)
ELSE
MessageBox("Lỗi", "Vẫn chưa thể kết nối sau khi thử lại.")
END IF
// 4. Giải phóng tài nguyên
// Quan trọng: Phải gọi DisconnectObject SAU khi hoàn tất mọi thao tác gọi hàm
oleCalc.DisConnectObject()
DESTROY oleCalc
5. Các lưu ý kỹ thuật quan trọng
- Mã lỗi -3 (Object could not be created): Thường xảy ra khi thiếu sự tương thích giữa kiến trúc bit (32-bit vs 64-bit). Đảm bảo rằng PowerBuilder và .NET Framework/COM Registration cùng chung một kiến trúc (ví dụ: cả hai đều 32-bit hoặc cả hai đều 64-bit).
- Vị trí File: Các file liên quan (`YourLibrary.dll`, `YourLibrary.tlb`, và `RegAsm.exe` nếu dùng cách 2) nên được đặt trong cùng một thư mục làm việc hoặc thư mục gốc của ứng dụng PB để tránh lỗi tìm kiếm đường dẫn.
- Quản lý trạng thái kết nối: Giá trị trả về của
ConnectToNewObjectlà 0 nghĩa là thành công. Bất kỳ giá trị nào khác đều là lỗi. Luôn kiểm tra biến trạng thái trước khi gọi các phương thức bên trong. - Giải phóng bộ nhớ: Việc gọi
DisConnectObject()phải nằm ở cuối cùng, sau khi đã lấy hết các giá trị cần thiết từ các hàm gọi trước đó. Nếu gọi sớm, các tham chiếu nội bộ có thể bị mất, dẫn đến crash hoặc trả về giá trị rác.