2009-12-14 31 views
6

Tôi không nói về việc gọi một VBA COM từ C# ... theo cách khác xung quanh!Inter-by-Side COM Interop với C# và VBA

Điều tôi muốn làm là gọi thư viện C# bằng VBA trong MS Access mà không cần đăng ký DLL. Tôi đã chơi xung quanh với interop side-by-side trong một thời gian không thành công và cuối cùng nó đã xảy ra với tôi rằng một mdb.manifest có lẽ không phải là một sự thay thế chấp nhận được cho một exe.manifest (có lẽ hiển nhiên, tôi biết, nhưng tôi đã cố gắng lạc quan).

Câu hỏi của tôi: Có thể tải VBA để tải thành phần COM cạnh nhau không?

Hoặc, có cách nào khác để sử dụng thư viện C# chưa đăng ký trong Access không?

(Trước khi bạn hỏi, lý do của tôi là: hoàn toàn không có cách nào tôi sẽ được cấp quyền truy cập vào đăng ký Windows của khách hàng - đó là lý do tại sao nó được viết trong Access ngay từ đầu. Và, tôi sẽ cần triển khai cùng một chức năng trong một ứng dụng C# sớm và thay vì không thực hiện nó hai lần).

Trả lời

3

Bạn không phải sở hữu exe để sử dụng SxS, SxS là một từ khác cho Activation Context. Nếu bạn có thể nhập các cuộc gọi win32 liên quan vào vba (và bạn có thể), thì bạn có thể sử dụng activation context api để tải tệp kê khai của mình.

Tìm hiểu thêm về chủ đề và một số ví dụ có thể được tìm thấy here.

+0

Tôi đã xem xét sử dụng API đó. Trớ trêu thay, Microsoft đã tạo ra một gói để tránh đăng ký yêu cầu đăng ký và để lại cùng một câu hỏi mà tôi đã có trước đây - làm thế nào để có được nó trên máy khách của tôi? Mặc dù Microsoft.Windows.Actctx có sẵn cho Windows 2K3 + nhưng nó chỉ được bao gồm trong cài đặt Máy chủ. Có một câu hỏi SO khác phàn nàn về điều đó ở đây: http://stackoverflow.com/questions/979567/microsoft-windows-actctx-on-windows-xp. Và MSDN sao lưu nó lên đây: http://msdn.microsoft.com/en-us/library/aa375644(VS.85).aspx. – Jelly

+0

Từ những gì tôi biết API ngữ cảnh kích hoạt là một phần của Kernel32.lib, có nghĩa là bạn không cần phải cài đặt bất kỳ thứ gì, và nó được bao gồm trong bất kỳ hệ điều hành nào có hỗ trợ cho SxS là WinXP SP2 và cao hơn. Tôi đã tự thực hiện trên WinXP SP3 và nó hoạt động mà không cần cài đặt đặc biệt. Tôi không biết về Microsoft.Windows.Actctx, nhưng tôi chắc chắn 100% bạn có thể gọi trực tiếp API bằng cách nhập các hàm có liên quan từ Kernel32.lib và gọi chúng trực tiếp. Giống như nó được trình bày tại mã mẫu này http://www.mazecomputer.com/sxs/help/sxsapi3.htm –

+0

Tôi hiểu rồi. Tất cả các ví dụ trên web tôi đã thấy làm điều này trong VBA sử dụng các đối tượng Actctx thay vì API đó là lý do duy nhất tôi ban đầu kết luận rằng nó không thể được thực hiện trong mã. Rõ ràng, nó được thực hiện cả hai cách (và được gọi là điều tương tự) chỉ để gây nhầm lẫn cho tôi. Tôi không nên có quá nhiều rắc rối khi làm việc này và chạy - và nó phải là một giải pháp ổn định hơn là hack IL - vì vậy tôi sẽ di chuyển cờ giải pháp được chấp nhận khi tôi đến đó. Cảm ơn đã giúp đỡ! – Jelly

0

Thư viện C# không phải là các tệp DLL thông thường. Chúng tương tự như các thư viện COM cần được đăng ký (giống như các điều khiển ActiveX) trước khi được sử dụng; đặc biệt khi được gọi từ mã không phải.

(Trừ khi, tất nhiên, mọi thứ đã thay đổi ...)

+0

Ấn tượng của tôi rằng C# DLL có thể được sử dụng chưa đăng ký đến từ đây: http://msdn.microsoft.com/en-us/library/ms973915.aspx nơi có máy chủ C# .NET và máy khách không phải là .NET. Tôi tin rằng đó là cơ bản tương đương với những gì tôi muốn làm khác hơn là thực tế là khách hàng là một thực thi VB6 thay vì một ứng dụng VBA. Có cái gì khác mà tôi đang thiếu? Cảm ơn! – Jelly

+0

Bạn có thể gặp khó khăn trong phần mà bạn cần tạo tệp kê khai cho khách hàng, vì VBA không phải là một chương trình độc lập mà bạn có thể tạo một tệp. Tệp kê khai trông đơn giản, nhưng tôi không thể nói chắc chắn cách liên kết nó một cách chính xác. Có lẽ bạn có thể nhận được VBA để thực thi một máy khách độc lập thực hiện những gì bạn cần? – Ioan

1

Vấn đề là sử dụng SxS, bạn cần phải sở hữu exe để thiết lập cấu hình để tải lắp ráp SxS. Bạn không "sở hữu" truy cập, và trong khi bạn có thể thả các cấu hình bên phải trong để làm cho nó để tải của bạn NET COM công cụ sans đăng ký, nó sẽ không phải là một "công dân tốt" di chuyển.

Nếu bạn gặp khó khăn với việc cắt xén, bạn có thể thiết lập một DLL không được quản lý (hoặc thư viện lớp C# bị tấn công bằng dllexport, xem ví dụ this) với một xuất sẽ tải khung .NET. một kiểu quản lý DispInterface có thể chấp nhận được và trả về nó (phương thức sẽ trả về IDispatch). Sau đó viết một VBA khai báo cho hàm xuất DLL của bạn (được khai báo là đối tượng trả về). Nếu điều này không có ý nghĩa, bạn có lẽ không nên thử nó ... :) Tôi đã làm điều này trước khi trong một tình huống tương tự, và nó không hoạt động, nhưng tôi không có một mẫu để chỉ cho bạn tại.

+0

Đó là rất thông minh và nó thực sự có ý nghĩa. Tôi đã không tìm thấy bất cứ điều gì khi tôi đang tìm kiếm trước khi hack IL để buộc C# xuất một phương thức. Tôi có một phần để làm việc và tôi không nghĩ rằng nó sẽ là quá nhiều khó khăn hơn để có được nó để làm cho một điểm vào để trả lại một đối tượng quá. Cám ơn vì sự gợi ý! – Jelly

8

Để thêm vào các câu trả lời đã có sẵn: với .NET 4.0 , nó thực sự khá đơn giản để tiêu thụ một C# dll trong dự án VBA của bạn mà không cần đăng ký COM.

EDIT: Tôi chỉ cố gắng này với mscorlib.tlbmscoree.tlb có trong C:\windows\Microsoft.NET\Framework\v2.0.50727 - tải một hội đồng biên soạn trong 3.5-- và nó chỉ làm việc tốt. Vì vậy, rõ ràng bạn không cần .NET 4.0.

Dưới đây là ví dụ về cách sử dụng C# dll trong dự án VBA của bạn. Nó được sửa đổi một chút từ câu trả lời this.

1) Thêm tài liệu tham khảo để libs loại vật liệu làm dự án VBA của bạn (Tools-> Tài liệu tham khảo):

C:\windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.tlb 
C:\windows\Microsoft.NET\Framework\v4.0.30319\mscoree.tlb 

(sử dụng thư mục Framework64 nếu bạn đang chạy phiên bản 64-bit Office)

2) Trong dự án # C của bạn, hãy chắc chắn bạn thêm thuộc tính [ComVisible(true)] đến lớp học của bạn:

using System.Windows.Forms; 
using System.Runtime.InteropServices; 
namespace VB6FuncLib 
{ 
    [ComVisible(true)] 
    public class VB6FuncLib 
    { 
     public VB6FuncLib() 
     { } 
     public void test() 
     { 
      MessageBox.Show("Test Successful"); 
     } 
    } 
} 

bạn không cần phải chec k tùy chọn "Đăng ký COM Interop". Đó là chỉ để xây dựng một đối tượng COM tiêu chuẩn. Bạn không cần phải kiểm tra "Make Assembly COM Visible" hoặc là, trừ khi bạn muốn toàn bộ assembly được hiển thị (điều đó cũng sẽ loại bỏ sự cần thiết cho thuộc tính COMVisible).

3) Trong mã VBA của bạn, thêm một module mới với mã này:

Sub Test() 
    Dim Host As mscoree.CorRuntimeHost 
    Set Host = New CorRuntimeHost 
    Host.Start 
    Dim Unk As IUnknown 
    Host.GetDefaultDomain Unk 
    Dim AppDomain As AppDomain 
    Set AppDomain = Unk 
    Dim ObjHandle As ObjectHandle 
    Set FS = CreateObject("Scripting.FileSystemObject") 
    Path = FS.GetParentFolderName(CurrentDb().Name) 
    Set ObjHandle = AppDomain.CreateInstanceFrom(Path & "\VB6 Function Library.dll", "VB6FuncLib.VB6FuncLib") 
    Dim ObjInstance As Object 
    Set ObjInstance = ObjHandle.Unwrap 
    ObjInstance.test 
    Host.Stop 
End Sub 

4) Sao chép DLL vào thư mục tương tự như dự án văn phòng của bạn và chạy thử nghiệm() phụ trong VBA.

Ghi chú:

Cần lưu ý rằng một trong những hạn chế của phương pháp này là nó sẽ không hoạt động nếu DLL được lưu trữ trên một mạng chia sẻ từ xa. Một giải pháp đơn giản là sao chép nó vào cùng một thư mục cục bộ trên mỗi máy tính mà nó đang được sử dụng. Một giải pháp khác là bao gồm các tệp nhị phân trong dự án ứng dụng Access/VBA của bạn và có MS-Access xuất chúng. Một cách có thể được thực hiện bằng cách lưu trữ chúng trong Base64 trong một bảng hoặc bảng tính, sau đó chuyển đổi chúng và xuất chúng dưới dạng nhị phân.

Tôi đã có thể nhận được ràng buộc sớm (và do đó Microsoft IntelliSense) để làm việc bằng cách tạo một thư viện kiểu để đi với DLL (bằng cách sử dụng tlbexp), và thêm một tham chiếu đến TLB trong dự án VBA của tôi, nhưng nó phức tạp vấn đề một chút bởi vì nó đòi hỏi ứng dụng VBA của bạn để biết nơi cả DLL và các tập tin TLB (và cũng đòi hỏi một ai đó để đảm bảo rằng họ đang có).

Các vấn đề liên quan