Generate Output to commandline - clarion

I have a programm thats run on commandline.
I call it like: myexe.exe parameter.
Now I want to output a message to my commandline (eg. success or error)
I tried:
return('there is an error') --> noting is displayed
Halt(0,'there is an error') --> a Windows-message is displayed
how can I output a message or perhaps some other data?

Here is an example that uses AttachConsole, GetStdHandle and WriteConsoleA and in particular, does it from a Clarion GUI apptype rather than CUI like in a different example.
PROGRAM
HANDLE EQUATE(UNSIGNED)
DWORD EQUATE(ULONG)
BOOL EQUATE(BYTE)
VOID EQUATE(LONG)
LPVOID EQUATE(ULONG)
LPDWORD EQUATE(ULONG)
ATTACH_PARENT_PROCESS EQUATE(-1)
STD_OUTPUT_HANDLE EQUATE(-11)
MAP
MODULE('API')
AttachConsole(DWORD dwProcessId),BYTE,PASCAL,RAW
FreeConsole(),BYTE,PROC,PASCAL,RAW
GetStdHandle(DWORD nStdHandle),LONG,PASCAL,RAW
WriteConsoleA( |
HANDLE hConsoleOutput, |
VOID lpBuffer, |
DWORD nNumberOfCharsToWrite, |
*LPDWORD lpNumberOfCharsWritten, |
LPVOID lpReserved),BYTE,PASCAL,RAW,PROC
END
WriteLine PROCEDURE(STRING pMessage)
END
Window WINDOW('Test WriteConsole'),AT(,,101,43),GRAY,FONT('Microsoft Sans Serif',8)
BUTTON('Write To Stdout'),AT(17,12),USE(?ButtonTest)
END
CODE
Open(Window)
ACCEPT
IF Event() = EVENT:Accepted AND Accepted() = ?ButtonTest
WriteLine('Hi!')
END
END
WriteLine PROCEDURE(STRING pMessage)
conHandle HANDLE
outLen LPDWORD
bufferStr &CSTRING
CODE
bufferStr &= New(CSTRING(Len(pMessage)+2))
bufferStr = pMessage & '<10><0>'
IF AttachConsole(ATTACH_PARENT_PROCESS)
conHandle = GetStdHandle(STD_OUTPUT_HANDLE)
WriteConsoleA(conHandle,Address(bufferStr),LEN(bufferStr),outLen,0)
FreeConsole()
END
Dispose(bufferStr)
RETURN

Related

How to get WM_COPYDATA in python

i'm trying to do (what should be) some minor work with win32. I basically just need to send a message and wait for a response.
I need the HWND or window handle of my python script/program to actually send the message.
I need to receive a WM_COPYDATA message from the end program.
I'm able to find the HWND of my python program with a script provided by ColonelFai1ure#0706 on the python discord server:
#gets the HWND of the active window
def getActiveWinID():
print(ctypes.windll.user32.GetForegroundWindow())
return ctypes.windll.user32.GetForegroundWindow()
Although I have to keep my PyCharm instance as the active window, it works fine, i'm able to send a message with the HWND now!
So I send a message with:
import ctypes
import subprocess # can be async
from ctypes import wintypes
from ctypes import *
with subprocess.Popen(r"C:\Users\lafft\Downloads\2021-04-11\3.35\ProxyTool\ProxyAPI.exe "
r"-changeproxy/US/NY/'New York' -citynolimit -proxyport=5001 -hwnd=330320",
stdin=subprocess.PIPE, stdout=subprocess.PIPE) as process:
for line in process.stdout:
print(line)
It works! The end program receives my message and performs the work I need it to do, this is the output:
b'Api executed successfully.\r\n'
Now I need to receive WM_COPYDATA from the end program to my hwnd, I modified some py2 code I found here:
class ACOPYDATASTRUCT(Structure):
_fields_ = [
('dwData', c_ulong),
('cbData', c_ulong),
('lpData', c_void_p)
]
PCOPYDATASTRUCT = POINTER(ACOPYDATASTRUCT)
class Listener:
def __init__(self):
message_map = {
win32con.WM_COPYDATA: self.OnCopyData
}
wc = win32gui.WNDCLASS()
wc.lpfnWndProc = message_map
wc.lpszClassName = 'MyWindowClass'
hinst = wc.hInstance = win32api.GetModuleHandle(None)
classAtom = win32gui.RegisterClass(wc)
self.hwnd = 330320
print(self.hwnd)
def OnCopyData(self, hwnd, msg, wparam, lparam):
print(hwnd)
print(msg)
print(wparam)
print(lparam)
pCDS = cast(lparam, PCOPYDATASTRUCT)
print(pCDS.contents.dwData)
print(pCDS.contents.cbData)
status = wstring_at(pCDS.contents.lpData)
print(status)
win32gui.PostQuitMessage(0)
return 1
l = Listener()
win32gui.PumpMessages()
Unfortunately, the message never comes in. I'm using PyCharm to run this, if it makes a difference.
I have 0 idea what to do now, and tutorials on the internet for this is sparse or written in python 2. Any help is appreciated, a link to a tutorial, some code, anything.

Getting no response from ProcessBuilder's input stream in some specific case

So I am trying to get battery status from linux, and so far the first command (path variable) returns perfectly and I am able to get its response in form of Sequence from the input stream, but unfortunately the second command (of result variable) returns empty sequence.
fun getLinuxBatteryStatus(): Nothing? {
val path = """upower --enumerate""".runCommand() ?: return null
val parameters = listOf("present", "state", "energy-full", "energy", "energy-rate", "time to empty", "percentage")
val result = """upower -i ${path.first { "battery_BAT" in it }} | grep -E "${parameters.joinToString("|")}""""
.also { println(it) }
.runCommand() ?: return null
result.forEach(::println) // <- no ouput
// println(result.count()) // <- 0
/* Do other thing and return something (that is not related to problem) */
}
Ouput:
upower -i /org/freedesktop/UPower/devices/battery_BAT1 | grep -E "present|state|energy-full|energy|energy-rate|time to empty|percentage"
The above output is from the also block in the last command, just to preview the command's string for debugging. And if I run the above command directly into the terminal I am successfully getting the responses as follows:
present: yes
state: charging
energy: 47.903 Wh
energy-empty: 0 Wh
energy-full: 50.299 Wh
energy-full-design: 48.004 Wh
energy-rate: 17.764 W
percentage: 95%
Why is the last command not working (not returning any response) with the ProcessBuilder?
Note: the extension function runCommand has been taken from here
private fun String.runCommand(
workingDir: File = File("."),
timeoutAmount: Long = 60,
timeoutUnit: TimeUnit = TimeUnit.SECONDS
): Sequence<String>? = try {
ProcessBuilder(split("\\s".toRegex()))
.directory(workingDir)
.redirectOutput(ProcessBuilder.Redirect.PIPE)
.redirectError(ProcessBuilder.Redirect.PIPE)
.start()
.apply { waitFor(timeoutAmount, timeoutUnit) }
.inputStream.bufferedReader().lineSequence()
} catch (e: IOException) {
e.printStackTrace()
null
}
The problem here is the pipe.
You're trying to run a pipeline — a construction involving running multiple programs, that needs a shell to interpret.
But ProcessBuilder runs a single program.  In this case, it's running the program upower and passing it the parameters -i, /org/freedesktop/UPower/devices/battery_BAT1, |, grep, -E, and "present|state|energy-full|energy|energy-rate|time to empty|percentage".  Obviously upower won't know what to do with the | parameter or those after it.
You could use ProcessBuilder to run up a shell instance, which could then run your pipeline; see this answer.
But it would probably be simpler, safer, and more efficient to do the filtering in your own code, and avoid calling grep entirely.
I recommend capturing the process's error output, which would very probably have made the problem clear.

how to stub a method that takes and argument

I'm kind of stuck (Maybe because this is my first time using Minitest) wherein I want to stub a method that takes an argument.
def self.bonsai_site_configuration(since=nil)
data = []
Site.all.reduce(data) do |data, site|
begin
data << JSON.parse(site.bonsai_desc)
rescue StandardError => exception
notify_exception(exception)
end
data
end
return {data: data`}
end
All I'm looking over here is that if test cases wherein if the site.bonsai_desc fails(i.e throw an exception). It should invoke notify_exception with given exception
Here how my minitest looks like
test "should return bonsai_site_configuration even on exception" do
site = Site.first
raises_exception = -> { raise 'boom' }
Site.stub(:all, [site]) do
site.stub(:bonsai_desc, raises_exception) do
Site.stub(:notify_exception) do
bonsai_information = Site.bonsai_site_configuration
assert_equal(0, bonsai_information[:data].count)
end
end
end
end
Upon running the minitest the test passes but I want to ensure that argument check is also included.
What am I suppose to do?

Storing Value in Arduino Sent From Python via Serial

I have been trying to send a value from a Python program via serial to an Arduino, but I have been unable to get the Arduino to store and echo back the value to Python. My code seems to match that I've found in examples online, but for whatever reason, it's not working.
I am using Python 3.5 on Windows 10 with an Arduino Uno. Any help would be appreciated.
Arduino code:
void readFromPython() {
if (Serial.available() > 0) {
incomingIntegrationTime = Serial.parseInt();
// Collect the incoming integer from PySerial
integration_time = incomingIntegrationTime;
Serial.print("X");
Serial.print("The integration time is now ");
// read the incoming integer from Python:
// Set the integration time to what you just collected IF it is not a zero
Serial.println(integration_time);
Serial.print("\n");
integration_time=min(incomingIntegrationTime,2147483648);
// Ensure the integration time isn't outside the range of integers
integration_time=max(incomingIntegrationTime, 1);
// Ensure the integration time isn't outside the range of integers
}
}
void loop() {
readFromPython();
// Check for incoming data from PySerial
delay(1);
// Pause the program for 1 millisecond
}
Python code:
(Note this is used with a PyQt button, but any value could be typed in instead of self.IntegrationTimeInputTextbox.text() and the value is still not receieved and echoed back by Arduino).
def SetIntegrationTime(self):
def main():
# global startMarker, endMarker
#This sets the com port in PySerial to the port with the Genuino as the variable arduino_ports
arduino_ports = [
p.device
for p in serial.tools.list_ports.comports()
if 'Genuino' in p.description
]
#Set the proper baud rate for your spectrometer
baud = 115200
#This prints out the port that was found with the Genuino on it
ports = list(serial.tools.list_ports.comports())
for p in ports:
print ('Device is connected to: ', p)
# --------------------------- Error Handling ---------------------------
#Tell the user if no Genuino was found
if not arduino_ports:
raise IOError("No Arduino found")
#Tell the user if multiple Genuinos were found
if len(arduino_ports) > 1:
warnings.warn('Multiple Arduinos found - using the first')
# ---------------------------- Error Handling ---------------------------
#=====================================
spectrometer = serial.Serial(arduino_ports[0], baud)
integrationTimeSend = self.IntegrationTimeInputTextbox.text()
print("test value is", integrationTimeSend.encode())
spectrometer.write(integrationTimeSend.encode())
for i in range(10): #Repeat the following 10 times
startMarker = "X"
xDecoded = "qq"
xEncoded = "qq"
while xDecoded != startMarker: #Wait for the start marker (X))
xEncoded = spectrometer.read() #Read the spectrometer until 'startMarker' is found so the right amound of data is read every time
xDecoded = xEncoded.decode("UTF-8");
print(xDecoded);
line = spectrometer.readline()
lineDecoded = line.decode("UTF-8")
print(lineDecoded)
#=====================================
spectrometer.close()
#===========================================
#WaitForArduinoData()
main()
First, this is a problem:
incomingValue = Serial.read();
Because read() returns the first byte of incoming serial data reference. On the Arduino the int is a signed 16-bit integer, so reading only one byte of it with a Serial.read() is going to give you unintended results.
Also, don't put writes in between checking if data is available and actual reading:
if (Serial.available() > 0) {
Serial.print("X"); // Print your startmarker
Serial.print("The value is now ");
incomingValue = Serial.read(); // Collect the incoming value from
That is bad. Instead do your read immediately as this example shows:
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();
That's two big issues there. Take care of those and let's take a look at it after those fundamental issues are corrected.
PART 2
Once those are corrected, the next thing to do is determine which side of the serial communication is faulty. Generally what I like to do is determine one side is sending properly by having its output show up in a terminal emulator. I like TeraTerm for this.
Set your python code to send only and see if your sent values show up properly in a terminal emulator. Once that is working and you have confidence in it, you can attend to the Arduino side.

Updating a label from a thread in Perl

I'm using perl on a linux box, and I have 2 devices - a pc(the linux box) and a router/dsl-thingy - on my local net at ip addresses 192.168.1.1 & 192.168.1.2 and am trying to list or show the progress of pinging such + a test of 8 other none existing devices, with the below code, but am having troubles with my StatusLabel updating, any help...
for($i=1;$i<=10;++$i) { # --- $i<$VarClients --- 254
my $thr_List = ("ping$i");
$thr_List = threads->create(\&pingingthreads, "$i");
}
sub pingingthreads{
my #pingpong = ping("$localAddress$i", '-c 1', '-i .2'); # -i may not count for much?
print "Pinging: $localAddress$i\n"; # output goes from address1 - address10 ok
$StatusLabel = "Pinging: $localAddress$i"; # only the last responding one(device) seems to be shown in my statuslabel?!
$val = ($val + 10); # 0.392156863
print "$val\% done...\n"; # goes to 100% for me ok
# $indicatorbar->value( $val ); # I have a ProgressBar and it gets stuck on 20% also
if ($val == 100){$val = 0;
} # reset after scanning
# then after the last ping, update the statusLable:
#my #ParamList = ('something', 'testing', 7, 8, 9);
#$thr5 = threads->create(\&updateStatusLable, #ParamList); # starting a thread within a thread ???
# ping response text...
for( #pingpong ) { # need to do something for none responding clients & any time laps/ping latency..., or *** ???
$pong=$_;
chop ($pong); # Get rid of the trailling \n ??
if ($pong =~ m/1 packets transmitted, 1 received, 0% packet loss/) {
push(#boxs, "$localAddress$i");
} else{
# see the other lines from the ping's output
# print "$pong\n";
}
}
}
# For $localAddress$i icmp_seq=1 Destination Host Unreachable ???
--------------------- # StatusBar/progress label & bar ----------------
my $sb = $main->StatusBar();
$sb->addLabel( -textvariable => \$StatusLabel,
-relief => 'flat',
-font => $font,
-foreground => "$statusbartextColour",
);
my $indicatorbar = $sb->ProgressBar( -padx=>2, -pady=>2, -borderwidth=>2,
-troughcolor=>"$Colour2",
-colors=>[ 0, "$indicatorcolour" ],
-length=>106,
-relief => 'flat',
-value => "$val",
)->pack;
# $val = 0;
# $indicatorbar->value( $val );
=====================================
my $StatusLabel :shared = ();
my $val :shared = (0); # var for progress bar value
I have uploaded my full code here (http://cid-99cdb89630050fff.office.live.com/browse.aspx/.Public) if needed, its in the Boxy.zip...
By default data in Perl threads are private; updates to a variable in one thread will not change the value of that variable in other threads (or in the main thread). You will want to declare $val as a shared variable.
See threads::shared.
I see you have declared $val as shared at the bottom of the script, so I didn't see it until it was too late. Not coincidentally, the Perl interpreter is also not going to see that declaration until it is too late. The top 95% of your program is manipulating the global, thread-private variable $var and not the lexical, shared $var you declare at the end of your script. Move this declaration to the top of the script.
Putting use strict at the top of your program would have caught this and saved you minutes, if not hours, of grief.
You don't. GUI frameworks tend to be not threadsafe. You communicate the info to the thread in which the GUI is run instead. Example
First sorry for replying here, but have lost my cookie or the ability to reply and edit etc...
Thanks ikegami, I will have to play with the example for a while to see if I can work things out and mix it into what I'm doing... but on first sight, looks just right... Thanks very much.
I was able to update the $StatusLabel using:
# in 3 seconds maybe do a fade to: Ready...
my #ParamList = ('ping', 'testing', 4, 5, 6);
$thr2 = threads->create(\&updateStatusLable, #ParamList);
sub updateStatusLable {
# should probably check if threads are running already first???
# and if so ***/*** them ???
my #InboundParameters = #_;
my $tid = threads->tid();
# my $thr_object = threads->self(); # Get a thread's object
# print("This is a new thread\($tid\)... and I am counting to 3...\n");
sleep(3);
$StatusLabel = "Ready..."; # print "Am now trying to change the status bar's label to \"Ready...\"\n";
# try updating better/smoother... My main window needs "focus and a mouse move" I think
# for the new text to appear...
# print('Recieved the parameters: ', join(', ', #InboundParameters), ".\n" );
# $returnedvalue = "the thread should return this...";
# return($returnedvalue); # try returning any value just to test/see how...
}
but will try your method... Thanks again.

Resources