/// <summary> /// Send SNRM Request to the meter. /// </summary> public void SNRMRequest() { GXReplyData reply = new GXReplyData(); byte[] data; data = Client.SNRMRequest(); if (data != null) { if (Trace > TraceLevel.Info) { Console.WriteLine("Send SNRM request." + GXCommon.ToHex(data, true)); GXDLMSTranslator t = new GXDLMSTranslator(TranslatorOutputType.SimpleXml); Console.WriteLine(t.MessageToXml(data)); } ReadDataBlock(data, reply); if (Trace == TraceLevel.Verbose) { Console.WriteLine("Parsing UA reply." + reply.ToString()); } //Has server accepted client. Client.ParseUAResponse(reply.Data); if (Trace > TraceLevel.Info) { Console.WriteLine("Parsing UA reply succeeded."); } } }
static public void WriteLog(string text, byte[] value) { string str = DateTime.Now.ToLongTimeString() + " " + text; //Show data as hex. if ((LogLevel & 1) != 0) { if (value != null) { str += "\r\n" + GXCommon.ToHex(value, true); } System.Diagnostics.Trace.WriteLine(str); } //Show data as xml. if ((LogLevel & 2) != 0) { receivedTraceData.Set(value); try { GXByteBuffer pdu = new GXByteBuffer(); InterfaceType type = GXDLMSTranslator.GetDlmsFraming(receivedTraceData); if (translator.FindNextFrame(receivedTraceData, pdu, type)) { System.Diagnostics.Trace.WriteLine(translator.MessageToXml(receivedTraceData)); receivedTraceData.Clear(); } } catch (Exception) { receivedTraceData.Clear(); } } }
static public void WriteLog(string text, byte[] value) { string str; if (GXDLMSDirector.Properties.Settings.Default.LogTime) { str = DateTime.Now.ToLongTimeString() + " " + text; } else { str = text; } //Show data as hex. if ((LogLevel & 1) != 0) { if (value != null) { str += Environment.NewLine + GXCommon.ToHex(value, true); } System.Diagnostics.Trace.WriteLine(str); } //Show data as xml. if (value != null && (LogLevel & 2) != 0) { receivedTraceData.Set(value); try { GXByteBuffer pdu = new GXByteBuffer(); InterfaceType type = GXDLMSTranslator.GetDlmsFraming(receivedTraceData); while (translator.FindNextFrame(receivedTraceData, pdu, type)) { System.Diagnostics.Trace.WriteLine(translator.MessageToXml(receivedTraceData)); receivedTraceData.Trim(); } } catch (Exception) { receivedTraceData.Clear(); } } }
/// <summary> /// Convert message to XML. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void TranslateBtn_Click(object sender, EventArgs e) { MessageXmlTB.Text = ""; StringBuilder sb = new StringBuilder(); GXByteBuffer bb = new GXByteBuffer(); //TODO: This can remove later. Security s = translator.Security; try { translator.Clear(); UpdateSecurity(); translator.Security = Security.Authentication; translator.PduOnly = PduOnlyCB.Checked; GXByteBuffer pdu = new GXByteBuffer(); bb.Set(GXDLMSTranslator.HexToBytes(RemoveComments(MessagePduTB.Text))); InterfaceType type = GXDLMSTranslator.GetDlmsFraming(bb); int cnt = 1; while (translator.FindNextFrame(bb, pdu, type)) { int start = bb.Position; string tmp = translator.MessageToXml(bb); sb.AppendLine(cnt + ": " + bb.ToHex(true, start, bb.Position - start)); ++cnt; sb.Append(tmp); pdu.Clear(); } MessageXmlTB.Text = sb.ToString(); translator.Security = s; } catch (Exception ex) { translator.Security = s; MessageXmlTB.AppendText(sb.ToString()); MessageXmlTB.AppendText(Environment.NewLine); MessageXmlTB.AppendText(bb.RemainingHexString(true)); MessageBox.Show(this, ex.Message); } }
/// <summary> /// Send AARQ Request to the meter. /// </summary> public void AarqRequest() { GXReplyData reply = new GXReplyData(); //Generate AARQ request. //Split requests to multiple packets if needed. //If password is used all data might not fit to one packet. foreach (byte[] it in Client.AARQRequest()) { if (Trace > TraceLevel.Info) { Console.WriteLine("Send AARQ request" + GXCommon.ToHex(it, true)); GXDLMSTranslator t = new GXDLMSTranslator(TranslatorOutputType.SimpleXml); Console.WriteLine(t.MessageToXml(it)); } reply.Clear(); ReadDataBlock(it, reply); } if (Trace > TraceLevel.Info) { Console.WriteLine("Parsing AARE reply\r\n" + reply.ToString()); } //Parse reply. Client.ParseAAREResponse(reply.Data); reply.Clear(); //Get challenge Is HLS authentication is used. if (Client.IsAuthenticationRequired) { foreach (byte[] it in Client.GetApplicationAssociationRequest()) { reply.Clear(); ReadDataBlock(it, reply); } Client.ParseApplicationAssociationResponse(reply.Data); } if (Trace > TraceLevel.Info) { Console.WriteLine("Parsing AARE reply succeeded."); } }
/// <summary> /// Import server settings and COSEM objects from GXDLMSDirector trace. /// </summary> /// <param name="server">Server where settings are updated.</param> /// <param name="data">GXDLMSDirector trace in byte array.</param> public static void Import(GXDLMSServer server, byte[] data) { GXDLMSTranslator translator = new GXDLMSTranslator(TranslatorOutputType.StandardXml); translator.CompletePdu = true; translator.PduOnly = true; XmlDocument doc = new XmlDocument(); List<ValueEventArgs> targets = new List<ValueEventArgs>(); GXDLMSSettings settings = new GXDLMSSettings(true); GXByteBuffer pdu = new GXByteBuffer(); GXByteBuffer bb = new GXByteBuffer(data); server.InterfaceType = GXDLMSTranslator.GetDlmsFraming(bb); bool lastBlock = true; GXByteBuffer val = new DLMS.GXByteBuffer(); while (translator.FindNextFrame(bb, pdu, server.InterfaceType)) { String xml = translator.MessageToXml(bb); if (xml != "") { doc.LoadXml(xml); foreach (XmlNode node in doc.ChildNodes[doc.ChildNodes.Count - 1].ChildNodes) { if (node.Name == "x:get-request") { server.UseLogicalNameReferencing = true; GetLN(settings.Objects, targets, node.ChildNodes); } else if (node.Name == "x:readRequest") { List<short> items = GetSN(node.ChildNodes); server.UseLogicalNameReferencing = false; foreach (short it in items) { GXSNInfo i = GXDLMSSNCommandHandler.FindSNObject(settings.Objects, Convert.ToUInt16((it) & 0xFFFF)); targets.Add(new ValueEventArgs(i.Item, i.Index, 0, null)); } } else if (node.Name == "x:readResponse" || node.Name == "x:get-response") { if (targets != null) { List<string> items; if (server.UseLogicalNameReferencing) { items = GetLNValues(node.ChildNodes); } else { items = GetSNValues(node.ChildNodes); } int pos = 0; foreach (string it in items) { if ("read-write-denied".Equals(it) || "scope-of-access-violated".Equals(it) || "object-unavailable".Equals(it)) { ValueEventArgs ve = targets[pos]; ve.Target.SetAccess(ve.Index, AccessMode.NoAccess); continue; } try { if (server.UseLogicalNameReferencing) { lastBlock = IsLastBlock(node.ChildNodes); } val.Set(translator.XmlToData(it)); if (lastBlock) { if (settings.Objects.Count == 0) { GXDLMSClient c = new GXDLMSClient(); c.UseLogicalNameReferencing = server.UseLogicalNameReferencing; settings.Objects = c.ParseObjects(val, true); //Update OBIS code description. GXDLMSConverter converter = new GXDLMSConverter(); converter.UpdateOBISCodeInformation(settings.Objects); } else { ValueEventArgs ve = targets[pos]; GXDataInfo info = new GXDataInfo(); ve.Value = GXCommon.GetData(server.Settings, val, info); if (ve.Value is byte[]) { DataType tp = ve.Target.GetUIDataType(ve.Index); if (tp != DataType.None) { ve.Value = GXDLMSClient.ChangeType((byte[])ve.Value, tp); } } ((IGXDLMSBase)ve.Target).SetValue(settings, ve); } val.Clear(); } } catch (Exception) { ValueEventArgs ve = targets[pos]; ve.Target.SetAccess(ve.Index, AccessMode.NoAccess); } ++pos; } if (lastBlock) { targets.Clear(); } } } } } } server.Items.Clear(); server.Items.AddRange(settings.Objects); }
/// <summary> /// Import server settings and COSEM objects from GXDLMSDirector trace. /// </summary> /// <param name="server">Server where settings are updated.</param> /// <param name="data">GXDLMSDirector trace in byte array.</param> public static void Import(GXDLMSServer server, byte[] data, Standard standard) { GXDLMSTranslator translator = new GXDLMSTranslator(TranslatorOutputType.StandardXml); translator.CompletePdu = true; translator.PduOnly = true; translator.OmitXmlNameSpace = translator.OmitXmlDeclaration = true; XmlDocument doc = new XmlDocument(); List <ValueEventArgs> targets = new List <ValueEventArgs>(); GXDLMSSettings settings = new GXDLMSSettings(true, InterfaceType.HDLC); GXByteBuffer pdu = new GXByteBuffer(); GXByteBuffer bb = new GXByteBuffer(data); server.InterfaceType = GXDLMSTranslator.GetDlmsFraming(bb); bool lastBlock = true; GXByteBuffer val = new DLMS.GXByteBuffer(); GXDLMSConverter converter = new GXDLMSConverter(standard); while (translator.FindNextFrame(bb, pdu, server.InterfaceType)) { String xml = translator.MessageToXml(bb); if (xml != "") { doc.LoadXml(xml.Replace("&", "&")); foreach (XmlNode node in doc.ChildNodes[doc.ChildNodes.Count - 1].ChildNodes) { string name = doc.ChildNodes[doc.ChildNodes.Count - 1].Name; if (name == "Ua" || name == "aarq" || name == "aare") { break; } else if (name == "get-request") { server.UseLogicalNameReferencing = true; GetLN(settings.Objects, targets, node.ChildNodes); } else if (name == "readRequest") { List <short> items = GetSN(node.ChildNodes); server.UseLogicalNameReferencing = false; foreach (short it in items) { GXSNInfo i = GXDLMSSNCommandHandler.FindSNObject(settings.Objects, Convert.ToUInt16((it) & 0xFFFF)); targets.Add(new ValueEventArgs(i.Item, i.Index, 0, null)); } } else if (name == "readResponse" || name == "get-response") { if (targets != null) { List <string> items; if (server.UseLogicalNameReferencing) { items = GetLNValues(doc.ChildNodes[doc.ChildNodes.Count - 1].ChildNodes); } else { items = GetSNValues(doc.ChildNodes[doc.ChildNodes.Count - 1].ChildNodes); } int pos = 0; foreach (string it in items) { if ("other-reason".Equals(it) || "read-write-denied".Equals(it) || "scope-of-access-violated".Equals(it) || "object-unavailable".Equals(it) || "object-class-inconsistent".Equals(it)) { ValueEventArgs ve = targets[pos]; ve.Target.SetAccess(ve.Index, AccessMode.NoAccess); continue; } try { if (server.UseLogicalNameReferencing) { lastBlock = IsLastBlock(doc.ChildNodes[doc.ChildNodes.Count - 1].ChildNodes); } val.Set(translator.XmlToData(it)); if (lastBlock) { if (settings.Objects.Count == 0) { GXDLMSClient c = new GXDLMSClient(); c.UseLogicalNameReferencing = server.UseLogicalNameReferencing; settings.Objects = c.ParseObjects(val, true); //Update OBIS code description. converter.UpdateOBISCodeInformation(settings.Objects); } else if (targets.Count != 0) { ValueEventArgs ve = targets[pos]; GXDataInfo info = new GXDataInfo(); ve.Value = GXCommon.GetData(server.Settings, val, info); if (ve.Value is byte[] && ve.Target != null) { DataType tp = ve.Target.GetUIDataType(ve.Index); if (tp != DataType.None) { ve.Value = GXDLMSClient.ChangeType((byte[])ve.Value, tp, false); ve.Target.SetDataType(ve.Index, DataType.OctetString); } } if (ve.Target is IGXDLMSBase) { ((IGXDLMSBase)ve.Target).SetValue(settings, ve); } } val.Clear(); } } catch (Exception) { ValueEventArgs ve = targets[pos]; ve.Target.SetAccess(ve.Index, AccessMode.NoAccess); } ++pos; } if (lastBlock) { targets.Clear(); break; } } } } } } server.Items.Clear(); server.Items.AddRange(settings.Objects); }
/// <summary> /// Convert message to XML. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void TranslateBtn_Click(object sender, EventArgs e) { MessageXmlTB.Text = ""; StringBuilder sb = new StringBuilder(); GXByteBuffer bb = new GXByteBuffer(); //TODO: This can remove later. byte s = translator.Security; try { translator.Clear(); UpdateSecurity(); translator.Security = (byte)Security.Authentication; translator.PduOnly = PduOnlyCB.Checked; GXByteBuffer pdu = new GXByteBuffer(); bb.Set(GXDLMSTranslator.HexToBytes(RemoveComments(MessagePduTB.Text))); InterfaceType type = GXDLMSTranslator.GetDlmsFraming(bb); int cnt = 1; string last = ""; while (translator.FindNextFrame(bb, pdu, type)) { int start = bb.Position; GXDLMSTranslatorMessage msg = new GXDLMSTranslatorMessage(); msg.Message = bb; translator.MessageToXml(msg); //Remove duplicate messages. if (RemoveDuplicatesCb.Checked) { if (last == msg.Xml) { continue; } } last = msg.Xml; if (msg.Command == Command.Aarq) { if (msg.SystemTitle != null) { string st = UpdateSystemTitle(this, "Current System title \"{0}\" is different in the parsed \"{1}\". Do you want to start using parsed one?", msg.SystemTitle, SystemTitleTB.Text, SystemTitleAsciiCb.Checked); if (st != null) { SystemTitleTB.Text = ""; SystemTitleAsciiCb.Checked = false; SystemTitleTB.Text = st; } } if (msg.DedicatedKey != null) { string key = UpdateSystemTitle(this, "Current dedicated key \"{0}\" is different in the parsed \"{1}\". Do you want to start using parsed one?", msg.DedicatedKey, DedicatedKeyTb.Text, DedicatedKeyAsciiCb.Checked); if (key != null) { DedicatedKeyTb.Text = ""; DedicatedKeyAsciiCb.Checked = false; DedicatedKeyTb.Text = key; } } } if (msg.Command == Command.Aare && msg.SystemTitle != null) { string st = UpdateSystemTitle(this, "Current Server System title \"{0}\" is different in the parsed \"{1}\". Do you want to start using parsed one?", msg.SystemTitle, ServerSystemTitleTB.Text, ServerSystemTitleAsciiCb.Checked); if (st != null) { ServerSystemTitleTB.Text = ""; SystemTitleAsciiCb.Checked = false; ServerSystemTitleTB.Text = st; } } if (!AllRb.Checked) { switch (msg.Command) { case Command.None: break; case Command.InitiateRequest: case Command.ReadRequest: case Command.WriteRequest: case Command.GetRequest: case Command.SetRequest: case Command.MethodRequest: case Command.Snrm: case Command.Aarq: case Command.ReleaseRequest: case Command.DisconnectRequest: case Command.AccessRequest: case Command.GloGetRequest: case Command.GloSetRequest: case Command.GloMethodRequest: case Command.GloInitiateRequest: case Command.GloReadRequest: case Command.GloWriteRequest: case Command.DedInitiateRequest: case Command.DedReadRequest: case Command.DedWriteRequest: case Command.DedGetRequest: case Command.DedSetRequest: case Command.DedMethodRequest: case Command.GatewayRequest: if (ReceivedRb.Checked) { continue; } break; case Command.InitiateResponse: case Command.ReadResponse: case Command.WriteResponse: case Command.GetResponse: case Command.SetResponse: case Command.MethodResponse: case Command.Ua: case Command.Aare: case Command.ReleaseResponse: case Command.AccessResponse: case Command.GloGetResponse: case Command.GloSetResponse: case Command.GloMethodResponse: case Command.GloInitiateResponse: case Command.GloReadResponse: case Command.GloWriteResponse: case Command.DedInitiateResponse: case Command.DedReadResponse: case Command.DedWriteResponse: case Command.DedGetResponse: case Command.DedSetResponse: case Command.DedMethodResponse: case Command.GatewayResponse: if (SentRb.Checked) { continue; } break; case Command.DisconnectMode: case Command.UnacceptableFrame: case Command.ConfirmedServiceError: case Command.ExceptionResponse: case Command.GeneralBlockTransfer: case Command.DataNotification: case Command.GloEventNotification: case Command.GloConfirmedServiceError: case Command.GeneralGloCiphering: case Command.GeneralDedCiphering: case Command.GeneralCiphering: case Command.InformationReport: case Command.EventNotification: case Command.DedConfirmedServiceError: case Command.DedUnconfirmedWriteRequest: case Command.DedInformationReport: case Command.DedEventNotification: break; } } sb.AppendLine(cnt + ": " + bb.ToHex(true, start, bb.Position - start)); ++cnt; sb.Append(msg.Xml); pdu.Clear(); } MessageXmlTB.Text = sb.ToString(); translator.Security = s; } catch (Exception ex) { translator.Security = s; MessageXmlTB.AppendText(sb.ToString()); MessageXmlTB.AppendText(Environment.NewLine); MessageXmlTB.AppendText(bb.RemainingHexString(true)); MessageBox.Show(this, ex.Message); } }
/// <summary> /// Convert message to XML. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void TranslateBtn_Click(object sender, EventArgs e) { if (MessagePduTB.ReadOnly) { StatusLbl.Text = "Cancelling translate."; CancelTranslate.Set(); return; } TranslateBtn.Checked = true; MessagePduTB.ReadOnly = true; Follow follow = (Follow)FollowmessagesCb.SelectedItem; ShowMessages show = (ShowMessages)ShowCb.SelectedItem; MessageXmlTB.Text = null; ProgressBar.Visible = true; object selectedInterface = InterfaceCb.SelectedItem; UpdateSecuritySettings(); StatusLbl.Text = "Finding frames"; GXByteBuffer bb = new GXByteBuffer(); bb.Set(GXDLMSTranslator.HexToBytes(RemoveComments(string.Join(Environment.NewLine, MessagePduTB.Lines)))); System.Threading.Tasks.Task.Run(async() => { if (translator.BlockCipherKey != null) { OnAppendMessage("BlockCipher key: " + GXDLMSTranslator.ToHex(translator.BlockCipherKey) + Environment.NewLine, Color.Green); } if (translator.AuthenticationKey != null) { OnAppendMessage("Authentication Key:" + GXDLMSTranslator.ToHex(translator.AuthenticationKey) + Environment.NewLine, Color.Green); } StringBuilder sb = new StringBuilder(); Security s = translator.Security; int count = 1; try { translator.Clear(); translator.PduOnly = PduOnlyMnu.Checked; GXByteBuffer pdu = new GXByteBuffer(); UpdateProgress(0, 0); UpdateMaxProgress(bb.Size, 0); GXDLMSTranslatorMessage frame = new GXDLMSTranslatorMessage(); frame.Message = bb; if (selectedInterface is string) { frame.InterfaceType = GXDLMSTranslator.GetDlmsFraming(bb); BeginInvoke((Action)(() => { InterfaceCb.SelectedItem = frame.InterfaceType; })); } else { frame.InterfaceType = (InterfaceType)selectedInterface; } string last = ""; int clientAddress = 0, serverAddress = 0; while (translator.FindNextFrame(frame, pdu, clientAddress, serverAddress)) { //Translate is cancelled. if (CancelTranslate.WaitOne(1)) { UpdateMaxProgress(0, 0); BeginInvoke((Action)(() => { MessagePduTB.ReadOnly = false; TranslateBtn.Checked = false; })); CancelTranslate.Reset(); return; } int start = bb.Position; UpdateProgress(start, count); GXDLMSTranslatorMessage msg = new GXDLMSTranslatorMessage(); msg.Message = bb; translator.MessageToXml(msg); if (follow != Follow.None) { if ((follow & Follow.Client) != 0 && clientAddress == 0) { clientAddress = msg.SourceAddress; } if ((follow & Follow.Meter) != 0 && serverAddress == 0) { serverAddress = msg.TargetAddress; } } //Remove duplicate messages. if (RemoveDuplicatesMnu.Checked) { if (last == msg.Xml) { continue; } } last = msg.Xml; if (msg.Command == Command.Aarq) { if (msg.SystemTitle != null && msg.SystemTitle.Length == 8) { if (UpdateSystemTitle(this, "Current System title \"{0}\" is different in the parsed \"{1}\". Do you want to start using parsed one?", msg.SystemTitle, translator.SystemTitle)) { translator.SystemTitle = msg.SystemTitle; BeginInvoke((Action)(() => { Ciphering.SystemTitle = msg.SystemTitle; })); } } if (msg.DedicatedKey != null && msg.DedicatedKey.Length == 16) { if (UpdateSystemTitle(this, "Current dedicated key \"{0}\" is different in the parsed \"{1}\". Do you want to start using parsed one?", msg.DedicatedKey, translator.DedicatedKey)) { translator.DedicatedKey = msg.DedicatedKey; BeginInvoke((Action)(() => { Ciphering.DedicatedKey = msg.DedicatedKey; })); } } } if (msg.Command == Command.Aare && msg.SystemTitle != null && msg.SystemTitle.Length == 8) { if (UpdateSystemTitle(this, "Current Server System title \"{0}\" is different in the parsed \"{1}\". Do you want to start using parsed one?", msg.SystemTitle, translator.ServerSystemTitle)) { translator.ServerSystemTitle = msg.SystemTitle; BeginInvoke((Action)(() => { Ciphering.ServerSystemTitle = msg.SystemTitle; })); } } if (show != ShowMessages.All) { switch (msg.Command) { case Command.None: break; case Command.InitiateRequest: case Command.ReadRequest: case Command.WriteRequest: case Command.GetRequest: case Command.SetRequest: case Command.MethodRequest: case Command.Snrm: case Command.Aarq: case Command.ReleaseRequest: case Command.DisconnectRequest: case Command.AccessRequest: case Command.GloGetRequest: case Command.GloSetRequest: case Command.GloMethodRequest: case Command.GloInitiateRequest: case Command.GloReadRequest: case Command.GloWriteRequest: case Command.DedInitiateRequest: case Command.DedReadRequest: case Command.DedWriteRequest: case Command.DedGetRequest: case Command.DedSetRequest: case Command.DedMethodRequest: case Command.GatewayRequest: if (show == ShowMessages.Received) { continue; } break; case Command.InitiateResponse: case Command.ReadResponse: case Command.WriteResponse: case Command.GetResponse: case Command.SetResponse: case Command.MethodResponse: case Command.Ua: case Command.Aare: case Command.ReleaseResponse: case Command.AccessResponse: case Command.GloGetResponse: case Command.GloSetResponse: case Command.GloMethodResponse: case Command.GloInitiateResponse: case Command.GloReadResponse: case Command.GloWriteResponse: case Command.DedInitiateResponse: case Command.DedReadResponse: case Command.DedWriteResponse: case Command.DedGetResponse: case Command.DedSetResponse: case Command.DedMethodResponse: case Command.GatewayResponse: if (show == ShowMessages.Sent) { continue; } break; case Command.DisconnectMode: case Command.UnacceptableFrame: case Command.ConfirmedServiceError: case Command.ExceptionResponse: case Command.GeneralBlockTransfer: case Command.DataNotification: case Command.GloEventNotification: case Command.GloConfirmedServiceError: case Command.GeneralGloCiphering: case Command.GeneralDedCiphering: case Command.GeneralCiphering: case Command.GeneralSigning: case Command.InformationReport: case Command.EventNotification: case Command.DedConfirmedServiceError: case Command.DedUnconfirmedWriteRequest: case Command.DedInformationReport: case Command.DedEventNotification: break; } } if (Properties.Settings.Default.TranslatorFrame) { if (Properties.Settings.Default.FrameNumber) { sb.Append(count + ": "); } sb.AppendLine(bb.ToHex(true, start, bb.Position - start)); } if (Properties.Settings.Default.TranslatorXml) { sb.Append(msg.Xml); } if (msg.Exception != null) { ++count; OnAppendMessage(sb.ToString(), Color.Red); } else if (show != ShowMessages.Failed) { ++count; OnAppendMessage(sb.ToString()); } sb.Clear(); pdu.Clear(); } OnAppendMessage(sb.ToString()); translator.Security = s; //Update UI. await System.Threading.Tasks.Task.Delay(1); } catch (Exception ex) { translator.Security = s; OnAppendMessage(sb.ToString()); OnAppendMessage(Environment.NewLine); OnAppendMessage(bb.RemainingHexString(true)); MessageBox.Show(ex.Message); } //Count starts from 1. UpdateMaxProgress(0, count - 1); BeginInvoke((Action)(() => { MessagePduTB.ReadOnly = false; TranslateBtn.Checked = false; })); }); }