2012-10-23 17 views
5

Chciałbym napisać wtyczkę WinMerge, aby przetłumaczyć bazy danych SQLite na tekst, więc mogę użyć WinMerge do porównywania baz danych.Jak napisać wtyczkę WinMerge w C# (lub VB.NET)

Napisałem kod w języku C#, aby wykonać konwersję, ale nie mogę sprawić, aby pojawiła się jako wtyczka WinMerge. Ale nie bardzo wiem, jak pisać obiekty ASP.

Doszedłem do wniosku, że nie mogłem podać prawidłowych atrybutów COM (po prostu wstawiłem ComVisible (true) na klasie). Jednak myślę, że VB.Net ma zrobić dla ciebie wszystko, więc przepisałem klasę w VB.Net, używając klasy Projekt/Dodaj Nowy/COM. Jednak nadal nie pojawia się w WinMerge jako załadowana wtyczka.

W desperacji próbowałem przeglądać bibliotekę DLL VB przy użyciu przeglądarki DLL Export Viewer, ale nie pokazywałem żadnych wyeksportowanych funkcji. Oczywiście robię coś nie tak.

Oto kod w całości:

<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 

Odpowiedz

1

Właśnie teraz przeglądowi rzeczywisty kod WinMerge 2.14.0 i myślę, że to działa tylko dla bibliotek DLL COM (prawdziwe i OCXs), głównie z powodu działa bez oczekiwania na rejestrację obiektów COM. Trzeba go rozszerzyć, aby przynajmniej odwołać się do .TLB lub dostosować, aby nie można było podać żadnej ścieżki, ale bardziej wyraźnego identyfikatora niż "WinMergeScript".


W pracy obiektu VB.NET COM jawnie wspomnieć <ComVisible(True)> _ a projekt „Zarejestruj COM” zaznaczone we właściwościach skompilować.

Właśnie utworzyłem funkcję HelloWorld za pomocą kodu, skompilowałem ją z vbc /t:library i zarejestrowałem pod numerem regasm /codebase. Ten został pomyślnie nazywane za pomocą tego prostego VBScript (używając wscript):

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

I cały kod (nie przekonfigurować swój system do wykorzystania później vbc tak to faktycznie skompilowany do .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

Dzięki - dodałem " _" przed klasą WinMergeScript i przed każdą publiczną funkcją. Już zaznaczyłem "Make Assembly COM-Visible" w oknie dialogowym AssemblyInfo, osiągnięte z właściwości projektu, aplikacji, informacji o zespole. Nie mogę znaleźć "Register for COM" w dowolnym miejscu (Visual Studio 2008). Nadal nie działa, a przeglądarka DLL nie pokazuje żadnych obiektów COM ani metod w skompilowanej bibliotece dll. –

+0

[Później] Znalazłem "Register for COM interop" w opcjach kompilacji projektu i zostało już zaznaczone. –

+0

czy udało ci się to osiągnąć? Jeśli tak: możesz to udostępnić? – fabsenet