2012-10-23 29 views
5

Tôi muốn viết một plugin WinMerge để dịch cơ sở dữ liệu SQLite thành văn bản, vì vậy tôi có thể sử dụng WinMerge để so sánh cơ sở dữ liệu.Cách viết một plugin WinMerge trong C# (hoặc VB.NET)

Tôi đã viết mã bằng C# để thực hiện chuyển đổi, nhưng dường như tôi không thể làm cho nó xuất hiện dưới dạng plugin WinMerge. Nhưng tôi không quen thuộc với việc viết các đối tượng .NET có thể nhìn thấy được.

Tôi đoán tôi không được đặt đúng thuộc tính COM (tôi chỉ cần đặt ComVisible (true) trên lớp). Tuy nhiên, tôi nghĩ rằng VB.Net là nghĩa vụ phải làm tất cả những thứ đó cho bạn, vì vậy tôi viết lại lớp trong VB.Net, sử dụng lớp Project/Add New/COM. Tuy nhiên, nó vẫn không xuất hiện trong WinMerge như một plugin được nạp.

Trong tuyệt vọng, tôi đã thử nhìn vào VB DLL bằng cách sử dụng DLL Export Viewer, nhưng nó không hiển thị bất kỳ chức năng được xuất. Tôi rõ ràng đang làm điều gì đó sai.

Đây là mã đầy đủ:

<ComClass(WinMergeScript.ClassId, WinMergeScript.InterfaceId, WinMergeScript.EventsId)> _ 
Public Class WinMergeScript 

#Region "COM GUIDs" 
    ' These GUIDs provide the COM identity for this class 
    ' and its COM interfaces. If you change them, existing 
    ' clients will no longer be able to access the class. 
    Public Const ClassId As String = "9b9bbe1c-7b20-4826-b12e-9062fc4549a0" 
    Public Const InterfaceId As String = "b0f2aa59-b9d0-454a-8148-9715c83dbb71" 
    Public Const EventsId As String = "8f4f9c82-6ba3-4c22-8814-995ca1050de6" 
#End Region 

    Dim _connection As SQLite.SQLiteConnection 
    Dim _output As IO.TextWriter 
    Dim _error As Long 
    Dim _errordesc As String 

    ' A creatable COM class must have a Public Sub New() 
    ' with no parameters, otherwise, the class will not be 
    ' registered in the COM registry and cannot be created 
    ' via CreateObject. 
    Public Sub New() 
     MyBase.New() 
    End Sub 

    Public ReadOnly Property PluginEvent() As String 
     Get 
      PluginEvent = "FILE_PACK_UNPACK" 
     End Get 
    End Property 

    Public ReadOnly Property PluginDescription() As String 
     Get 
      PluginDescription = "Display Sqlite Databases in tab-delimited format" 
     End Get 
    End Property 

    Public ReadOnly Property PluginFileFilters() As String 
     Get 
      PluginFileFilters = "\.db$" 
     End Get 
    End Property 

    Public ReadOnly Property LastErrorNumber() As Long 
     Get 
      LastErrorNumber = _error 
     End Get 
    End Property 

    Public ReadOnly Property LastErrorString() As String 
     Get 
      LastErrorString = _errordesc 
     End Get 
    End Property 

    Public Function UnpackFile(ByVal fileSrc As String, ByVal fileDst As String, ByRef bChanged As Boolean, ByRef subcode As Long) As Boolean 
     On Error GoTo CleanUp 
     subcode = 1 
     _error = 0 
     _errordesc = "" 
     Using connection As New SQLite.SQLiteConnection("Data Source=" + fileSrc + ";Version=3;DateTimeFormat=ISO8601;") 
      _connection = connection 
      Using output As New IO.StreamWriter(fileDst) 
       _output = output 
       For Each table As DataRow In Query("Select name from sqlite_master where type = 'table' order by name") 
        Dump(table(0).ToString()) 
       Next 
      End Using 
     End Using 
     bChanged = True 
     UnpackFile = True 
     Exit Function 
CleanUp: 
     _error = Err().Number 
     _errordesc = Err().Description 
     bChanged = False 
     UnpackFile = False 
    End Function 

    Sub Dump(ByVal tablename As String) 
     Dim reader As IDataReader 
     Using cmd As New SQLite.SQLiteCommand(_connection) 
      cmd.CommandText = "Select * from """ + tablename + """" 
      cmd.CommandType = CommandType.Text 
      reader = cmd.ExecuteReader() 
      Using reader 
       _output.WriteLine("==== " + tablename + " ====") 
       Dim data(reader.FieldCount) As String 
       For i As Integer = 0 To reader.FieldCount - 1 
        data(i) = reader.GetName(i) 
       Next 
       Dump(data) 
       While reader.Read() 
        For i As Integer = 0 To reader.FieldCount - 1 
         data(i) = reader.GetValue(i).ToString() 
        Next 
        Dump(data) 
       End While 
      End Using 
     End Using 
    End Sub 

    Sub Dump(ByVal data() As String) 
     _output.WriteLine(String.Join(vbTab, data)) 
    End Sub 

    Function Query(ByVal sql As String) As DataRowCollection 
     Dim cmd As SQLite.SQLiteCommand 
     cmd = _connection.CreateCommand() 
     Using cmd 
      cmd.CommandText = sql 
      Using da As New SQLite.SQLiteDataAdapter(cmd) 
       Dim dt As New DataTable() 
       da.Fill(dt) 
       Query = dt.Rows 
      End Using 
     End Using 
    End Function 
End Class 

Trả lời

1

Tôi chỉ là bây giờ xem xét mã thực tế của WinMerge 2.14.0, và tôi nghĩ rằng nó chỉ hoạt động cho DLL COM thực (và OCXs), chủ yếu là do nó hoạt động mà không mong đợi các đối tượng COM được đăng ký. Nó sẽ cần phải được mở rộng để ít nhất là tham chiếu đến .TLB hoặc được điều chỉnh để cho phép không có đường dẫn nào được chỉ định, nhưng một ID rõ ràng hơn "WinMergeScript".


Đối tượng VB.NET COM đang hoạt động, tôi đã đề cập rõ ràng <ComVisible(True)> _ và dự án đã "Đăng ký COM" được chọn trong Thuộc tính biên dịch.

Tôi vừa tạo một hàm HelloWorld bằng mã của bạn, biên dịch bằng vbc /t:library và đăng ký với regasm /codebase. Đây được gọi là thành công sử dụng VBScript đơn giản này (sử dụng wscript):

Option Explicit 
Dim so 
Set so = CreateObject("SO13035027.WinMergeScript") 
MsgBox so.HelloWorld 

Và toàn bộ mã (Tôi không cấu hình lại hệ thống của tôi sử dụng một sau vbc vì vậy đây thực sự đã được biên soạn để .NET 1.1):

Option Explicit On 
Option Strict On 
'Option Infer On 

Imports Microsoft.VisualBasic 

Namespace SO13035027 
<ComClass(WinMergeScript.ClassId, WinMergeScript.InterfaceId, WinMergeScript.EventsId)> _ 
Public Class WinMergeScript 

#Region "COM GUIDs" 
' These GUIDs provide the COM identity for this class 
' and its COM interfaces. If you change them, existing 
' clients will no longer be able to access the class. 
Public Const ClassId As String =  "9b9bbe1c-7b20-4826-b12e-9062fc4549a2" 
Public Const InterfaceId As String = "b0f2aa59-b9d0-454a-8148-9715c83dbb72" 
Public Const EventsId As String = "8f4f9c82-6ba3-4c22-8814-995ca1050de2" 
#End Region 

' A creatable COM class must have a Public Sub New() 
' with no parameters, otherwise, the class will not be 
' registered in the COM registry and cannot be created 
' via CreateObject. 
Public Sub New() 
    MyBase.New() 
End Sub 

Public Function HelloWorld() As String 
Return "Hello, world!" 
End Function 

End Class 
End Namespace 
+0

Cảm ơn - Tôi đã thêm " _" ở phía trước lớp WinMergeScript và trước mỗi chức năng công khai. Tôi đã đánh dấu "Make Assembly COM-Visible" trong hộp hội thoại AssemblyInfo, đạt được từ các thuộc tính của dự án, ứng dụng, nút Assembly Info. Tôi không thể tìm thấy "Đăng ký cho COM" bất cứ nơi nào (Visual Studio 2008). Vẫn không hoạt động, và trình xem DLL cho thấy không có đối tượng COM hoặc phương pháp trong dll biên dịch. –

+0

[Sau] Tôi đã tìm thấy "Đăng ký COM interop" trong các tùy chọn biên dịch dự án, và nó đã được chọn. –

+0

bạn có làm việc này không? Nếu có: Bạn có thể chia sẻ nó không? – fabsenet

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