Câu hỏi Gọi một hàm VB6 DLL với một User Defined Type (UDT) phức tạp từ C #


Tôi đang viết một ứng dụng C # để gọi một bên thứ ba VB6 DLL. Tôi đã thêm tham chiếu đến DLL VB6 trong tab Tham khảo-> COM.

Một phương thức cụ thể trong DLL lấy một UDT UD6 (User Defined Type) làm tham số.

UDT này được hiển thị dưới dạng cấu trúc trong trình bao bọc .NET được tạo tự động cho COM. Cấu trúc có rất nhiều UDT / cấu trúc con cũng như các thành viên của loại VBA.Collection (như được hiển thị bởi siêu dữ liệu .NET). Nó cũng có các kiểu dữ liệu thông thường như chuỗi, ngắn, kép, int, v.v.

Tôi đang khởi tạo cấu trúc này trong mã C # của tôi là:

udtEmployee udtEmpData = default(udtEmployee);

Tôi cũng đã thử

udtEmpData = new udtEmployee();

Nếu tôi không khởi tạo nó bằng cách sử dụng mặc định hoặc mới, tôi không thể biên dịch mã C # của tôi, vì trình biên dịch phàn nàn về việc sử dụng biến chưa gán.

Tôi cần phải vượt qua cấu trúc này như là tài liệu tham khảo. Tôi đang làm như thế này:

clsEmployee.SetData(ref udtEmpData);

Trong khi gọi phương thức này của VB6 DLL, tôi nhận được lỗi:

Lỗi: Đã cố gắng đọc hoặc ghi bộ nhớ được bảo vệ. Đây thường là một   chỉ ra rằng bộ nhớ khác bị hỏng.

Lý do và giải pháp là gì?

Lưu ý, tôi không thể thay đổi VB6 DLL như tôi không có mã nguồn của nó. Tôi đang sử dụng VS 2005.

CHỈNH SỬA 1:

Đây là một nền tảng hoàn chỉnh:

Có một sản phẩm ERP được phát triển tại địa phương, hỗ trợ phát triển tiện ích bằng cách sử dụng VB6. Nó có một tệp cấu hình, trong đó chỉ định tên của các tệp DLL bổ sung được tải. Các addons này sau đó được hiển thị trong một menu trong ứng dụng ERP. Khi nhấp vào menu, ERP gọi một hàm có tên StartAddOn () cần có trong VB6 DLL.

Tôi muốn phát triển add-on trong C #, vì vậy tôi đã phát triển một addon VB6 đơn giản với một phương thức StartAddOn, điều này lần lượt chuyển quyền kiểm soát vào .NET DLL của tôi.

.NET DLL sử dụng các lớp nghiệp vụ mà ERP tiếp xúc và truyền các đối tượng dữ liệu đến và fro. Trong .NET DLL, tôi đã thêm một tham chiếu COM vào DLL được xuất bản bởi nhà cung cấp ERP.

Vì vậy, kiến ​​trúc là như thế này: ERP-> VB6 AddOn với phương thức StartAddOn -> .NET DLL-> sử dụng COM DLL được xuất bản bởi nhà cung cấp ERP và các lớp dữ liệu của nó (cấu trúc / UDT).

Làm cách nào để gỡ lỗi bộ nhớ?


9
2018-05-16 18:46


gốc


Nó có thể là một số tiểu cấu trúc cần 'mới' cũng như cấp độ cao nhất? Tôi chúc bạn may mắn, bạn đã có một vấn đề khó khăn ở đó. - OldBoyCoder
Tôi đã thử sử dụng mới với mỗi cấu trúc thành viên, và cũng kiểm tra xem họ lần lượt có cấu trúc khác. Tôi vẫn gặp lỗi tương tự. Cách chính xác để khởi tạo các thành viên của loại VBA.Collection là một giao diện là gì? Tôi đã thử sử dụng VBA.CollectionClass mới. Nhưng tôi nhận được một lỗi khác: Lỗi: Lấy lại nhà máy của lớp COM cho thành phần với CLSID {A4C4671C-499F-101B-BB78-00AA00383CBB} không thành công do lỗi sau: 80040154. ------------- -------------- - AllSolutions
bạn đang gọi một dll 32bit com từ một ứng dụng .net 64 bit? - Mike Miller
@AllSolutions Thử định nghĩa một lớp tĩnh trong C # và áp dụng StandardModuleAttribute cho nó. - GSerg
@AllSolutions Quên về bình luận trước đó của tôi, bạn đang sử dụng COM interop, không P / Invoke. Tôi vẫn tin rằng, mặc dù, vấn đề của bạn là marshalling và / hoặc chia sẻ bộ nhớ giữa C # và VB6. Nếu UDT có Bộ sưu tập VBA như fieds, bạn có thể cần phải thực hiện như thế này liên kết. Mặc dù, tôi không chắc chắn những gì sẽ xảy ra nếu VB6 cố gắng sửa đổi bộ sưu tập bằng cách thêm / xóa thành viên (những người sẽ sở hữu bộ nhớ sao lưu bộ sưu tập ??) - Andrés Robinet


Các câu trả lời:


Cấu trúc trông như thế nào? Nó đã được một thời gian kể từ khi tôi đã thực hiện bất kỳ phát triển VB6 nghiêm trọng, nhưng một trong những điều tôi nhớ vấp tôi lên đôi khi khi gọi giữa các ngôn ngữ đã được VB6 nhấn mạnh vào dword-aligning tất cả các cấu trúc của nó. Vì vậy, ví dụ nếu bạn có một số giá trị byte hỗn hợp ở giữa, nó sẽ chèn đệm để tất cả các giá trị căn chỉnh trên một ranh giới thậm chí 4 byte. Hãy xem xét những điều sau đây:

Type MyType
    A As Long
    B As Byte
    C As Long
End Type

Trong bộ nhớ, sẽ có 3 byte không gian không sử dụng giữa B và C. Tất nhiên nếu C # không thực hiện cùng một padding, nó có thể ném các giá trị của bạn ra và gây ra tất cả các loại hỗn loạn.

Với một số trình biên dịch (như C) có thể thiết lập một trình chuyển đổi trình biên dịch để sử dụng kiểu căn chỉnh này. Tôi không biết nếu C # có bất cứ điều gì tương tự. Nếu không, giải pháp là chèn một số trường giả của kích thước thích hợp vào cấu trúc của bạn trên kích thước C #.

Dưới đây là một bài viết cung cấp thêm thông tin về cách VB6 căn chỉnh UDT: http://www.developerfusion.com/article/3367/copymemory-and-arrays-proper-use/4/


3
2018-05-25 13:35



Việc căn chỉnh cấu trúc có thể được điều khiển bằng thuộc tính StructLayout: msdn.microsoft.com/en-us/library/… - Aloraman
UDT không có bất kỳ thành viên nào thuộc loại byte. - AllSolutions
@Aloraman, cấu trúc được tạo tự động bởi .NET khi tôi thêm một tham chiếu đến DLL COM trong dự án của tôi. - AllSolutions
Mặc dù UDT không có kiểu dữ liệu byte, nhưng nó có kiểu dữ liệu ngắn, đôi và bool và cũng là khai báo mảng của mỗi loại này. - AllSolutions
Bất cứ điều gì không có một chiều dài mà là một bội số thậm chí của 4 là nghi ngờ, bao gồm cả chuỗi độ dài cố định. Bạn sẽ nghĩ rằng nếu lớp interop được tự động gen'ing cấu trúc nó sẽ đưa này vào tài khoản, nhưng bạn không bao giờ biết. Bình luận của Aloraman về StructLayout rất thú vị. Tôi đã không nhận thức được rằng thuộc tính, nhưng nó có vẻ như câu trả lời nếu đây là vấn đề. - Steve In CO