VB.NET中处理COM事件的问题

VB.NET中处理COM事件的问题,.net,sql-server,vb.net,interop,.net,Sql Server,Vb.net,Interop,我正在从VB.NET调用SQLDMO 8.0 COM库(使用我用tlbimp生成的PIA),以便使用完成百分比通知备份数据库: Dim server As SQLDMO.SQLServer = Nothing Dim backup As SQLDMO.Backup = Nothing Dim restore As SQLDMO.Restore = Nothing Dim backupAbortable As Boolean Dim restoreAbortable As Boolean Try

我正在从VB.NET调用SQLDMO 8.0 COM库(使用我用tlbimp生成的PIA),以便使用完成百分比通知备份数据库:

Dim server As SQLDMO.SQLServer = Nothing
Dim backup As SQLDMO.Backup = Nothing
Dim restore As SQLDMO.Restore = Nothing
Dim backupAbortable As Boolean
Dim restoreAbortable As Boolean
Try
    server = New SQLDMO.SQLServer
    server.LoginSecure = True
    server.Connect(serverName)

    backup = New SQLDMO.Backup
    backup.Action = SQLDMO.SQLDMO_BACKUP_TYPE.SQLDMOBackup_Database
    backup.BackupSetDescription = "test"
    backup.BackupSetName = "test"
    backup.Database = databaseName
    backup.Files = TransactSqlName.Delimit(fileName)
    backup.TruncateLog = SQLDMO.SQLDMO_BACKUP_LOG_TYPE.SQLDMOBackup_Log_Truncate
    backup.PercentCompleteNotification = 1
    AddHandler backup.PercentComplete, AddressOf OnOperationPercentComplete
    AddHandler backup.NextMedia, AddressOf OnOperationNextMedia
    AddHandler backup.Complete, AddressOf OnOperationComplete
    backupAbortable = True
    backup.SQLBackup(server)
    backupAbortable = False

    restore = New SQLDMO.Restore
    restore.Files = backup.Files
    AddHandler restore.PercentComplete, AddressOf OnOperationPercentComplete
    AddHandler restore.NextMedia, AddressOf OnOperationNextMedia
    AddHandler restore.Complete, AddressOf OnOperationComplete
    restoreAbortable = True
    restore.SQLVerify(server)
    restoreAbortable = False

    server.DisConnect()
Catch ex As AbortException
    If backupAbortable Then
        backup.Abort()
    End If
    If restoreAbortable Then
        restore.Abort()
    End If
Finally
    If restore IsNot Nothing Then
        RemoveHandler restore.PercentComplete, AddressOf OnOperationPercentComplete
        RemoveHandler restore.NextMedia, AddressOf OnOperationNextMedia
        RemoveHandler restore.Complete, AddressOf OnOperationComplete
        Marshal.FinalReleaseComObject(restore)
        restore = Nothing
    End If
    If backup IsNot Nothing Then
        RemoveHandler backup.PercentComplete, AddressOf OnOperationPercentComplete
        RemoveHandler backup.NextMedia, AddressOf OnOperationNextMedia
        RemoveHandler backup.Complete, AddressOf OnOperationComplete
        Marshal.FinalReleaseComObject(backup)
        backup = Nothing
    End If
    If server IsNot Nothing Then
        Marshal.FinalReleaseComObject(server)
        server = Nothing
    End If
End Try
除了事件处理程序之外,它工作得很好-只有第一个连接起来的处理程序才真正执行。我不能肯定NextMedia事件,因为它只针对磁带备份触发,但对于其他两个事件,根据AddHandler语句的顺序,我要么获取Complete事件,要么获取PercentComplete事件触发,决不能同时获取这两个事件

可能性:

  • 我做错了(欢迎建议!)
  • SQLDMO8.0中有一个bug,它实际上只触发了其中一个事件
  • RCW或VB.NET编译器中存在影响COM互操作事件的错误

  • 有什么想法吗?

    这在VB.NET 2005中有效,不确定1.1

    我知道你已经在COM互操作上做了大量工作,但是你能在连接之外使用信息事件吗

    注意STATS=10。。这意味着每10%发送一次进度通知

    这只是我一直在做的一个项目的一个片段,我希望你能从中得到你所需要的

    public sub Backup()
      Dim Conn As SqlClient.SqlConnection
      dim theCommand as SqlClient.SQLCommand
      Conn = New SqlClient.SqlConnection("Data Source=.\MyInstance;Initial Catalog=Master;Integrated Security=SSPI;")
      theCommand = Conn.CreateCommand
    
      theCommand.CommandText = "BACKUP DATABASE [MyDatabase] TO DISK = '" & mDatabasePath & "\" & Filenames.SQLBackup & "' WITH NOFORMAT, INIT, NAME = 'MyDatabase-Full Database Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10"
    
      AddHandler Conn.InfoMessage, AddressOf onSqlInfoMessage
      'make sure the events are fired as they are available, instead of at the end.
      Conn.FireInfoMessageEventOnUserErrors = True
    
      Conn.Open()
    
      theCommand.ExecuteNonQuery()
          RemoveHandler Conn.InfoMessage, AddressOf onSqlInfoMessage
    
      Conn.Close()
    
    end sub 
    
       Private Sub onSqlInfoMessage(ByVal sender As Object, ByVal args As SqlClient.SqlInfoMessageEventArgs)
            If args.Message.EndsWith("percent processed.") Then
                Dim theMatch As System.Text.RegularExpressions.Match
                theMatch = mRegEx.Match(args.Message)
                debug.print("Progress = " & theMatch.Value.Trim)
            End If
        End Sub
    

    这在VB.NET2005中有效,但不确定是否为1.1

    我知道你已经在COM互操作上做了大量工作,但是你能在连接之外使用信息事件吗

    注意STATS=10。。这意味着每10%发送一次进度通知

    这只是我一直在做的一个项目的一个片段,我希望你能从中得到你所需要的

    public sub Backup()
      Dim Conn As SqlClient.SqlConnection
      dim theCommand as SqlClient.SQLCommand
      Conn = New SqlClient.SqlConnection("Data Source=.\MyInstance;Initial Catalog=Master;Integrated Security=SSPI;")
      theCommand = Conn.CreateCommand
    
      theCommand.CommandText = "BACKUP DATABASE [MyDatabase] TO DISK = '" & mDatabasePath & "\" & Filenames.SQLBackup & "' WITH NOFORMAT, INIT, NAME = 'MyDatabase-Full Database Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10"
    
      AddHandler Conn.InfoMessage, AddressOf onSqlInfoMessage
      'make sure the events are fired as they are available, instead of at the end.
      Conn.FireInfoMessageEventOnUserErrors = True
    
      Conn.Open()
    
      theCommand.ExecuteNonQuery()
          RemoveHandler Conn.InfoMessage, AddressOf onSqlInfoMessage
    
      Conn.Close()
    
    end sub 
    
       Private Sub onSqlInfoMessage(ByVal sender As Object, ByVal args As SqlClient.SqlInfoMessageEventArgs)
            If args.Message.EndsWith("percent processed.") Then
                Dim theMatch As System.Text.RegularExpressions.Match
                theMatch = mRegEx.Match(args.Message)
                debug.print("Progress = " & theMatch.Value.Trim)
            End If
        End Sub
    

    sqldmo.dll的文件版本为2000.85.2312.0,typelib版本为8.0。运行代码所针对的SQL Server版本可以是2000或2005。我最好去仔细检查两个版本是否有相同的行为。对不起,typelib版本是8.5。SQL 2005似乎升级了我原来的SQL 2000安装。:-)是的,两个版本上都发生了相同的行为。sqldmo.dll的文件版本是2000.85.2312.0,typelib版本是8.0。运行代码所针对的SQL Server版本可以是2000或2005。我最好去仔细检查两个版本是否有相同的行为。对不起,typelib版本是8.5。SQL 2005似乎升级了我原来的SQL 2000安装。:-)是的,两个版本都有相同的行为。谢谢Paul,我不知道FireInfoMessageEventOnUserErrors属性。这是一个比使用SQLDMO更好的解决方案,我已经将所有备份/恢复代码转换回ADO.NET。不错。:-)谢谢Paul,我不知道FireInfoMessageEventOnUserErrors属性。这是一个比使用SQLDMO更好的解决方案,我已经将所有备份/恢复代码转换回ADO.NET。不错。:-)