Question
Eduard Lebedyuk · Mar 11, 2016

Determine currently used service

I want to determine what service (eg. %Service_Console) is used for current process.

I can probably use some workarounds, i.e.

  • Is %request object present
  • Does $Device  contain |TRM|
  • etc

But is there any centralised way to get current service?

20
2 0 7 248
Log in or sign up to continue

Replies

One solution would be to look at the audit database. It's not pretty, but there might not be any other way.

 

ClassMethod GetLoginService() As %String
{
    New $Namespace
    Zn "%SYS"
    
    Set tService = ""
    
    // Ensure that login events are being audited.
    Set tLoginEvent = ##class(Security.Events).Get("%System","%Login","Login",.tProps)
    If '$Get(tProps("Enabled")) {
        // Querying the audit DB probably won't do any good.
        Quit tService
    }
    
    // Warning: on systems with a lot of activity, this query might take a long time.
    // It might be worth filtering by recent UTCTimeStamp, assuming processes won't be that long-running.
    Set tRes = ##class(%SQL.Statement).%ExecDirect(,
        "select top 1 EventData from %SYS.Audit "_
        "where EventSource = '%System' and EventType = '%Login' and Event = 'Login' and PID = ? "_
        "order by UTCTimeStamp DESC, SystemID DESC, AuditIndex DESC",$Job)
    
    Set tHasResult = tRes.%Next()
    If (tHasResult) {
        Set tData = tRes.%Get("EventData")
        //NOTE: This makes assumptions about the format of EventData.
        //Particularly, that it looks something like:
        /*
        Service name:       %Service_Bindings
        Login roles:        %All
        $I:                 |TCP|1972|15396
        $P:                 |TCP|1972|15396
        */
        //
        Set tFirstLine = $Piece(tData,$c(13,10))
        
        //Presumably "Service name:" might be localized, but %Service_<something> would not be.
        Set:tFirstLine["%Service" tService = "%Service"_$Piece(tFirstLine,"%Service",2)
    }
    Quit tService
}

 

Note: if your application is using Caché security correctly, you'd probably need to define a privileged routine application to allow access to Security.Events and the audit database.

Hi Ed.

May I ask why do you need to do it?

Hi.

I want to create LOGIN^%ZSTART routine that works only for terminal connections. Here's the code.

And you need to do this why? I mean what is the end goal?

To show user some menu when they open Terminal?

Yes.

You can specify "Startup Tag^Routine" for this purpose:

Awesome. Didn't knew that it aplied only to terminal devices.

The subject made me smile :) "service"
 

Shouldn't we wrap the above method and expose these services via a RESTful "service" API and even encapsulate the inside system Caché ObjectScript API we have with such "service"?

So the above would look something like:

GET /server/system/v1/services

and then of course you'd have all the other methods implemented...