How to catch OS-COMMAND results in Progress-4GL? - command-line

I'm using the logging facilities, as described in this other post:
OUTPUT TO VALUE("C:\Temp_Folder\logfile.txt").
...
PUT UNFORMATTED "Start : Check-zones" SKIP.
...
OUTPUT CLOSE.
This is working fine.
Now I would like to add the results of an OS-COMMAND in the output file.
I've already tried the following: (putting the results in a newly to be created file)
OS-COMMAND NO-WAIT VALUE("WMIC printer get name, deviceID >> C:\Temp_Folder\Printers.txt").
This is working fine.
So, I know the command is working fine. However, the following is not working:
OS-COMMAND NO-WAIT VALUE("WMIC printer get name, deviceID >> C:\Temp_Folder\LogFile.txt").
This is obvious, because C:\Temp_Folder\Logfile.txt is locked for writing by the progress application, so the shell, opened by OS-COMMAND can't write to that file.
In order to overcome this, I would like to catch the results of the OS-COMMAND's results.
How can I do this?

Unfortunately back in the dark ages when os-command was designed, it was considered useful to suppress all errors.
You can either start a batch file and let that do some “guaranteed” output error handling, see https://knowledgebase.progress.com/articles/Article/21039
Or (since you are on Windows) you can use the .Net system diagnostics process class (which you will want to wrap in your own method or function to simplify use):
DEFINE VARIABLE oProcess AS System.Diagnostics.Process NO-UNDO.
DEFINE VARIABLE lcstderr AS LONGCHAR NO-UNDO.
DEFINE VARIABLE lcstdout AS LONGCHAR NO-UNDO.
oProcess = NEW System.Diagnostics.Process().
oProcess:StartInfo:FileName = "wmic.exe".
oProcess:StartInfo:Arguments = "printer get name, deviceID".
oProcess:StartInfo:CreateNoWindow = TRUE.
oProcess:StartInfo:UseShellExecute = FALSE.
oProcess:StartInfo:RedirectStandardError = TRUE.
oProcess:StartInfo:RedirectStandardOutput = TRUE.
oProcess:Start().
lcstdout = oProcess:StandardOutput:ReadToEnd().
lcstderr = oProcess:StandardError:ReadToEnd().
oProcess:WaitForExit().
lcstdout = lcstdout + oProcess:StandardOutput:ReadToEnd().
lcstderr = lcstderr + oProcess:StandardError:ReadToEnd().

Related

Having trouble conditionally moving files based on their names

I am trying to write a script that will auto sort files based on the 7th and 8th digit in their name. I get the following error: "Argument must be a string scalar or character vector". Error is coming from line 16:
Argument must be a string scalar or character vector.
Error in sort_files (line 16)
movefile (filelist(i), DirOut)
Here's the code:
DirIn = 'C:\Folder\Experiment' %set incoming directory
DirOut = 'C:\Folder\Experiment\1'
eval(['filelist=dir(''' DirIn '/*.wav'')']) %get file list
for i = 1:length(filelist);
Filename = filelist(i).name
name = strsplit(Filename, '_');
newStr = extractBetween(name,7,8);
if strcmp(newStr,'01')
movefile (filelist(i), DirOut)
end
end
Also, I am trying to make the file folder conditional so that if the 10-11 digits are 02 the file goes to DirOut/02 etc.
First, try avoid using the eval function, it is pretty much dreaded as slow and hard to understand. Specially if you need to create variables. Instead do this:
filelist = dir(fullfile(DirIn,'*.wav'));
Second, the passage:
name = strsplit(Filename, '_');
Makes name a list, so you can access name{1} or possibly name{2}. Each of these are strings. But name isn't a string, it is a list. extractBetween requires a string as an input. That is why you are getting this problem. But note that you could have simply done:
newStr = name(7:8);
If name was a string, which in Matlab is a char array.
EDIT:
Since it has been now claimed that the error occurs on movefile (filelist(i), DirOut), the likely cause is because filelist(i) is a struct. Wheres a filena name (char array) should have been given at input. The solution should be replacing this line with:
movefile(fullfile(filelist(i).folder, filelist(i).name), DirOut)
Now, if you want to number the output folders too, you can do this:
movefile(fullfile(filelist(i).folder, filelist(i).name), [DirOut,filesep,name(7:8)])
This will move a file to /DirOut/01. If you wanted /DirOut/1, you could do this:
movefile(fullfile(filelist(i).folder, filelist(i).name), [DirOut,filesep,int2str(str2num(name(7:8)))])

Substring is getting too less data

I want to grab lots of text content from a .sql file between a --Start and --End comment.
Whatever I do somehow I don`t get the substring method correctly to grab only the text within the --Start and --End comment:
text.sql
This text I want not
--Start
this text I want here
--End
This text I want not
This is what I tried:
$insertStartComment = "--Start"
$insertEndComment = "--End"
$content = [IO.File]::ReadAllText("C:\temp\test.sql")
$insertStartPosition = $content.IndexOf($insertStartComment) + $insertStartComment.Length
$insertEndPosition = $content.IndexOf($insertEndComment)
$content1 = $content.Substring($insertStartPosition, $content1.Length - $insertEndPosition)
$content = $content1.Substring(0,$content1.Length - $insertEndPosition)
It would be nice if someone could help me out find my error :-)
There's an attempt to use uninitialized variable in the code:
$content1 = $content.Substring($insertStartPosition, $content1.Length - $insertEndPosition)
The variable $content1 isn't initialized yet, thus the substring call goes haywire. When you run the code again, the variable is set - and results are even more weird.
Use Powershell's Set-StrictMode to enable warnings about uninitialized variables.
It's not the substring approach you are looking for, but I figured that I would toss out a RegEx solution. This will find the text between the --Start and --End on a text file. In this case, I am grouping the matched text with a named capture called LineYouWant and display the matches that it finds. This also works if you have multiple instances of --Start--End blocks in a single file.
$Text = [IO.File]::ReadAllText("C:\users\proxb\desktop\SQL.txt")
[regex]::Matches($Text,'.*--Start\s+(?<LineYouWant>.*)\s+--End.*') | ForEach {
$_.Groups['LineYouWant'].Value
}

How to retrieve maillist into one field?

I want to retrieve the mail list into one field and display the data retrieved.
The mail list is represented as an array, and I want all data to be in one field.
define variable i as integer no-undo.
define variable cmmt as longchar no-undo.
cmmt = " ".
for each cd_det no-lock
where cd_ref = "test1"
and cd_type = "EL":
do i = 1 to extent(cd_cmmt):
cmmt = cmmt + cd_cmmt[i].
end.
disp cmmt.
end.
I tried the above code, but it doesn't display. Instead, test1 record contains 2 mails (gangadhar.pichika-external#gemalto.com,balkrishna.talapalliwar-
external#gemalto.com), but I didn’t get that data in cmmt.
A LONGCHAR variable cannot be displayed (unless using a large editor widget). Try to DISPLAY STRING(cmmt).

Excel Export as Text Using Progress 4GL

I need help with an Excel Export. I'm trying to export a column as text using Progress 4GL. I need numbers in the column which have a leading "0" that excel keeps deleting when opens.
I tried it with using STRING function to make the variable to be String before it goes to export. It did not work. Is there any other way to export with leading 0s?
I assume that you are saving the file in progress as a CSV and when the file is opened in Excel it loses the leading 0.
When outputting the string you can enclose it as follows so that excel reads it in as a string.
put unformatted '="' string("00123") '"'
If you're writing directly to Excel, you can put a ' character at the beginning of the number, and then Excel will interpret it as number formatted with text.
You can see it in action here:
def var ch-excel as com-handle no-undo.
def var ch-wrk as com-handle no-undo.
create "Excel.Application" ch-excel no-error.
ch-excel:visible = no no-error.
ch-excel:DisplayAlerts = no no-error.
ch-wrk = ch-excel:workbooks:add.
ch-excel:cells(1,1) = "'01".
ch-wrk:SaveAs("c:\temp\test.xlsx", 51, "", "", false, false, ) no-error. /* 51 = xlOpenXMLWorkbook */
ch-excel:DisplayAlerts = yes.
ch-excel:quit().
release object ch-wrk.
release object ch-excel.
Since I've be using excel to generate reports for a while, I've create a small lib that generates an excel based on a temp-table definition, and I think it might be helpful, you can check it up at: https://github.com/rodolfoag/4gl-excel
When you import manually into excel select the columns as TEXT and not GENERAL, then the leading zero will not dissapear
You can set the format of the cell, something like this:
h-excel:Range("A12")::numberformat = FILL("0",x).
where x would be the length of the variable you want to insert.

CATIA macro (Input box not working)

Help My Balloon finding macro is not working with input box, it works only when i manually add the balloon number.. please tell me what i m missing ...Ferdo m expecting you
Language="VBSCRIPT"
Sub CATMain()
Set drawingDocument1 = CATIA.ActiveDocument
Set selection1 = drawingDocument1.Selection
result = InputBox("Ballon Number ?", "Title") 'The variable is assigned the value entered in the InputBox
selection1.Search "CATDrwSearch.DrwBalloon.BalloonPartName_CAP= result ,all"
End Sub
I don't know what you are doing but the last line looks wrong. I don't know what the docs are for your function but you are passing the string result rather than the value of the variable result because it is in quotes. Assuming your line is otherwise right ...
selection1.Search "CATDrwSearch.DrwBalloon.BalloonPartName_CAP= " & result & ",all"