For starters, I think this:

request.GetValueAt("RGSgrp(1).AIGgrp(context.AIGitr).AIG:3)")'=""

Should actually be this:

request.GetValueAt("RGSgrp(1).AIGgrp("_context.AIGitr_").AIG:3)")'=""

Let's see what happens after you fix that.

Jeffrey Drumm · Dec 13, 2025 go to post

Yes, adding that rule to your DTL will set MSH:6, assuming the schema you've selected for the target message in your DTL definition uses ReceivingFacility as the fieldname. You can use the numeric representation MSH:6 if you prefer. It will work just as well as MSH:ReceivingFacility, but is not as human-readable.

Jeffrey Drumm · Dec 3, 2025 go to post

If you're using the HL7 File Service, the full filename can be found as a %String in the message object's Source property. You can extract the required characters from that and set MSH:6 in a DTL:

Jeffrey Drumm · Nov 10, 2025 go to post

If you're using a custom business process to handle the message, you could perform the truncate in an OnRequest() callback.

If you're using a BPL, you would add an action near the beginning of the process to perform the truncate. The request object will be a single batch object containing a collection of records; the next step would be to iterate over the collection and perform the inserts.

You could do essentially the same thing in a DTL; use an SQL rule at the beginning to truncate, then add a foreach to iterate over the batch and populate the DB.

The key is the fact that your BP is getting all of the records in a single object. So when that object arrives, it's time to truncate the table and repopulate it. You will have to skip the first record if it contains headers, of course.

Jeffrey Drumm · Oct 31, 2025 go to post

With IRIS 2025.1.1 on Windows, I cannot reproduce your issue. Both sets of instructions execute normally. 

VS Code Version: 1.105.1 (user setup)
Commit: 7d842fb85a0275a4a8e4d7e040d2625abbf7f084
Date: 2025-10-14T22:33:36.618Z
Electron: 37.6.0
ElectronBuildId: 12502201
Chromium: 138.0.7204.251
Node.js: 22.19.0
V8: 13.8.258.32-electron.0
OS: Windows_NT x64 10.0.19045

ISC ObjectScript Extension 3.2.1-beta.1

ISC Server Manager 3.10.6-beta.3

ISC Language Server 2.8.0

Jeffrey Drumm · Oct 27, 2025 go to post

You are correct in that ReplyCodeAction E* does not evaluate the contents of the ACK message MSA segment; it only looks at the IRIS error code and text.

For your specific example, though, I'm wondering why you're not simply setting a condition to exclude invalid messages in the Routing Rule?

Jeffrey Drumm · Oct 22, 2025 go to post

A foreach (possibly multiple foreaches) is what you need. Getting the iterators right is the issue. You're iterating over the AISgrp in the first RGSgrp of the source message and placing them in target RGSGroups with the same iteration count of the source AISgrp. Here's an example based on the 2.3.1:SIU_S12 schema structure that should do what you want, and also handles repetitions of the AIL, AIP and AIG groups:

Jeffrey Drumm · Oct 21, 2025 go to post

And Firefox! Note that the author requests payment equivalent to US$9.99. As far as I can tell, payment doesn't unlock any special features, but it's probably the right thing to do 😁

Jeffrey Drumm · Oct 15, 2025 go to post

If Cache isn't running under his account, it likely won't have access to that directory. 

Jeffrey Drumm · Oct 15, 2025 go to post

What account is Caché running under? You'll need to review Windows Services to find the Caché service controller (I don't remember the exact name). It's probably running under the Local System account; you'll need to change it to log on with your own credentials if you want it to use your account's environment.

Jeffrey Drumm · Oct 14, 2025 go to post

Instead of ..Contains() as the outer method, use:

..RegexMatch(..ToUpper(source.{PIDgrpgrp(k1).ORCgrp(k2).OBXgrp(2).OBX:ObservationValue()}),"NOT DETECTED|NEGATIVE")
Jeffrey Drumm · Oct 7, 2025 go to post

I just attempted the same sequence using a known valid network path on IRIS 2025.1.1 and it worked as expected. The result set contained the list of folders and files in the specified share.

Jeffrey Drumm · Oct 7, 2025 go to post

I've never created an IPM module ... it seems like a fair amount of effort to set it up for a single small class and based  on my current status it's unlikely that I'd do it more than this one time.

That said, if some streamlined mechanism for building and publishing it exists, I'll give it a shot ...

Jeffrey Drumm · Oct 6, 2025 go to post

ORCgrp is a member of PIDgrpgrp and PIDgrpgrp is missing from your "if" statement. The condition should read:

..Contains(..ToUpper(source.{PIDgrpgrp(k1).ORCgrp(k2).OBXgrp(k3).OBX:ObservationValue()}),"DETECTED")

I don't know whether you're using the same doctype for the target, but if you are, the target path will need to be updated as well.

Jeffrey Drumm · Oct 6, 2025 go to post

Use a combination of the ToUpper() and Contains() methods in the Function list with an if rule:

The AI Bot offers another option, but it's probably a bit more involved than you really need 😁

Jeffrey Drumm · Oct 3, 2025 go to post

The rule parser/compiler doesn't handle calls to methods/classmethods unless they extend Ens.Rule.FunctionSet, and it doesn't recognize the ##class() keyword. If your class does extend Ens.Rule.FunctionSet, you should be able to use just the Methodname as shown below:

<assignproperty="PropertyName"value="SomeMethod(args)" />
Jeffrey Drumm · Oct 3, 2025 go to post

Here's an example of the generated query, updated with calls to HICG.GetMsg():
 

SELECT TOP 100 head.ID AsID, 
    {fn RIGHT(%EXTERNAL(head.TimeCreated),999 )} As TimeCreated,
    head.SessionId AsSession, 
    head.Status AsStatus,
    CASE head.IsError WHEN1THEN'Error'ELSE'OK'ENDAsError,
    head.SourceConfigName AsSource,
    head.TargetConfigName As Target,
    head.SourceConfigName, 
    head.TargetConfigName, 
    head.MessageBodyClassName As BodyClassname, 
    head.MessageBodyId As BodyId, 
    EnsLib_HL7.Message.%IDAs Body_ID, 
    HICG.GetMsg(head.MessageBodyId,'PID:3') As Body_PID_PatientID,
    HICG.GetMsg(head.MessageBodyId,'PID:18') As Body_PID_PatientAccountNumber 
    FROM %IGNOREINDEX Ens.MessageHeader.SessionId Ens.MessageHeader head, 
        EnsLib_HL7.Message 
    WHERE (((head.SourceConfigName = 'From_Some_Router'AND head.TargetConfigName = 'To_Some_Operation')) 
        AND head.MessageBodyClassName='EnsLib.HL7.Message'AND head.MessageBodyId=EnsLib_HL7.Message.%ID) 
    ORDERBY head.ID Desc

I just replaced the null values with calls to HICG.GetMsg(). The 2nd argument is the schema-specific path to the values you're extracting, using the same syntax as found in EnsLib.HL7.Message's GetValueAt() method. You can download the class from the HL7 Spy website: https://hl7spy.ca/downloads/HICG_HL7.xml.

Jeffrey Drumm · Oct 3, 2025 go to post

While @David.M's response will provide a query, it will likely not include the HL7 message-derived values. For example, a search that includes the HL7 field values you've listed will return null for their values when executed via the SQL menu or SQL shell.

That said, I created a tool (originally for use with HL7 Spy to extract HL7 messages from Ensemble/Health Connect) that has some features that may help get you what you want. See this thread for an example of its use.

Jeffrey Drumm · Sep 15, 2025 go to post

On Ubuntu, check your /etc/apache2/apache2.conf file and verify that the csp Directory stanza contains a CSPFileTypes line with all of the required file extensions needed:

<Directory "/opt/webgateway/csp">
        CSPFileTypes csp cls zen cxw png jpg css gif svg js
        AllowOverride None
        Options MultiViews FollowSymLinks ExecCGI
        Require all granted
        <FilesMatch "\.(log|ini|pid|exe)$">
                Require all denied
        </FilesMatch></Directory>
Jeffrey Drumm · Sep 8, 2025 go to post

Getting this error with SQL tools when connecting to IRIS 2025.1.1 via https. The customer I'm working with has an internal CA and its root/chain is in my trusted root certificate store. The ObjectScript extension doesn't appear to complain about it when using https for my server configurations, with or without NODE_TLS_REJECT_UNAUTHORIZED = 0 set in the environment.

From the SQL Tools error log:

Error t [RequestError]: Error: unable to verify the first certificate
at new t (c:\Users\Jeff.vscode\extensions\intersystems-community.sqltools-intersystems-driver-0.1.7\dist\ls\plugin.js:2:405571)
at U.callback (c:\Users\Jeff.vscode\extensions\intersystems-community.sqltools-intersystems-driver-0.1.7\dist\ls\plugin.js:2:407384)
at e.callback.t.callback [as _callback] (c:\Users\Jeff.vscode\extensions\intersystems-community.sqltools-intersystems-driver-0.1.7\dist\ls\plugin.js:2:406830)
at t._callback.t.callback.t.callback (c:\Users\Jeff.vscode\extensions\intersystems-community.sqltools-intersystems-driver-0.1.7\dist\ls\plugin.js:2:430662)
at U.emit (node:events:518:28)
at U.onRequestError (c:\Users\Jeff.vscode\extensions\intersystems-community.sqltools-intersystems-driver-0.1.7\dist\ls\plugin.js:2:439522)
at ClientRequest.emit (node:events:518:28)
at emitErrorEvent (node:_http_client:104:11)
at TLSSocket.socketErrorListener (node:_http_client:518:5)
at TLSSocket.emit (node:events:518:28)
at emitErrorNT (node:internal/streams/destroy:170:8)
at emitErrorCloseNT (node:internal/streams/destroy:129:3)
at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {
cause: Error: unable to verify the first certificate
at TLSSocket.onConnectSecure (node:_tls_wrap:1679:34)
at TLSSocket.emit (node:events:518:28)
at TLSSocket._finishInit (node:_tls_wrap:1078:8)
at ssl.onhandshakedone (node:_tls_wrap:864:12) {
code: 'UNABLE_TO_VERIFY_LEAF_SIGNATURE'

A similar issue has been reported on GitHub, and I added the relevant stuff from above as a comment; the issue has been open since May and he developer hasn't responded. Just wondering if anyone else has experienced this and found a solution.

Jeffrey Drumm · Sep 4, 2025 go to post

The Matches() method in the DTL and Routing Rule function list does not use regex syntax; it uses COS "?" pattern matching. The pattern you'd need for your specific example is "1A2N" for 1 alpha character followed by 2 digits.

There's also a ..RegexMatch() method for the DTL and Routing Rule editors in most modern versions of IRIS. That accepts most pcre regex patterns.

Jeffrey Drumm · Aug 21, 2025 go to post

It's been my experience that the contents of the ACK message are not evaluated by any of the ReplyCodeActions. If you need to specifically suspend messages that are NAK'ed with this value in MSA:3, you'll need to create a custom operation and associated adapter (likely extending EnsLib.HL7.Operation.TCPOperation and EnsLib.HL7.Adapter.TCPOutboundAdapter respectively) that implements the NAK/Suspend logic.

Jeffrey Drumm · Aug 20, 2025 go to post

There were a couple of solutions mentioned in my reply.

If you need to work with field values in the message, either for routing or transformation, you will need to create a custom schema that includes the Z segment (which you'll also need to create) and assign that Message Schema Category in the inbound interface.

And if you want to transform the message using the DTL Editor, you'll need to specify the custom Message Schema Category for the Source (and possibly Target, if the downstream application needs it) message.

Jeffrey Drumm · Aug 18, 2025 go to post

Include the setting in the SETTINGS string, but prefix it with a dash (-) character:

Parameter SETTINGS = "-Whatever,DSN:Basic:selector?context={Ens.ContextSearch/DSNs},..."

EDIT: Was apparently typing that while you were reading the documentation 😁

And for competeness' sake, the actual documentation:

Adding and Removing Settings

Jeffrey Drumm · Aug 11, 2025 go to post

While I love this idea (and have voted for it!) I think it would be ideal to generalize it into the concept of themes. I've elaborated on my reasoning in a comment on the idea @Yone Moreno Jiménez  posted in the Ideas Portal.

I'm wondering if it should be its own Idea, though ... but I don't want to "split the vote" if it interferes with Yone getting his accessibility issue addressed.

Jeffrey Drumm · Aug 5, 2025 go to post

Also, one might be tempted to simply kill the ^Ens.Queue global.

Don't.

^Ens.Queue is used for other housekeeping tasks, and while killing it will absolutely remove all messages from visibility in the queue viewer, it won't change the message headers for those items from queued status to something else (like aborted or discarded). And it will very likely break other things that you really don't want to break.

Jeffrey Drumm · Aug 5, 2025 go to post

Here's a short method you can place in a utility class that does what you want:

ClassMethod AbortAll() As%Status
{
    Set tSC = $$$OKSet tQry = ##class(%SQL.Statement).%New()
    Set tSC = tQry.%PrepareClassQuery("Ens.Queue","Enumerate")
    If$$$ISOK(tSC)
    {
        Set tRS = tQry.%Execute()
        While tRS.%Next()
        {
            Set tQueue = tRS.%Get("Name")
            Write !, "Aborting Queue "_tQueue
            Do##class(Ens.Queue).AbortQueue(tQueue)
        }
    }
    Return tSC
}