private string ConstructMessageDetails(string Hl7Message)
        {
            HL7Message message = new HL7Message(Hl7Message);

            string[] msgID           = message.GetHL7ItemValue("MSH-10");
            string[] msgType         = message.GetHL7ItemValue("MSH-9.1");
            string[] msgTrigger      = message.GetHL7ItemValue("MSH-9.2");
            string   msgDetailString = "";

            // construct the strings if the elements exist in the message
            if (!((msgID == null) || (msgID.Length == 0)))
            {
                msgDetailString += "_" + msgID[0];
            }
            if (!((msgType == null) || (msgType.Length == 0)))
            {
                msgDetailString += "_" + msgType[0];
            }
            if (!((msgTrigger == null) || (msgTrigger.Length == 0)))
            {
                msgDetailString += "_" + msgTrigger[0];
            }
            return(msgDetailString);
        }
예제 #2
0
        /// <summary>
        /// Generate a string containing the ACK message in response to the original message. Supply a string containing the original message (or at least the MSH segment).
        /// </summary>
        /// <returns></returns>
        string GenerateACK(string originalMessage)
        {
            // create a HL7Message object using the original message as the source to obtain details to reflect back in the ACK message
            HL7Message tmpMsg          = new HL7Message(originalMessage);
            string     trigger         = tmpMsg.GetHL7ItemValue("MSH-9.2")[0];
            string     originatingApp  = tmpMsg.GetHL7ItemValue("MSH-3")[0];
            string     originatingSite = tmpMsg.GetHL7ItemValue("MSH-4")[0];
            string     messageID       = tmpMsg.GetHL7ItemValue("MSH-10")[0];
            string     processingID    = tmpMsg.GetHL7ItemValue("MSH-11")[0];
            string     hl7Version      = tmpMsg.GetHL7ItemValue("MSH-12")[0];
            string     ackTimestamp    = DateTime.Now.Year.ToString() + DateTime.Now.Month.ToString() + DateTime.Now.Day.ToString() + DateTime.Now.Hour.ToString() + DateTime.Now.Minute.ToString();

            StringBuilder ACKString = new StringBuilder();

            ACKString.Append((char)0x0B);
            ACKString.Append("MSH|^~\\&|HL7Listener|HL7Listener|" + originatingSite + "|" + originatingApp + "|" + ackTimestamp + "||ACK^" + trigger + "|" + messageID + "|" + processingID + "|" + hl7Version);
            ACKString.Append((char)0x0D);
            ACKString.Append("MSA|CA|" + messageID);
            ACKString.Append((char)0x1C);
            ACKString.Append((char)0x0D);
            return(ACKString.ToString());
        }
예제 #3
0
        /// <summary>
        /// get the HL7 item provided via the cmdlet parameter HL7ItemPosition
        /// </summary>
        protected override void ProcessRecord()
        {
            // confirm the item location parameter is valid before processing any files
            if (!Common.IsHL7LocationStringValid(this.itemPosition))
            {
                ArgumentException ex    = new ArgumentException(this.itemPosition + " does not appear to be a valid HL7 item");
                ErrorRecord       error = new ErrorRecord(ex, "InvalidElement", ErrorCategory.InvalidArgument, this.itemPosition);
                this.WriteError(error);
                return;
            }

            // confirm the filter parameter is valid before processing any files
            foreach (string currentFilter in this.filter)
            {
                // confirm each filter is formatted correctly
                if (!Common.IsFilterValid(currentFilter))
                {
                    ArgumentException ex    = new ArgumentException(currentFilter + " does not appear to be a valid filter");
                    ErrorRecord       error = new ErrorRecord(ex, "InvalidFilter", ErrorCategory.InvalidArgument, currentFilter);
                    this.WriteError(error);
                    return;
                }
            }

            // set the text encoding
            Encoding encoder = System.Text.Encoding.GetEncoding(this.encoding);

            WriteVerbose("Encoding: " + encoder.EncodingName);

            // expand the file or directory information provided in the -Path or -LiteralPath parameters
            foreach (string path in paths)
            {
                // This will hold information about the provider containing the items that this path string might resolve to.
                ProviderInfo provider;

                // This will be used by the method that processes literal paths
                PSDriveInfo drive;

                // this contains the paths to process for this iteration of the loop to resolve and optionally expand wildcards.
                List <string> filePaths = new List <string>();

                // if the path provided is a directory, expand the files in the directy and add these to the list.
                if (Directory.Exists(path))
                {
                    filePaths.AddRange(Directory.GetFiles(path));
                }

                // not a directory, could be a wildcard or literal filepath
                else
                {
                    // expand wildcards. This assumes if the user listed a directory it is literal
                    if (expandWildcards)
                    {
                        // Turn *.txt into foo.txt,foo2.txt etc. If path is just "foo.txt," it will return unchanged. If the filepath expands into a directory ignore it.
                        foreach (string expandedFilePath in this.GetResolvedProviderPathFromPSPath(path, out provider))
                        {
                            if (!Directory.Exists(expandedFilePath))
                            {
                                filePaths.Add(expandedFilePath);
                            }
                        }
                    }
                    else
                    {
                        // no wildcards, so don't try to expand any * or ? symbols.
                        filePaths.Add(this.SessionState.Path.GetUnresolvedProviderPathFromPSPath(path, out provider, out drive));
                    }
                    // ensure that this path (or set of paths after wildcard expansion)
                    // is on the filesystem. A wildcard can never expand to span multiple providers.
                    if (Common.IsFileSystemPath(provider, path) == false)
                    {
                        // no, so skip to next path in paths.
                        continue;
                    }
                }

                // At this point, we have a list of paths on the filesystem, process each file.
                foreach (string filePath in filePaths)
                {
                    // If the file does not exist display an error and return.
                    if (!File.Exists(filePath))
                    {
                        FileNotFoundException fileException     = new FileNotFoundException("File not found", filePath);
                        ErrorRecord           fileNotFoundError = new ErrorRecord(fileException, "FileNotFound", ErrorCategory.ObjectNotFound, filePath);
                        WriteError(fileNotFoundError);
                        return;
                    }

                    // if the ItemPosition parameter is not in the correct format display an error and return
                    if (!Common.IsItemLocationValid(this.itemPosition))
                    {
                        ArgumentException argException   = new ArgumentException("The -ItemPosition parameter does not appear to be in the correct format.", this.itemPosition);
                        ErrorRecord       parameterError = new ErrorRecord(argException, "ParameterNotValid", ErrorCategory.InvalidArgument, this.itemPosition);
                        WriteError(parameterError);
                        return;
                    }

                    // process the message
                    try {
                        // assume the filter is true, until a failed match is found
                        this.filterConditionsMet = true;
                        // load the file into a HL7Message object for processing
                        string     fileContents = File.ReadAllText(filePath, encoder);
                        HL7Message message      = new HL7Message(fileContents);
                        // if a filter was supplied, evaluate if the file matches the filter condition
                        if (this.filter != null)
                        {
                            // check to see is all of the filter conditions are met (ie AND all filters supplied).
                            foreach (string currentFilter in this.filter)
                            {
                                bool   anyItemMatch = false;
                                string filterItem   = Common.GetFilterItem(currentFilter);
                                string filterValue  = Common.GetFilterValue(currentFilter);
                                // for repeating fields, only one of the items returned has to match for the filter to be evaluated as true.
                                foreach (string itemValue in message.GetHL7ItemValue(filterItem))
                                {
                                    if (itemValue.ToUpper() == filterValue.ToUpper())
                                    {
                                        anyItemMatch = true;
                                    }
                                }
                                // if none of the repeating field items match, then fail the filter match for this file.
                                if (!anyItemMatch)
                                {
                                    this.filterConditionsMet = false;
                                }
                            }
                        }

                        // if the filter supplied matches this message (or no filter provided) then process the file to optain the HL7 item requested
                        if (filterConditionsMet)
                        {
                            List <HL7Item> hl7Items = message.GetHL7Item(itemPosition);
                            // if the hl7Items array is  empty, the item was not found in the message
                            if (hl7Items.Count == 0)
                            {
                                WriteWarning("Item " + this.itemPosition + " not found in the message " + filePath);
                            }

                            //  items were located in the message, so proceed with replacing the original value with the new value.
                            else
                            {
                                // update all repeats/occurances of the specified item
                                if (this.allrepeats)
                                {
                                    foreach (HL7Item item in hl7Items)
                                    {
                                        // appeand the new value to the existing value of the item if -AppendToExistingValue switch is set
                                        if (appendValue)
                                        {
                                            this.newValue = item.ToString() + this.newValue;
                                        }
                                        // update the item value
                                        SetHL7ItemResult result = new SetHL7ItemResult(this.newValue, item.ToString(), filePath, this.itemPosition);
                                        item.SetValueFromString(this.newValue);
                                        WriteObject(result);
                                    }
                                }
                                // update only the first occurrance. This is the default action.
                                else
                                {
                                    // append the new value to the existing value of the item if -AppendToExistingValue switch is set
                                    if (appendValue)
                                    {
                                        this.newValue = hl7Items.ElementAt(0).ToString() + this.newValue;
                                    }
                                    // update the item value
                                    SetHL7ItemResult result = new SetHL7ItemResult(this.newValue, hl7Items.ElementAt(0).ToString(), filePath, this.itemPosition);
                                    hl7Items.ElementAt(0).SetValueFromString(this.newValue);
                                    WriteObject(result);
                                }
                                // Write changes to the file. Replace the segment delimeter <CR> with the system newline string as this is being written to a file.
                                string cr      = ((char)0x0D).ToString();
                                string newline = System.Environment.NewLine;
                                if (this.ShouldProcess(filePath, "Saving changes to file"))
                                {
                                    System.IO.File.WriteAllText(filePath, message.ToString().Replace(cr, newline), encoder);
                                }
                            }
                        }
                    }

                    // if the file does not start with a MSH segment, the constructor will throw an exception.
                    catch (System.ArgumentException) {
                        ArgumentException argException     = new ArgumentException("The file does not appear to be a valid HL7 v2 message", filePath);
                        ErrorRecord       invalidFileError = new ErrorRecord(argException, "FileNotValid", ErrorCategory.InvalidData, filePath);
                        WriteError(invalidFileError);
                        return;
                    }
                }
            }
        }
예제 #4
0
        /// <summary>
        /// Receive data from a client connection, look for MLLP HL7 message.
        /// </summary>
        /// <param name="client"></param>
        private void ReceiveData(object client)
        {
            // generate a random sequence number to use for the file names
            Random random = new Random(Guid.NewGuid().GetHashCode());
            int    filenameSequenceStart = random.Next(0, 1000000);

            TcpClient     tcpClient    = (TcpClient)client;
            NetworkStream clientStream = tcpClient.GetStream();

            clientStream.ReadTimeout  = TCP_TIMEOUT;
            clientStream.WriteTimeout = TCP_TIMEOUT;

            byte[] messageBuffer = new byte[4096];
            int    bytesRead;
            String messageData  = "";
            int    messageCount = 0;

            while (true)
            {
                bytesRead = 0;
                try {
                    // Wait until a client application submits a message
                    bytesRead = clientStream.Read(messageBuffer, 0, 4096);
                }
                catch (Exception) {
                    // A network error has occurred
                    LogDebug("Connection from " + tcpClient.Client.RemoteEndPoint + " has ended");
                    break;
                }
                if (bytesRead == 0)
                {
                    // The client has disconected
                    LogDebug("The client " + tcpClient.Client.RemoteEndPoint + " has disconnected");
                    break;
                }
                // Message buffer received successfully
                messageData += Encoding.UTF8.GetString(messageBuffer, 0, bytesRead);
                // Find a VT character, this is the beginning of the MLLP frame
                int start = messageData.IndexOf((char)0x0B);
                if (start >= 0)
                {
                    // Search for the end of the MLLP frame (a FS character)
                    int end = messageData.IndexOf((char)0x1C);
                    if (end > start)
                    {
                        messageCount++;
                        try {
                            // queue the message to sent to the passthru host if the -PassThru option has been set
                            if (passthruHost != null)
                            {
                                messageQueue.Enqueue(messageData.Substring(start + 1, end - (start + 1)));
                            }
                            // create a HL7message object from the message recieved. Use this to access elements needed to populate the ACK message and file name of the archived message
                            HL7Message message = new HL7Message(messageData.Substring(start + 1, end - (start + 1)));
                            messageData = ""; // reset the message data string for the next message
                            string messageTrigger   = message.GetHL7ItemValue("MSH-9")[0];
                            string messageControlID = message.GetHL7ItemValue("MSH-10")[0];
                            //string acceptAckType = message.GetHL7Item("MSH-15")[0];
                            string dateStamp = DateTime.Now.Year.ToString() + DateTime.Now.Month.ToString().PadLeft(2, '0') + DateTime.Now.Day.ToString().PadLeft(2, '0') + DateTime.Now.Hour.ToString().PadLeft(2, '0') + DateTime.Now.Minute.ToString().PadLeft(2, '0');
                            string filename  = dateStamp + "_" + (filenameSequenceStart + messageCount).ToString("D6") + "_" + messageTrigger + ".hl7"; //  increment sequence number for each filename
                            // Write the HL7 message to file.
                            WriteMessagetoFile(message.ToString(), System.IO.Path.Combine(this.archivePath, filename));
                            ReceivedMessageResult resultObject = new ReceivedMessageResult(messageTrigger, System.IO.Path.Combine(this.archivePath, filename), tcpClient.Client.RemoteEndPoint.ToString());
                            objectQueue.Enqueue(resultObject);
                            // send ACK message is MSH-15 is set to AL and ACKs not disbaled by -NOACK command line switch
                            //if ((this.sendACK) && (acceptAckType.ToUpper() == "AL"))
                            if (this.sendACK)
                            {
                                LogDebug("Sending ACK (Message Control ID: " + messageControlID + ")");
                                // generate ACK Message and send in response to the message received
                                string response        = GenerateACK(message.ToString()); // TO DO: send ACKS if set in message header, or specified on command line
                                byte[] encodedResponse = Encoding.UTF8.GetBytes(response);
                                // Send response
                                try {
                                    clientStream.Write(encodedResponse, 0, encodedResponse.Length);
                                    clientStream.Flush();
                                }
                                catch (Exception e) {
                                    // A network error has occurred
                                    LogDebug("An error has occurred while sending an ACK to the client " + tcpClient.Client.RemoteEndPoint);
                                    LogDebug(e.Message);
                                    break;
                                }
                            }
                        }
                        catch (Exception e) {
                            messageData = ""; // reset the message data string for the next message
                            LogWarning("An exception occurred while parsing the HL7 message");
                            LogWarning(e.Message);
                            break;
                        }
                    }
                }
            }
            LogDebug("Total messages received:" + messageCount);
            clientStream.Close();
            clientStream.Dispose();
            tcpClient.Close();
        }
예제 #5
0
        /// <summary>
        /// get the HL7 item provided via the cmdlet parameter HL7ItemPosition
        /// </summary>
        protected override void ProcessRecord()
        {
            // confirm the item location parameter is valid before processing any files
            if (!Common.IsHL7LocationStringValid(this.itemPosition))
            {
                ArgumentException ex    = new ArgumentException(this.itemPosition + " does not appear to be a valid HL7 item");
                ErrorRecord       error = new ErrorRecord(ex, "InvalidElement", ErrorCategory.InvalidArgument, this.itemPosition);
                this.WriteError(error);
                return;
            }

            // confirm the filter parameter is valid before processing any files
            foreach (string currentFilter in this.filter)
            {
                // confirm each filter is formatted correctly
                if (!Common.IsFilterValid(currentFilter))
                {
                    ArgumentException ex    = new ArgumentException(currentFilter + " does not appear to be a valid filter");
                    ErrorRecord       error = new ErrorRecord(ex, "InvalidFilter", ErrorCategory.InvalidArgument, currentFilter);
                    this.WriteError(error);
                    return;
                }
            }

            // expand the file or directory information provided in the -Path or -LiteralPath parameters
            foreach (string path in paths)
            {
                // This will hold information about the provider containing the items that this path string might resolve to.
                ProviderInfo provider;

                // This will be used by the method that processes literal paths
                PSDriveInfo drive;

                // this contains the paths to process for this iteration of the loop to resolve and optionally expand wildcards.
                List <string> filePaths = new List <string>();

                // if the path provided is a directory, expand the files in the directy and add these to the list.
                if (Directory.Exists(path))
                {
                    filePaths.AddRange(Directory.GetFiles(path));
                }

                // not a directory, could be a wildcard or literal filepath
                else
                {
                    // expand wildcards. This assumes if the user listed a directory it is literal
                    if (expandWildcards)
                    {
                        // Turn *.txt into foo.txt,foo2.txt etc. If path is just "foo.txt," it will return unchanged. If the filepath expands into a directory ignore it.
                        foreach (string expandedFilePath in this.GetResolvedProviderPathFromPSPath(path, out provider))
                        {
                            if (!Directory.Exists(expandedFilePath))
                            {
                                filePaths.Add(expandedFilePath);
                            }
                        }
                    }
                    else
                    {
                        // no wildcards, so don't try to expand any * or ? symbols.
                        filePaths.Add(this.SessionState.Path.GetUnresolvedProviderPathFromPSPath(path, out provider, out drive));
                    }
                    // ensure that this path (or set of paths after wildcard expansion)
                    // is on the filesystem. A wildcard can never expand to span multiple providers.
                    if (Common.IsFileSystemPath(provider, path) == false)
                    {
                        // no, so skip to next path in paths.
                        continue;
                    }
                }

                // At this point, we have a list of paths on the filesystem, process each file.
                foreach (string filePath in filePaths)
                {
                    // If the file does not exist display an error and return.
                    if (!File.Exists(filePath))
                    {
                        FileNotFoundException fileException     = new FileNotFoundException("File not found", filePath);
                        ErrorRecord           fileNotFoundError = new ErrorRecord(fileException, "FileNotFound", ErrorCategory.ObjectNotFound, filePath);
                        WriteError(fileNotFoundError);
                        return;
                    }

                    // if the ItemPosition parameter is not in the correct format display an error and return
                    if (!Common.IsItemLocationValid(this.itemPosition))
                    {
                        ArgumentException argException   = new ArgumentException("The -ItemPosition parameter does not appear to be in the correct format.", this.itemPosition);
                        ErrorRecord       parameterError = new ErrorRecord(argException, "ParameterNotValid", ErrorCategory.InvalidArgument, this.itemPosition);
                        WriteError(parameterError);
                        return;
                    }

                    // process the message
                    try {
                        // assume the filter is true, until a failed match is found
                        this.filterConditionsMet = true;
                        // load the file into a HL7Message object for processing
                        string     fileContents = File.ReadAllText(filePath);
                        HL7Message message      = new HL7Message(fileContents);
                        // if a filter was supplied, evaluate if the file matches the filter condition
                        if (this.filter != null)
                        {
                            // check to see is all of the filter conditions are met (ie AND all filters supplied).
                            foreach (string currentFilter in this.filter)
                            {
                                bool   anyItemMatch = false;
                                string filterItem   = Common.GetFilterItem(currentFilter);
                                string filterValue  = Common.GetFilterValue(currentFilter);
                                // for repeating fields, only one of the items returned has to match for the filter to be evaluated as true.
                                foreach (string itemValue in message.GetHL7ItemValue(filterItem))
                                {
                                    // convert both values to upper case for a case insentive match
                                    if (itemValue.ToUpper() == filterValue.ToUpper())
                                    {
                                        anyItemMatch = true;
                                    }
                                }
                                // if none of the repeating field items match, then fail the filter match for this file.
                                if (!anyItemMatch)
                                {
                                    this.filterConditionsMet = false;
                                }
                            }
                        }

                        // if the filter supplied matches this message (or no filter provided) then process the file to optain the HL7 item requested
                        if (filterConditionsMet)
                        {
                            string[] hl7Items = message.GetHL7ItemValue(itemPosition);
                            // if the hl7Items array is  empty, the item was not found in the message
                            if (hl7Items.Length == 0)
                            {
                                WriteWarning("Item " + this.itemPosition + " not found in the message " + filePath);
                            }

                            //  items were returned
                            else
                            {
                                SelectHL7ItemResult result = new SelectHL7ItemResult(hl7Items, filePath);
                                WriteObject(result);
                            }
                        }
                    }

                    // if the file does not start with a MSH segment, the constructor will throw an exception.
                    catch (System.ArgumentException) {
                        ArgumentException argException     = new ArgumentException("The file does not appear to be a valid HL7 v2 message", filePath);
                        ErrorRecord       invalidFileError = new ErrorRecord(argException, "FileNotValid", ErrorCategory.InvalidData, filePath);
                        WriteError(invalidFileError);
                        return;
                    }
                }
            }
        }
예제 #6
0
        /// <summary>
        /// get the HL7 item provided via the cmdlet parameter HL7ItemPosition
        /// </summary>
        protected override void ProcessRecord()
        {
            // expand the file or directory information provided in the -Path or -LiteralPath parameters
            foreach (string path in paths)
            {
                // This will hold information about the provider containing the items that this path string might resolve to.
                ProviderInfo provider;
                // This will be used by the method that processes literal paths
                PSDriveInfo drive;
                // this contains the paths to process for this iteration of the loop to resolve and optionally expand wildcards.
                List <string> filePaths = new List <string>();

                // if the path provided is a directory, expand the files in the directory and add these to the list.
                if (Directory.Exists(path))
                {
                    filePaths.AddRange(Directory.GetFiles(path));
                }

                // not a directory, could be a wildcard or literal filepath
                else
                {
                    // expand wildcards. This assumes if the user listed a directory it is literal
                    if (expandWildcards)
                    {
                        // Turn *.txt into foo.txt,foo2.txt etc. If path is just "foo.txt," it will return unchanged. If the filepath expands into a directory ignore it.
                        foreach (string expandedFilePath in this.GetResolvedProviderPathFromPSPath(path, out provider))
                        {
                            if (!Directory.Exists(expandedFilePath))
                            {
                                filePaths.Add(expandedFilePath);
                            }
                        }
                    }
                    else
                    {
                        // no wildcards, so don't try to expand any * or ? symbols.
                        filePaths.Add(this.SessionState.Path.GetUnresolvedProviderPathFromPSPath(path, out provider, out drive));
                    }
                    // ensure that this path (or set of paths after wildcard expansion)
                    // is on the filesystem. A wildcard can never expand to span multiple providers.
                    if (Common.IsFileSystemPath(provider, path) == false)
                    {
                        // no, so skip to next path in paths.
                        continue;
                    }
                }

                // At this point, we have a list of paths on the filesystem, process each file.
                foreach (string filePath in filePaths)
                {
                    // If the file does not exist display an error and return.
                    if (!File.Exists(filePath))
                    {
                        FileNotFoundException fileException     = new FileNotFoundException("File not found", filePath);
                        ErrorRecord           fileNotFoundError = new ErrorRecord(fileException, "FileNotFound", ErrorCategory.ObjectNotFound, filePath);
                        WriteError(fileNotFoundError);
                        return;
                    }

                    // process the message
                    try {
                        // load the file into a HL7Message object for processing
                        string     fileContents = File.ReadAllText(filePath);
                        HL7Message message      = new HL7Message(fileContents);

                        // get the message trigger from MSH-9 (only interested in MSH-9.1 and MSH-9.2 - ignore any document types if included).
                        string[] messageTrigger = message.GetHL7ItemValue("MSH-9");
                        string[] splitTrigger   = messageTrigger[0].Split(message.ComponentDelimeter);
                        string   simplifiedTrigger;
                        if (splitTrigger.Length > 1)
                        {
                            simplifiedTrigger = splitTrigger[0] + message.ComponentDelimeter + splitTrigger[1];
                        }
                        else
                        {
                            simplifiedTrigger = splitTrigger[0];
                        }

                        // get the message timestamp
                        string[] messageDateTime = message.GetHL7ItemValue("MSH-7");
                        // if the hl7Items array is  empty, the item was not found in the message
                        if (messageDateTime.Length == 0)
                        {
                            WriteWarning("MSH-7 does not contain a value for " + filePath);
                        }
                        //  items were returned
                        else
                        {
                            string timePattern     = "[0-9]{12}([0-9]{2})?";
                            string timezonePattern = "(?<=(/+|-))[0-9]{4}";

                            Match timeMatch     = Regex.Match(messageDateTime[0], timePattern);
                            Match timezoneMatch = Regex.Match(messageDateTime[0], timezonePattern);

                            if (timeMatch.Success)
                            {
                                // time zone is includes
                                if (timezoneMatch.Success)
                                {
                                    // time includes seconds
                                    if (timeMatch.Value.Length == 14)
                                    {
                                        ShowHL7MessageTimelineResult resultListItem = new ShowHL7MessageTimelineResult(DateTime.ParseExact(timeMatch.Value + timezoneMatch.Groups[1].Value + timezoneMatch.Value, "yyyyMMddHHmmsszzzz", null), filePath, simplifiedTrigger);
                                        messageTimestampResults.Add(resultListItem);
                                    }
                                    // time only resolves to minutes
                                    else
                                    {
                                        ShowHL7MessageTimelineResult resultListItem = new ShowHL7MessageTimelineResult(DateTime.ParseExact(timeMatch.Value + timezoneMatch.Groups[1].Value + timezoneMatch.Value, "yyyyMMddHHmmzzzz", null), filePath, simplifiedTrigger);
                                        messageTimestampResults.Add(resultListItem);
                                    }
                                }
                                // timezone is not included
                                else
                                {
                                    // time includes seconds
                                    if (timeMatch.Value.Length == 14)
                                    {
                                        ShowHL7MessageTimelineResult resultListItem = new ShowHL7MessageTimelineResult(DateTime.ParseExact(timeMatch.Value, "yyyyMMddHHmmss", null), filePath, simplifiedTrigger);
                                        messageTimestampResults.Add(resultListItem);
                                    }
                                    // time only resolves to minutes
                                    else
                                    {
                                        ShowHL7MessageTimelineResult resultListItem = new ShowHL7MessageTimelineResult(DateTime.ParseExact(timeMatch.Value, "yyyyMMddHHmm", null), filePath, simplifiedTrigger);
                                        messageTimestampResults.Add(resultListItem);
                                    }
                                }
                            }
                            // timestamp missing, or does not resolve down to at least minutes
                            else
                            {
                                WriteWarning("Timestamp missing from " + filePath);
                            }
                        }
                    }
                    // if the file does not start with a MSH segment, the constructor will throw an exception.
                    catch (System.ArgumentException) {
                        ArgumentException argException     = new ArgumentException("The file does not appear to be a valid HL7 v2 message", filePath);
                        ErrorRecord       invalidFileError = new ErrorRecord(argException, "FileNotValid", ErrorCategory.InvalidData, filePath);
                        WriteError(invalidFileError);
                        return;
                    }
                }
            }
        }