Is there a way to print to output console? (twincat3) - twincat

Is there a way to print to output to console like debug.print() in VB.NET using structured text? (twincat3)

You can send messages through ADS commands from TwinCAT code. The function is called ADSLOGSTR. There also also own functions for DINT and REAL, but the STRING function of course can be used with anything.
The function has three inputs:
msgCtrlMask
Mask that describes the message type
Types can be found here
For example, to show warning message and save it to Windows log: msgCtrlMask := ADSLOG_MSGTYPE_WARN OR ADSLOG_MSGTYPE_LOG
To show just a Windows MessageBox: msgCtrlMask := ADSLOG_MSGTYPE_MSGBOX
msgFmtStr
The message to be shown as STRING
A %s can be used to add parameter without CONCAT functions. See the last parameter.
strArg
A STRING that is replaces the %s in previous string.
Here is an example the probably is what you need:
IF test THEN
ADSLOGSTR(
msgCtrlMask := ADSLOG_MSGTYPE_HINT,
msgFmtStr := 'Test message. Parameter is %s',
strArg := 'ABC'
);
test := false;
END_IF
When you set the test true, and call the function, you will see this on your Visual Studio error list. Note that it is not written to console.
I often use error messages (ADSLOG_MSGTYPE_ERROR) because I hide notes and warnings quite often and the I wouldn't notice my own entries. Other good way is to add the entry to the Windows log, if you want to log something to be seen later.

Related

How to debug a Go function returning multiple values in IntelliJ?

Suppose we are debugging some Go code, and somewhere in an external dependency we encounter this line:
return json.Marshal(foo)
We want to set a breakpoint and use IntelliJ's "Evaluate Expression" to inspect the JSON being produced. However, this doesn't work:
If we evaluate the expression json.Marshal(foo), we only get to see the byte array.
Evaluating string(json.Marshal(foo)) doesn't work because json.Marshal returns two values, the byte array and an error.
There is no way in Go to access one of the return values directly.
So how can I use "Evaluate Expression" to achieve my goal of just printing the produced JSON string when I'm not able to change the underlying source code?
you can print the returned bytes as a string
bytes, err := json.Marshal(foo)
// check error here
fmt.Println(string(bytes))
update based on comments
You can't change the byte slice in the debugger to a string without changing the source code.

Scripting Word from vbs

I'm trying to get Word to fill in cells in a table. The script works when run as a macro from within Word, but fails when saved as a .vbs file and double-clicked, or run with wscript. This is a part of it.
set obj = GetObject(,"Word.Application)
With obj
With .Selection
MsgBox .text
If (.Information(wdWithInTable) = True) Then
.Collapse Direction:=wdCollapseStart
tCols = .Tables(1).Columns.Count
tRow = .Information(wdStartOfRangeRowNumber)
tCol = .Information(wdStartOfRangeColumnNumber)
For I = 2 To 5
.Tables(1).Cell(tRow, I).Range.Text = "fred" & Str(I)
Next
` now make new row
For I = 1 To tCols - tCol + 1
.MoveRight unit:=wdCell
Next
End If
End With
End With
I have three problems. First, it won't compile unless I comment out the .Collapse and .MoveRight lines. Second, although the MsgBox .text displays the selected text, I get "out of range" errors if I try to access any .Information property.
I'm sure I'm missing something very simple: I usually write software for Macs, and I'd do this using AppleScript. This is my first attempt at getting anything done under Windows.
VBScript and VBA are different languages.
They are a bit similar, but not very. Moreover, VBScript is not like AppleScript; it doesn't let you easily interface with running programs.
The interfaces you'll get from VBScript can behave subtly differently in VBA and VBScript. However, I think you've got two problems here:
:= is invalid syntax in VBScript; you'll need to find an alternative way of calling the function. Try just using positional arguments.
You've no guarantee that this will open the expected file; there could be another instance of Word that it's interacting with instead.
Since your code is not running within the Word environment it would require a reference to the Word object library in order to use enumeration constants (those things that start with wd).
VBScript, however, cannot work with references, which means the only possibility is to use the long value equivalents of the enumerations. You'll find these in the Word Language References. Simplest to use is probably the Object Browser in Word's VBA Editor. (In Word: Alt+F11 to open the VBA Editor; F2 to start the Object Browser; type in the term in the "Search" box, click on the term, then look in the bottom bar.)
The code in the question uses, for example:
wdWithInTable
wdCollapseStart
wdStartOfRangeRowNumber
wdStartOfRangeColumnNumber
wdCell
The reason you get various kinds of errors depends on where these are used.
Also, VBScript can't used named parameters such as Unit:=. Any parameters must be passed in comma-delimited format, if there's more than one, in the order specified by the method or property. If there are optional parameters you don't want to use these should be left "blank":
MethodName parameter, parameter, , , parameter

Delphi tmediaplayer don't play mp3 file with "strange" cover image embedded

I have developed a mp3 player with Delphi (XE) using the BASS library.
Due to certain reasons, I want to remove the BASS libraries and want to use the TMediaPlayer component in Delphi (also want to "move" the project to Delphi 10 Seattle).
Now I found out that some of my mp3 files have a "strange" jpg image embedded.
Means, that the Delphi components run into an error due to the image.
With long time debugging I can say the following:
try
mplMain.FileName := CurrentSong;
progbSong.Max := mplMain.Duration;
lblDuration.Text := DurationToString(mplMain.Duration);
PlayClick(Self);
except
on E: Exception do
begin
FMX.Dialogs.MessageDlg('Cannot play song: ' + CurrentSong + #10 + #13 +
'Reason: ' + E.Message,
TMsgDlgType.mtWarning, [TMsgDlgBtn.mbOK], 0,
procedure(const AResult: TModalResult)
begin
MediaNext;
end
);
end;
end;
This line:
mplMain.FileName := CurrentSong;
causes the problem.
Diving deeper in debugging it comes to here:
FMX.Media library:
procedure TMediaPlayer.SetFilename(const Value: String);
...
FMedia := TMediaCodecManager.CreateFromFile(FFileName);
...
At the end it ends up in FMX.Media.Win:
constructor TWindowsMedia.Create(const AFileName: string);
...
HR := FGraphBuilder.RenderFile(PChar(AFileName), nil);
...
When the line
HR := FGraphBuilder.RenderFile(PChar(AFileName), nil);
is called, in debug mode, the program just returns to the IDE.
In runtime mode, nothing happens. No error message, just "nothing".
As you can see, I wrapped the related line into a try...except block, but no error is raised. The program/player doesn't continue.
That's very bad for me, because I wanted to catch this "special case" and log the affected mp3 files to a logfile so that I can change the embedded image.
I found out that it is only caused by some images. Maybe they are "somehow corrupt", but shown in all other players.
When I remove the image and embed a "new" one and save the file, everything is fine and the TMediaPlayer can play the file.
How can I catch this certain kind of "error" to get the list of affected files?
I got it managed now.
Only in debug mode the application/player is exited without any thrown error and I find myself back in the IDE.
During runtime the try...except block works, when I chose an "affected file" manually. For the case that one file is played ("good one") and the next file is a "bad one", I had to change my "MediaNext" procedure. In this procedure I also had a try...except block when the filename was associated to the TMediaPlayer, but I just had set a bool variable for further use and didn't "jump" to the next file.
The code just was:
try
mplMain.FileName := CurrentSong;
except
on E:Exception do
SongNotPlayable := true;
end;
Here I can implement a routine to log the affected mp3 files into a logfile and then jump to the next file (if exists). :-)
Thanks again to all!

gsdll.init_with_args parameters for Win32 display device

I intent to use gsdll32 to display postscript in a Win32 window (not ghostview).
I need help with the parameters needed by gsdll_init_with_args.
The function immediately returns error -0x12 or -0x100.
I tried several parameter combinations in various sequences:
-sDisplayFormat=16#030804
-dDisplayHandle="1234"
-dDisplayResolution=96
-sDEVICE=display
postscriptfile.ps
As a second question:
What should the parameters be if I want to pipe in the postscript data programmatically ?
Examples would be nice.
Seppe
The supplied source code for Windows uses gs_dll_init_with_args(). If you look in /ghostpdl/psi/dwmain.c, function new_main(int argc, char *argv) then at about line 328 you can see the call happening.
You can follow this through in a debugger to see what the arguments look like (they get sanitised before arriving here). Get it to work the way you want on the command line, then break here with those arguments and you can see what your own code should be providing.
To send the data buffer-by-buffer, we don't have an example. However, you start by calling gsapi_run_string_begin(), then repeatedly calling gsapi_run_string_continue() until you exhaust the data, then call gsapi_run_string_end(). Obviously you will have to check the return code to see if an error occurred.
Finally; please check the AGPL to be sure you can conform to the license restrictions.

DSSetParam -4 error when filling a parameter with a routine

I'm building a Sequence job that contains a UserVariables activity (ParamLoading) and a Job activity (ExtractJob), in that order. ParamLoading creates 4 user variables and invokes a routine to fill each one with the correspondng value, then invokes ExtractJob pasiing it the parametes previously loaded.
ParamLoading invokes a server routine (GetParams) which simply executes a shell script (ShellQuery) and captures the result; that shell script executes an SQL query against an Oracle database and prints the result on screen.
As far as tests go, ShellQuery works as expected and GetParams returns the expected value. But when GetParams is invoked from the sequence job (no matter if it's in ParamLoading or ExtractJob) the job fails with the following error:
Test2..JobControl (#JOB033_TBK_026_EXT_PTLF): Controller problem: Error calling DSSetParam(RUTA_ORIGEN), code=-4
[ParamValue/Limitvalue is not appropriate]
I've checked data types, parameter names, all, without success or even a message saying what might be happening.
Code of ShellQuery:
value=$(sqlplus -s $1/$2#$3/$4 <<!
set heading off
set feedback off
set pages 0
select param_value from cfg_params where filter='$5' and param_name='$6';
!)
echo $value
Code of GetParams:
Call DSExecute("UNIX", Ruta_Programas:"getparams.sh ":Username:" ":Password:" ":Server:" ":ServiceId:" ":Filtro:" ":Parametro, Output, SystemReturnCode)
Ans = Output
Return(Ans)
What are you returning as values from GetParams?
Calling a function from a sequence expects an integer value back and any non-zero digit returned is evaluated as an error.
As a test, try changing the return value from the routines to values 0-4.
Solved. For those struggling with a similar problem, GetParams was returning the captured value from ShellQuery adding a special character called "field delimiter", and given that the character is a 254 in ASCII, any job receiving the parameter would complain of an invalid value, which was the error.
Changing the routine to the following solved it:
Call DSExecute("UNIX", Ruta_Programas:"getparams.sh ":Username:" ":Password:" ":Server:" ":ServiceId:" ":Filtro:" ":Parametro, Output, SystemReturnCode)
Ans = EReplace(Output, #FM, "")
Return(Ans)
Thanks to Matt Calderon for providing a clue for solving.

Resources