2015-04-03 22 views
1

我一直負責在C#.NET中編寫自定義應用程序,以便將消息從一個隊列移動到另一個隊列,同時保留所有上下文和身份信息與原始消息相同。Websphere MQ - 在.NET中從一個隊列移動到另一個隊列時保留消息上下文和身份

我試圖破譯的在線文檔,並試圖在打開隊列MQC.MQOO_PASS_ALL_CONTEXTMQOO_SAVE_ALL_CONTEXT每一個組合,並在放電話MQC.MQPMO_PASS_ALL_CONTEXT,都無濟於事。我曾嘗試MQPutMessageOptions.ContextReference設置爲源和 目標隊列兩者,但是我繼續得到例外,無論是MQRC_CONTEXT_HANDLE_ERRORMQRC_OPTIONS_ERROR,我找不到在線文檔足夠的信息來確定問題。

我使用amqmdnet.dll的運行時版本v2.0.50727 V7.5.0.1。如果有人知道我需要使用正確的開放和/或放置消息選項設置,那麼我將非常感激。謝謝。

*****第二次更新*****

這是一個非常簡單的GUI程序來測試類,我也得到了相同的結果:

public partial class frmMain : Form 
{ 
    // Simple test - all data hard-coded 

    string sourceQStr = "PETE.TQ1"; 
    string targetQStr = "PETE.TQ2"; 
    string targetMsgIdStr = "414D5120514D4942584330352020202028ED0155202EB302"; 
    string connName = "localhost"; 
    string connPort = "1414"; 


    MQQueueManager sourceManager; 
    MQQueueManager targetManager; 
    MQQueue sourceQueue; 
    MQQueue targetQueue; 

    MQMessage msg = new MQMessage(); 
    MQGetMessageOptions gmo = new MQGetMessageOptions(); 
    MQPutMessageOptions pmo = new MQPutMessageOptions(); 


    public frmMain() 
    { 
     InitializeComponent(); 
    } 

    private void Form1_Load(object sender, EventArgs e) 
    { 

    } 

    private void txtPassword_Validating(object sender, CancelEventArgs e) 
    { 

     if (txtPassword.Text.Trim() != string.Empty) 
     { 
      if (LoginUser()) 
       btnTest.Focus(); 
      else 
       txtUserId.Focus(); 
     } 
    } 

    public void LogoutUser() 
    { 
     txtUserId.Text = ""; 
     txtPassword.Text = ""; 
     btnTest.Enabled = false; 

    } 

    public bool LoginUser() 
    { 
     bool OK = ValidateUserAndPassword(); 
     if (OK) 
     { 
      btnTest.Enabled = true; 
     } 
     else LogoutUser(); 
     return OK; 
    } 

    private bool ValidateUserAndPassword() 
    { 
     if ((txtUserId.Text.Trim() == string.Empty) || (txtPassword.Text.Trim() == string.Empty)) 
      return false; 
     try 
     { 
      bool _passwordValid = false; 
      ContextOptions options = ContextOptions.SimpleBind | ContextOptions.SecureSocketLayer; 
      using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, "UP")) 
      { 
       _passwordValid = pc.ValidateCredentials 
        (txtUserId.Text.Trim(), txtPassword.Text.Trim(), options); 
      } 
      if (!_passwordValid) 
       MessageBox.Show("Invalid username/password", "Invalid", 
        MessageBoxButtons.OK, MessageBoxIcon.Error); 
      return _passwordValid; 
     } 
     catch (PrincipalServerDownException pex) 
     { 
      string msg = pex.Message.Insert(pex.Message.IndexOf("server"), "Authentication "); 
      MessageBox.Show(msg, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 
      return false; 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 
      return false; 
     } 
    } 

    private void btnTest_Click(object sender, EventArgs e) 
    { 
     try 
     { 
      SetupObjects(); 
      sourceQueue.Get(msg, gmo); 
      targetQueue.Put(msg, pmo); 
      sourceManager.Commit(); 
      targetManager.Commit(); 
      MessageBox.Show("Test appears successful - verify with MQ Explorer","OK", 
       MessageBoxButtons.OK, MessageBoxIcon.Exclamation); 
     } 
     catch (Exception ex) // MQRC_CONTEXT_HANDLE_ERROR is always thrown 
     { 
      MessageBox.Show("Error: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 
      sourceManager.Backout(); 
      targetManager.Backout(); 
     } 
    } 

    private void btnClose_Click(object sender, EventArgs e) 
    { 
     this.Close(); 
    } 

    /************************************** Utiility methods *****************************************/ 

    private void SetupObjects() 
    { 
     // set up objects 
     string connectName = connName + "(" + connPort + ")"; 
     int ConnOptions = MQC.MQCNO_HANDLE_SHARE_BLOCK; 

     sourceManager = new MQQueueManager("", ConnOptions, "CHANNEL1", connectName); 
     targetManager = new MQQueueManager("", ConnOptions, "CHANNEL1", connectName); 

     MQEnvironment.UserId = txtUserId.Text.Trim(); 
     MQEnvironment.Password = txtPassword.Text.Trim(); 

     int options = 
      MQC.MQOO_INPUT_SHARED + MQC.MQOO_FAIL_IF_QUIESCING + 
      MQC.MQOO_SAVE_ALL_CONTEXT + MQC.MQOO_INQUIRE; 
     sourceQueue = sourceManager.AccessQueue 
      (sourceQStr, options, sourceManager.Name, null, txtUserId.Text.Trim()); 
     options = 
      MQC.MQOO_OUTPUT + MQC.MQOO_FAIL_IF_QUIESCING + 
      MQC.MQOO_PASS_ALL_CONTEXT + MQC.MQOO_INQUIRE; 
     targetQueue = targetManager.AccessQueue 
      (targetQStr, options, targetManager.Name, null, txtUserId.Text.Trim()); 

     int i = 0; 
     try 
     { 
      i = sourceQueue.CurrentDepth; 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show("Exception: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 
     } 

     gmo.Options = MQC.MQGMO_COMPLETE_MSG + MQC.MQGMO_FAIL_IF_QUIESCING + 
      MQC.MQGMO_NO_WAIT + MQC.MQGMO_SYNCPOINT; 

     pmo.Options = MQC.MQPMO_PASS_ALL_CONTEXT + 
      MQC.MQPMO_SYNCPOINT + MQC.MQPMO_SYNC_RESPONSE; 
     pmo.ContextReference = sourceQueue; 

     msg.MessageId = StringToByteArray(targetMsgIdStr); 
    } 

    public byte[] StringToByteArray(String hex) 
    { 
     hex = hex.Trim(); 
     int NumberChars = hex.Length; 
     if ((NumberChars % 2) != 0) 
     { 
      hex = "0" + hex; 
      NumberChars++; 
     } 
     byte[] bytes = new byte[NumberChars/2]; 
     for (int i = 0; i < NumberChars; i += 2) 
      bytes[i/2] = StringToByte(hex.Substring(i, 2)); 
     return bytes; 
    } 

    public byte StringToByte(string hexDigits) 
    { 
     if (hexDigits.Length != 2) 
      return 0; 

     int high = hexValue(hexDigits[0]); 
     int low = hexValue(hexDigits[1]); 

     return (byte)(((high << 4) & 240) | (low & 15)); 
    } 

    public int hexValue(char c) 
    { 
     int retval = 0; 
     if (c > '9') 
      retval = ((int)c) - 55; 
     else 
      retval = ((int)c) - 48; 
     return retval; 
    } 
} 

的GUI簡單的提示輸入用戶名和密碼(通過LDAP調用進行驗證),然後啓用運行btnTest_Click方法的「測試」按鈕。即使我認爲我已經使用了指定的所有打開和獲取消息選項,我仍然得到相同的異常(MQRC_CONTEXT_HANDLE_ERROR)。

+0

我有三重檢查所有的開放,獲取和看跌期權 - 有一些I'n沒有得到關於「上下文」因爲現在我收到的例外是「MQRC_CONTEXT_HANDLE_ERROR」(原因代碼2097。 ) – 2015-04-07 15:53:38

回答

2

用於在保留所有上下文信息的同時移動消息的正確選項如下。

打開隊列以獲取消息時,請使用MQOO_SAVE_ALL_CONTEXT。上下文將在獲取時間保存在表示此已打開隊列的對象句柄中。

打開隊列放置消息時,使用MQOO_PASS_ALL_CONTEXT。然後在輸入消息時,使用MQPMO_PASS_ALL_CONTEXT並提供包含上下文的對象句柄。

接收返回碼MQRC_CONTEXT_HANDLE_ERROR意味着您在第一次打開時沒有使用MQOO_SAVE_ALL_CONTEXT,但隨後嘗試使用put上的對象句柄。這也可能意味着它不是第一個隊列的正確參考。在MQ API中,它是一個對象句柄(MQHOBJ),而在.Net中則是MQQueue(請參閱MQPutMessageOptions .NET class)。

收到退貨代碼MQRC_OPTIONS_ERROR意味着您混合並過多地匹配選項。

+0

即使使用MQC打開源隊列WAS,我也會遇到MQRC_CONTEXT_HANDLE_ERROR異常。MQOO_INPUT_SHARED + MQC.MQOO_FAIL_IF_QUIESCING + MQC.MQOO_SAVE_ALL_CONTEXT。請給我一個功能組合。 – 2015-04-07 16:54:02

+0

此外,MQPutMessageOptions中的「Context」屬性如果沒有記錄該值來自何處,則不值得。當我填充MQPutMessageOptions.ContextReference時,一個值會自動出現在「Context」屬性中。這是它應該有的價值嗎? – 2015-04-07 16:58:05

2

添加到Morag的答案,這裏是用上下文移動消息的片段。我也使用SYNC_POINT來確保消息成功放入目標隊列後,消息從源隊列中移除。

/// <summary> 
    /// Moves messages from one queue to another with context 
    /// </summary> 
    public void moveMessagesWithContext() 
    { 
     MQQueueManager qmSource = null; 
     MQQueueManager qmDestination = null; 
     MQQueue qSource = null; 
     MQQueue qDestination = null; 
     Hashtable htSource = null; 
     Hashtable htDestination = null; 

     try 
     { 
      htSource = new Hashtable(); 
      htDestination = new Hashtable(); 

      htSource.Add(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_MANAGED); 
      htSource.Add(MQC.HOST_NAME_PROPERTY, "localhost"); 
      htSource.Add(MQC.PORT_PROPERTY, 2020); 
      htSource.Add(MQC.CHANNEL_PROPERTY, "A_QM_SVRCONN"); 
      qmSource = new MQQueueManager("A_QM", htSource); 
      qSource = qmSource.AccessQueue("Q_SOURCE", MQC.MQOO_INPUT_AS_Q_DEF | MQC.MQOO_FAIL_IF_QUIESCING | MQC.MQOO_SAVE_ALL_CONTEXT); 

      htDestination.Add(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_MANAGED); 
      htDestination.Add(MQC.HOST_NAME_PROPERTY, "localhost"); 
      htDestination.Add(MQC.PORT_PROPERTY, 3030); 
      htDestination.Add(MQC.CHANNEL_PROPERTY, "B_QM_SVRCONN"); 
      qmDestination = new MQQueueManager("B_QM", htDestination); 
      qDestination = qmDestination.AccessQueue("Q_DESTINATION", MQC.MQOO_OUTPUT | MQC.MQOO_FAIL_IF_QUIESCING | MQC.MQOO_PASS_ALL_CONTEXT); 

      MQMessage msgSource = new MQMessage(); 
      MQGetMessageOptions gmo = new MQGetMessageOptions(); 
      gmo.Options |= MQC.MQGMO_SYNCPOINT; 
      qSource.Get(msgSource,gmo); 
      if (msgSource != null) 
      { 
       MQMessage msgDestination = new MQMessage(); 
       MQPutMessageOptions pmo = new MQPutMessageOptions(); 
       pmo.ContextReference = qSource; 
       qDestination.Put(msgSource, pmo); 
       qmSource.Commit(); 
      } 
     } 
     catch (MQException mqEx) 
     { 
      qmSource.Backout(); 
      Console.WriteLine(mqEx); 
     } 
     catch (Exception otherEx) 
     { 
      Console.WriteLine(otherEx); 
     } 
    } 
相關問題