Eduard Lebedyuk · Oct 7, 2017 go to post

Compare what user entered to the specific value. If they mismatch  - ask again. Also there are several utility methods in %Prompt class for number/yes-no/etc input:

  • GetNumber
  • GetString
  • GetYesNo
  • GetArray - Prompt for a number or entry in a displayed menu. Returns the selected item.
  • GetMenu - Prompt for a number in a displayed menu.
  • GetMore - Prompt for More or Quit.

For example:

do ##class(%Prompt).GetYesNo("Enter Yes or No:", .result)

User can input only Yes (Y) or No (N). result variable would hold 1 or 0.

You can also check %Prompt code and write something based on that.

Eduard Lebedyuk · Oct 7, 2017 go to post

This can be done with SQL procedure:

Query SomeQuery() As %SQLQuery
{
SELECT ID || SomeClass.GetParam('SomeClass', 'SOMENAME') FROM Table
}

ClassMethod GetParam(class, param) As %String [ CodeMode = expression, SqlProc ]
{
$parameter(class, param)
}
Eduard Lebedyuk · Oct 5, 2017 go to post

Turns out Java Gateway can instantiate objects and call their methods.  Here's a rewrite of the above code, but all connecting is done in constructor:

package com.isc.rabbitmq;

import com.rabbitmq.client.*;

public class Wrapper {
    private final Channel _channel;

    private final String _queueName;

    public Wrapper(String hostName, String queueName)  throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost(hostName);
        Connection connection = factory.newConnection();
        _channel = connection.createChannel();
        _channel.queueDeclare(queueName, false, false, false, null);
        _queueName = queueName;
    }

    public void sendMsg(byte[] msg) throws Exception {
        _channel.basicPublish("", _queueName, null, msg);
    }

    public int readMsg(byte[] msg) throws Exception {
        boolean autoAck = true;
        GetResponse response = _channel.basicGet(_queueName, autoAck);
        int len = 0;
        if (response == null) {
            // No message retrieved.
        } else {
            AMQP.BasicProperties props = response.getProps();
            len = response.getBody().length;
            System.arraycopy(response.getBody(),0,msg,0,len);
        }
        return len;
    }

}
Eduard Lebedyuk · Sep 30, 2017 go to post

If you know all possible arguments just create a wrapper method that accepts all arguments and job that.

Eduard Lebedyuk · Sep 30, 2017 go to post

If you want to execute a class query and get a result set you can directly call <Query>Func method and get a new %SQL result set:

set rs = ##class(Config.MapGlobals).ListFunc("ENSDEMO","*")
while rs.%Next() {
  w rs.Name,!
}

The only case where you can't use that if you need to choose the query at runtime.

Eduard Lebedyuk · Sep 29, 2017 go to post

Yes, there's no way to print multiple files from js with one dialogue.

You can merge all PDFs on server and print that.

I suppose you can also search for/develop browser extension to get around this particular feature of  browser security model, but that's probably more work than merging.

Eduard Lebedyuk · Sep 29, 2017 go to post

You can use deprecated %Net.RemoteConnection:

Set rc=##class(%Net.RemoteConnection).%New()
Set Status=rc.Connect("127.0.0.1","SAMPLES",1972,"_SYSTEM","SYS")
Write Status

If you don't know login/pass just use _SYSTEM/SYS defaults - you'll get either Access Denied error upon successful connection or TCP error.

Alternatively try to open TCP device to the target:

ClassMethod Test(host = "localhost", port = 1972, timeout = 10) As %Boolean {
      set oldIO = $IO
      set io = "|TCP|1" _ port
      open io:(/Hostname=host:/Port=port):timeout
      set success = $Test
      use oldIO
      close io
      quit success
}
Eduard Lebedyuk · Sep 29, 2017 go to post

It's in the docs:

The query may contain parameters represented by ? characters within the query. The values of any parameters are supplied via the Execute method.

Eduard Lebedyuk · Sep 29, 2017 go to post

Prepare doesn't require arguments, only execute does.

You can prepare query once and then execute it several times with different arguments.

Eduard Lebedyuk · Sep 29, 2017 go to post

I don't think there's an option to export inc files from this dialog.

If you often need to move production between environments writing your own deploy script can save you time on clicking through the UI.

Eduard Lebedyuk · Sep 29, 2017 go to post

You can use pure javascript to do that:

function PrintAll() {
    var files = ["file1.pdf", "file2.pdf", "file3.pdf"];
    for (var i = 0; i < files.length; i++) {
        var newWindow = window.open(files[i], "print");
        newWindow.print();
        newWindow.close();
    }
}
Eduard Lebedyuk · Sep 29, 2017 go to post

Your options are:

  • Try to compile crypt only under win x64 (libc as a whole can't be compiled under windows, but maybe you can compile crypt module)
  • PHP doc you referenced states that PHP has it's own fallback implementation when OS does not provide crypt implementation. Check where does PHP search for crypt implementation on windows - it's probably some C lib and call it too
  • Write the algorithm yourself, here's  a good guide on that
  • Use another more secure hashing algorithm, for example SHA-512
Eduard Lebedyuk · Sep 28, 2017 go to post

There is also CNA project - it provides an interface for using native C-compatible shared libraries without anything but Caché ObjectScript code. CNA is a wrapper for libffi. CNA consists of native library (libcna) and Caché class (CNA.CNA). It is a wrapper around $zf functions (you can use them directly too).

Here's the code to call crypt using CNA:

Class CNA.Crypt
{

/// do ##class(CNA.Crypt).Crypt()
ClassMethod Crypt(key = "2Ggaobjb", salt = "$1$1a2b3c4d$")
{
    set cna = ##class(CNA.CNA).%New("/InterSystems/forCLM/libcna.so") ; Creates object of CNA.CNA class.
    do cna.LoadLibrary("/lib/x86_64-linux-gnu/libcrypt-2.23.so")      ; Loads C standard library (crypto) in CNA

    set keyPointer = cna.ConvertStringToPointer(key) ; Converts the string into char array, and saves pointer to the first element

    set saltPointer = cna.ConvertStringToPointer(salt)

    set argTypes = $lb(cna.#POINTER, cna.#POINTER)   ; function argument types
    set result = cna.CallFunction("crypt",          ; Passes the name of the function,
                                cna.#POINTER,       ; type of return value,
                                argTypes,         ; list of argument types,
                                keyPointer, saltPointer)           ; and comma-separated arguments */    
    write cna.ConvertPointerToString(result), !      
   
    do cna.FreeLibrary()
}

}

Sample output:

do ##class(CNA.Crypt).Crypt()
>$1$1a2b3c4d$Y5tt50CQ12xW2saeYnI43.

do ##class(CNA.Crypt).Crypt("ABC", "$1$12345678$") 
>$1$12345678$0QgUhxfT5h1pvtkhF5pzx/ 
Eduard Lebedyuk · Sep 27, 2017 go to post
Write ##class(Security.Resources).Export("C:\Resources.xml")
Write ##class(Security.Resources).Import("C:\Resources.xml")
Eduard Lebedyuk · Sep 27, 2017 go to post

"Print" SVG to file or stream. It depends on what you want to do with the image.

For example opening this popup as a separate tab and capturing all web page with auto-scroll would yield a complete bp image.

 

If you're talking about nested whiles and such, I don't think there's an easy way  to expand them all into one diagram.

Eduard Lebedyuk · Sep 27, 2017 go to post

This condition is insufficient for multi-level inheritance (C is a subclass of B, B is subclass of A. So C is subclass of A but Super wouldn't show this information). More on that in here.

Eduard Lebedyuk · Sep 27, 2017 go to post

SMP -> Ensemble -> Build -> Business Processes -> [Open your BP] -> Show print friendly version of diagram -> Print that page.

EnsPortal.SVG.SVGPrint.zen page outputs the SVG image so if you need you can subclass it to print SVG to file or inject into some document.

Eduard Lebedyuk · Sep 26, 2017 go to post

SQL gateway connections settings are stored in %SQLConnection class and the corresponding %Library.sys_SQLConnection table. Note that passwords are stored in encrypted form, so you can't get them as a plaintext. Also password may be stored as a part of system ODBC configuration, so there would be no password at all stored in Caché.

Eduard Lebedyuk · Sep 22, 2017 go to post

Assuming  you're on 2016.2+:

set payload = "{""profile_id"":""9XOzzcI8NfSUjxAhEt0cTLRejwmp6HPi"",""biometrics"":[{""timestamp"":""2017-05-17T13:45:40"",""utc_offset"":""+02:00"",""resting_heartrate"":120.0,""spo2"":98.0,""activity_id"":""591c540aac8f295479ee14ce""}]}"
set obj = {}.%FromJSON(payload)
write obj."profile_id"
>9XOzzcI8NfSUjxAhEt0cTLRejwmp6HPi
write obj.biometrics.%Get(0).timestamp
>2017-05-17T13:45:40
Eduard Lebedyuk · Sep 21, 2017 go to post

It's really not.

You can have "On Demand" task and call it from %ZSTART. This way you can have task scheduler reporting and execute task only when it's required.

Eduard Lebedyuk · Sep 20, 2017 go to post

Is there any reason to use Task Manager instead of %ZSTART?

 

Anyway you can have a task that runs hourly, and checks for existence of ^CacheTemp.MyTask global. If the global does not exist, set it and execute the task. If the global exists - quit. Since restart wipes CacheTemp, the global wouldn't exist on startup.

Eduard Lebedyuk · Sep 20, 2017 go to post

What if I have extra properties such as InsertTime in the Test.cvs class?

What about them? When you call %SQL.Util.Procedures:CSVTOCLASS you need to specify rowtype, corresponding to your CSV structure. If you have InsertTime property you need to reflect it and any other properties CSV has in your rowtype.