处理排队组件中的错误

偶尔会出现消息无法成功传递到预期目标的情况,通常是由于系统或配置问题。 例如,消息可能被定向到不存在的队列,或者目标队列可能不处于可接收的状态。 消息移动器是一种工具,可将所有失败的消息队列消息从一个队列移到另一个队列,以便重试。 消息移动器实用工具是一个自动化对象,可以用 VBScript 调用。

组件服务管理工具

不应用。

Visual Basic

以下示例代码演示如何创建 MessageMover 对象、设置所需的属性以及启动传输。 若要从 Visual Basic 使用,请添加对 COM+ 服务类型库的引用。

注意

若要使用 MessageMover 对象,必须在计算机上安装消息队列,并且 AppName 指定的应用程序必须启用排队。 有关安装消息队列的信息,请参阅开始菜单上的“帮助和支持”。

 

Function MyMessageMover( _
  strSource As String, _
  strDest As String _
) As Boolean  ' Return False if any errors occur.

    MyMessageMover = False  ' Initialize the function.
    On Error GoTo My_Error_Handler  ' Initialize error handling.

    Dim lngMovedMessages As Long
    Dim objMessageMover As COMSVCSLib.MessageMover
    Set objMessageMover = CreateObject("QC.MessageMover")
    objMessageMover.SourcePath = strSource
    objMessageMover.DestPath = strDest
    lngMovedMessages = objMessageMover.MoveMessages

    MsgBox lngMovedMessages & " messages moved from " & _
      strSource & " to " & strDest

    MyMessageMover = True  ' Successful end to procedure
    Set objMessageMover = Nothing
    Exit Function

My_Error_Handler:  ' Replace with specific error handling.
    MsgBox "Error # " & Err.Number & " (Hex: " & Hex(Err.Number) _
      & ")" & vbNewLine & Err.Description
    Set objMessageMover = Nothing
    lngMovedMessages = -1
End Function

以下 Visual Basic 代码演示如何调用 MyMessageMover 函数。

Sub Main()
  ' Replace AppName with the name of a COM+ application.
  If Not MyMessageMover(".\private$\AppName_deadqueue", ".\AppName") Then
      MsgBox "MyMessageMover failed."
  End If
End Sub

消息的源路径是最终休息队列。 是死队列,是消息队列专用队列,称为 AppName_deadqueue。 如果在第五个重试队列上尝试事务时重复中止,则消息会移动到此处。 使用消息移动器工具,可以将消息移回第一个队列,即 AppName。 有关重试队列的详细信息,请参阅服务器端错误

如果队列属性允许,消息移动器会过渡性地移动消息,以便在移动期间发生故障时不会丢失或重复消息。 该工具保留了将消息从一个队列移动到另一个队列时可以保留的所有消息属性。

如果消息由 COM+ 排队组件调用生成,则消息移动器实用工具在队列之间移动消息时会保留原始调用方的安全标识符。 如果目标队列和源队列都是事务性的,那么整个操作将以过渡性方式完成。 如果源队列或目标队列都不是事务性队列,则操作不会在事务下运行。 非事务性移动的意外失败(如崩溃)和重新启动可能会复制失败时移动的消息。

C/C++

以下示例代码演示如何创建 MessageMover 对象、设置所需的属性以及启动传输。 解释错误代码中介绍了 ErrorDescription 方法。

注意

若要使用 MessageMover 对象,必须在计算机上安装消息队列,并且 AppName 指定的应用程序必须启用排队。 有关安装消息队列的信息,请参阅开始菜单上的“帮助和支持”。

 

#include <windows.h>
#include <stdio.h>
#import "C:\WINDOWS\system32\ComSvcs.dll"
#include "ComSvcs.h"
#include "StrSafe.h"  

BOOL MyMessageMover (OLECHAR* szSource, OLECHAR* szDest) {
    IUnknown * pUnknown = NULL;
    IMessageMover * pMover = NULL;
    HRESULT hr = S_OK;
    BSTR bstrSource = NULL;
    BSTR bstrDest = NULL;
    unsigned int uMaxLen = 255;  // Maximum length of szMyApp

try {
    // Test the input strings to make sure they're OK to use.
    hr = StringCchLengthW(szSource, uMaxLen, NULL);
    if (FAILED (hr)) throw(hr);
    hr = StringCchLengthW(szDest, uMaxLen, NULL);
    if (FAILED (hr)) throw(hr);
    
    // Convert the input strings to BSTRs.
    bstrSource = SysAllocString(szSource);
    bstrDest = SysAllocString(szDest);

    // Create a MessageMover object and get its IUnknown.
    hr = CoCreateInstance(CLSID_MessageMover, NULL, 
      CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pUnknown);
    if (FAILED (hr)) throw(hr);    

    // Get the IMessageMover interface.
    hr = pUnknown->QueryInterface(IID_IMessageMover, (void**)&pMover); 
    if (FAILED (hr)) throw(hr);

    // Put the source and destination files.
    hr = pMover->put_SourcePath(bstrSource);
    if (FAILED (hr)) throw(hr);
    hr = pMover->put_DestPath(bstrDest);
    if (FAILED (hr)) throw(hr);

    // Move the messages.
    LONG lCount = -1;
    hr = pMover->MoveMessages(&lCount);
    if (FAILED (hr)) throw(hr);
    printf("%ld messages moved from %S to %S.\n", 
      lCount, bstrSource, bstrDest);

    // Clean up.
    SysFreeString(bstrDest);
    SysFreeString(bstrSource);
    pUnknown->Release();
    pUnknown = NULL;
    pMover->Release();
    pMover = NULL;
    return (TRUE);
}  // try

catch(HRESULT hr) {  // Replace with specific error handling.
    printf("Error # %#x: ", hr);
    ErrorDescription(hr);
    SysFreeString(bstrDest);
    SysFreeString(bstrSource);
    if (NULL != pUnknown) pUnknown->Release();
    pUnknown = NULL;
    if (NULL != pMover) pMover->Release();
    pMover = NULL;
    return (FALSE);
}catch(...) {
    printf("An unexpected exception occurred.\n");
    throw;
}        
}  // MyMessageMover

以下 C++ 代码演示如何调用 MyMessageMover 函数。

#include <windows.h>
#include <stdio.h>

#define _WIN32_DCOM  // To use CoInitializeEx()

void main() 
{
    HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
    if (FAILED (hr)) {
        printf("CoInitializeEx failed: Error # %#x\n", hr);
        exit(0);  // Replace with specific error handling.
    }
    if (! MyMessageMover(L".\\private$\\AppName_deadqueue", 
      L".\\AppName"))
        printf("MyMessageMover failed.\n");
    CoUninitialize();
}

消息的源路径是最终休息队列。 是死队列,是消息队列专用队列,称为 AppName_deadqueue。 如果在第五个重试队列上尝试事务时重复中止,则消息会移动到此处。 使用消息移动器工具,可以将消息移回第一个队列,即 AppName。 有关重试队列的详细信息,请参阅服务器端错误

如果队列属性允许,消息移动器会过渡性地移动消息,以便在移动期间发生故障时不会丢失或重复消息。 该工具保留了将消息从一个队列移动到另一个队列时可以保留的所有消息属性。

如果消息由 COM+ 排队组件调用生成,则消息移动器实用工具在队列之间移动消息时会保留原始调用方的安全标识符。 如果目标队列和源队列都是事务性的,那么整个操作将以过渡性方式完成。 如果源队列或目标队列都不是事务性队列,则操作不会在事务下运行。 非事务性移动的意外失败(如崩溃)和重新启动可能会复制失败时移动的消息。

注解

COM+ 通过将失败的消息移动到另一个“最终休息”队列来处理服务器端(播放器)中止,以将其排除在外。 侦听器和播放器无法连续循环处理中止的消息。 在许多情况下,可以通过在服务器上执行操作来修复中止的事务。

排队组件错误