c# - 如何用 C#(或 VB.NET)编写 WinMerge 插件

标签 c# vb.net plugins winmerge

我想写一个 WinMerge 插件来将 SQLite 数据库翻译成文本,这样我就可以使用 WinMerge 来比较数据库。

我已经用 C# 编写了代码来进行转换,但我似乎无法使其显示为 WinMerge 插件。但我不太熟悉编写 COM 可见的 .NET 对象。

我认为我一定没有放入正确的 COM 属性(我只是将 ComVisible(true) 放入类中)。但是,我认为 VB.Net 应该为您完成所有这些工作,所以我使用 Project/Add New/COM 类在 VB.Net 中重写了类。但是,它仍然没有作为加载的插件出现在 WinMerge 中。

无奈之下,我尝试使用 DLL 导出查看器查看 VB DLL,但它没有显示任何导出的函数。我显然做错了什么。

完整代码如下:

<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

最佳答案

我刚刚查看了 WinMerge 2.14.0 的实际代码,我认为它只适用于真正的 COM DLL(和 OCX),主要是因为它在不期望注册 COM 对象的情况下工作。它需要扩展到至少引用 .TLBs 或调整为允许不指定路径,但比“WinMergeScript”更明确的 ID。


在工作的 VB.NET COM 对象中,我明确提到 <ComVisible(True)> _并且该项目在编译属性中选中了“为 COM 注册”。

我刚刚创建了一个 HelloWorld函数使用你的代码,用 vbc /t:library 编译它并用 regasm /codebase 注册.这是使用这个简单的 vbscript 成功调用的(使用 wscript ):

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

以及整个代码(我没有重新配置我的系统以使用更高版本的 vbc 所以它实际上被编译为 .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

关于c# - 如何用 C#(或 VB.NET)编写 WinMerge 插件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13035027/

相关文章:

c# 新手 : if statement && with int

mysql - 如何加密 App.config 中的连接字符串 VB.net

vb.net - InvalidArgument= '0' 的值对于 'SelectedIndex' 无效。参数名称: SelectedIndex using ShowDialog

css - Photospace Gallerific wordpress 响应式垂直画廊缩略图媒体查询javascript css?

php - 如何从 WordPress 中的插件 php 编辑 mySQL wp_posts 表?

Wordpress 插件开发 - 获取所有事件小部件

c# - 如何直接从文件反序列化 json 数据集?

c# - otside 类放置在 Form 中的 Visual Studio 调用方法

.net - 创建一个类型为字符串参数的对象

c# - 如何测试mySql数据库是否正常工作?