How to write output to a file on a Unix server using Intersystems Caché? - intersystems-cache

I'm trying to execute a query in Caché and output the results to a file on a Unix server, but I'm having trouble finding the right commands.
I tried the following:
%SYS>s rs=##Class(%ResultSet).%New()
%SYS>s rs.ClassName="%SYS.Namespace"
%SYS>s rs.QueryName="List"
%SYS>s sc=rs.Prepare(rs.QueryName)
%SYS>s sc=rs.Execute()
%SYS>s fs=##Class(%IO.FileStream).%New()
%SYS>d fs.Open("/myDir/outputDir/test_filestream.txt")
%SYS>while rs.Next(){d fs.Write(rs.Nsp)}
%SYS>d fs.Close()
%SYS>s sc=rs.Close()
I didn't get any errors when I ran the above, but I also didn't get any output. I would like to have the file created if it doesn't already exist or overwrite it if it does. Is that possible with Caché commands or is server scripting the only way to accomplish this?
I'm having to do this all from the command line on the server so if easier functionality exists using a Caché utility like Caché Studio or Terminal, I don't have that luxury.
Thanks.

You can try this code
#; you can use simple call
s rs=##Class(%ResultSet).%New("%SYS.Namespace:List")
#; for query it does not need
#;s sc=rs.Prepare(rs.QueryName)
s sc=rs.Execute()
#; better to use %FileCharacterStream or %FileBinaryStream
s fs=##Class(%FileCharacterStream).%New()
s fs.Filename="/home/daimor/test_filestream.txt"
while rs.Next(){ d fs.WriteLine(rs.Nsp) }
#; important things, saving stream. Close don't need now
d fs.SaveStream()
#; and we can see, what we saved
d fs.OutputToDevice()
And you can use NBStudio for editing existing routines or clasess in Linux, but you can't create new routines yet.

I figured it out using the following:
%SYS>s rs=##Class(%ResultSet).%New()
%SYS>s rs.ClassName="%SYS.Namespace"
%SYS>s rs.QueryName="List"
%SYS>s sc=rs.Prepare(rs.QueryName)
%SYS>s sc=rs.Execute()
%SYS>s outFile="/myDir/outputDir/test_filestream.txt"
%SYS>OPEN outFile:"WNS" ; open in Write, New (overwrite if it exists in Windows/Unix, Stream mode)
%SYS>while rs.Next(){USE outFile WRITE rs.Nsp, !}
%SYS>CLOSE outFile
Apparently, you can also use the $ZF utility, but I'm not 100% clear on the syntax.

Related

WinDbg scripting - how to delete a file?

I'm working with an existing framework of WinDbg scripts that go through a series of test scripts Test1.txt, Test2.txt, etc., which are generated by C++ code and which output results.
For example a chunk of one of the test scripts would be,
.if (($spat(#"${var}","18300.000000")==1))
{
.logappend C:\Tests\TestResults.txt
.printf "TestNumber=\t1\tExpected=\t18300.000000\tActual=\t%.6f\t******PASSED******\n",poi(poi(#$t2+#$t6)+0x10)
.logclose
}
I'm trying to add functionality that will create a file whose name displays the current # of the test being run, so that users can see their progress without needing to open a file.
My thought process was that I would set up the script generator, so that at the start of Test #N, it would add a line to the script to create a file 'currentlyRunningTestN.txt', and at the end of Test #N, it would add a line to the script to delete that file. However, I don't see any delete function in the WinDbg meta command glossary: https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/meta-commands, or in the list of supported C functions like printf. Am I just missing something, or is deleting files not supported by WinDbg (or equivalently renaming files, which would also serve my purpose?) If deleting/renaming don't work, is there another way to achieve the functionality I'm looking for?
With the .shell command, you can execute any DOS-like command. Although I never tried deleting a file, it should be possible.
As you may have noticed, WinDbg scripting does not always work on first attempt, please make sure your scripting will not result in a big data loss on your customer's PC whilst deleting files.

Executing Perl script inside IntelliJ Idea

I'm trying to use IntelliJ Idea to work on a perl script. I installed the perl plugin for IDEA as well as Strawberry Perl for Windows (10).
The syntax highlighting and other features work, but this is what happens when I try to run the program:
I'm a beginner at perl, so I'm still just using command line stuff and ASCII graphics. I was hoping to simply run, test, and debug my perl programs in IntelliJ, but the print statement isn't putting anything in this dialog when perl runs...
I can still type stuff in the above image where the cursor is, and typing the wrong stuff can throw errors as it is supposed to. So <STDIN> seems to be properly mapped, but <STDOUT> is not? Or is something else wrong?
If I copy the command that it shows it is running to cmd, it works perfectly:
So is there a way to configure intellij to get <STDOUT> in this dialog? Any help would be appreciated.
Now, following Chankey's answer, I've made a test script, and that one works:
Maybe the problem is that I imported the perl file from an external source, and IntelliJ doesn't realize it is a script, or something like that? But if I copy the code into the new file, it doesn't work either...
The test.pl had one difference: use warnings FATAL => 'all'; instead of use warnings;. When I try this, it works until I type a string where numeric input is expected, and then prints a whole bunch of what it should have been printing all along as it quits the program:
Again, the output works fine in cmd, so I think this is an issue with IntelliJ. Any ideas? Maybe the # symbols are creating issues? Something else? If anyone uses IDEA for windows and wants to toy around with my code, it's available on github.
Works fine for me. Below are the steps:
Create a project
Right click on project and select New, then select Perl5 file
Give a name to file and select Script from dropdown
Write your script, save it
Press CTRL+SHIFT+F10
Provide some data as user input then press Enter
Output:
If it still does not work for you then perhaps you have not setup your Perl properly.
Go to File->Project Structure and add perl to Project SDK.
As per your screenshot I can see that you are using absolute path for perl.exe. That means you have not added perl to your PATH. That seems to be the issue why IntelliJ is not finding it to execute your script.
Do
set PATH=C:\Strawberry\perl\bin;%PATH%
If that also doesn't fix the issue for you then go through the wiki page of Camelcade plugin. Author has provided step by step instructions there on how to setup this plugin.
Try adding:
$| = 1;
...to the top of your script. Perl buffers stdout, adding $| = 1; causes the buffer to flush immediately and should display output from your print statements in the IntelliJ debug console.
See also:
perl $|=1; What is this?

ESS[SAS] Submit region not working as expected -- each submission starts a new session

Specs: SAS 9.3, GNU emacs 23.4.1 (2012-06-05), and what I think is kind of an old version of ESS (sometime in 2001 maybe?). Unix -- I think SunOS 5.10.
I'm a fairly new emacs user and a very new user of ESS[SAS]. I have noticed that code which works when submitted as an entire file will not work when I submit it region by region. Here is an example:
libname mylib "/.";
data temp; set mylib.temp; run;
Assume that I have a directory as specified in libname and there is a SAS dataset called temp in it -- my code works properly when I submit the whole thing, but if I run just the first line and then the second, it tells me that "mylib" is not defined.
Based on the behavior of the log files -- the second submission creates a log file that overwrites the first -- I think what is going on is that it's starting a new SAS session with each submission. Why might it be doing this? (ESS does not do that with R code -- I can run a snippet to define a variable and then that variable stays defined.) I find I make fewer programming errors if I test things incrementally rather than running all my code in batch mode, and the GUI for SAS in unix leaves something to be desired, so I would really like to find a fix to this.
The only other clue I have is a pair of warnings I get on every submission:
NOTE: Unable to open SASUSER.REGSTRY. WORK.REGSTRY will be opened
instead.
NOTE: All registry changes will be lost at the end of the session.
WARNING: Unable to copy SASUSER registry to WORK registry. Because of
this,you will not see registry customizations during this session.
NOTE: Unable to open SASUSER.PROFILE. WORK.PROFILE will be opened
instead.
NOTE: All profile changes will be lost at the end of the session.
I googled those warnings separately and found they're commonly associated with a corrupt profile, but unfortunately the recommended fix did not fix anything (after deleting the iffy profile, it just restored itself and the error persisted). I am not sure whether this is related or not.
I realize this question might be out of scope for stackoverflow; if it is, a redirect to a more appropriate forum would be much appreciated.

Can I head a file in tramp?

Say I want to tramp a remote file in Emacs. If the file is huge, this could take a long time.
Can I tell Emacs/Tramp to only head or display/retrieve part of it?
You can open the directory that the file is in, and type M-! head my_file. The command gets executed over SSH.
The function insert-file-contents takes optional arguments that specify which portion of the file to insert, and from a quick glance it seems like Tramp tries to extract only the parts it needs. You'd need to write an interactive function on top of that, though.

how to run VBA macro from perl code

I am new to perl & i am trying to write a module which would run a excel macro on a already open excel sheet. there is a code sniplet that describes how to run a macro from another excel sheet but i want the macro code as a subroutine in the same file. How to implement that? Can any one help?
use strict;
use warnings;
use Win32::OLE;
my $excel= Win32::OLE->new('Excel.Application')or die "Could not create Excel.Application!\n;
$excel->Workbooks->open( 'C:\Users\Me\Documents\Book1.xlsx' );
$excel->run( 'Book1!Macro1' );
# Here i want that Macro1 as sub in this file itself & not from book1
$excel->quit;
I don't really think you can do this. You would need to access
$workbook->VBProject->VBComponents
but then the typical way to pass create a macro on the fly is to call the VBComponents collection's AddFile, AddFromTemplate or Import method which all require paths to files that Excel will read itself. It's not like it's an extension of Perl and will accept an open file stream as well.
Of course, you can always write the machinery to take a in-script string, dump it out to a temporary file and send that file name to Excel. However, since Microsoft has greatly stepped up its paranoia, I wonder how many security hurdles you will need to clear to get Excel to run a macro from a temp file directory.
After you get this loaded it's simply a matter of $xl->run( 'Bookname!Macro' ). But I think the protections against attacks are bound to hinder your doing this.
Update:
Yeah, I just tried something along these lines and got "Programmatic access to Visual Basic Project is not trusted". Like I said, expect a lot of hurdles, if not complete failure.
However, you can work around that with this advice.
Actually, it turns out I was wrong, the code below allows you to add behavior to a code module.
my $prj = $wb->VBProject;
my $mod = $prj->VBComponents->Item( 'ThisWorkbook' )->CodeModule;
$mod->addFromString( <<"END_VB" );
Public Sub Doodad
MsgBox( "I am Doodad! Hear me roar!" )
End Sub
END_VB
However when I did this:
$excel->Run( $wb->Name . '!Doodad' );
I got this:
Cannot run the macro 'Book1!Doodad'. The macro may not be available in this
workbook or all macros may be disabled.