Piping in Windows - windows

i am have a console to controll a device driver. This tool allows me to enter numbers an change parameters of the device. Which is executed on a windows system. In order to not enter numbers manually, I am piping those numbers to the executable, like so..
cd %tool_path%
(
echo 1
echo 2
echo 3
)myconsole.exe
And here is my question, is there a way to put a delay between those echos? And it would be even better if I could read the output, so I can send different numbers depandend on the output.
My idea would be writing a short programm in C or C++ doesn't matter and handle those delays in there. But I can't really find examples to this. Here is what I found.
https://msdn.microsoft.com/de-de/library/windows/desktop/ms682499(v=vs.85).aspx
But in this examples I don't know where I can input myconsole.exe.
I also looked at named pipes, but they don't seem to be the right thing for this task.

You should have a look at the Unix tool called expect - there is a Windows version from ActiveState.
Basically, you can do things like:
send "Hello\r\n"
sleep 1
send "Something\r\n"
expect {
"> " { }
"$ " { }
}
if { $a == "soup" } {
puts "You have soup!"
else {
puts "No soup for you!"
}
There are examples here and all over the Web - look for Tcl/expect tutorials.

Related

AutoHotKey - defining a variable from the output of a program ran inside AHK

I'm trying to make a script that automatically toggles between 100% and 150% scale on Windows and I found
https://github.com/imniko/SetDPI
which is perfect for this specifically as it just outputs the needed value, but I don't know how to run the program inside the script, then define a variable with said output.
BTW, it's probably relevant to mention this is AHKv2
The script would be something like:
Run "SetDPI.exe value 1"
currentscale:= OUTPUT GOES HERE
if(currentscale == 100)
{
Run "SetDpi.exe 150 1"
}
else
{
Run "SetDpi.exe 100 1"
}
I know this is unoptimized but it'd do.

Expect->Telnet->Store and read a variable / Check if directory exists

Summary:
I am writing a script to check if a directory exists on a remote machine. I need a solution which can allow me to check for that directory and return the result in a usable way. This whole process is automated within a much larger script so I need a functional way to tell the parent script the directory exists or not.
Restrictions:
The tools that I have are limited. $REMOTE_2 can only be accessed through $REMOTE_1. Also, $REMOTE_2 can only be connected via telnet (no ssh available).
Current goal:
I am trying to set a local variable to be then read back to chose a return code. I am open to other options, but this is the closest I've come to a working solution so far.
I realize that $found will take from the parent process, but this is not my desired result and am not sure what syntax I need to return true or false when trying to echo the $found variable.
/usr/bin/expect<<EOF
spawn ssh $USER#$REMOTE_1
expect "*$USER*"
send -- "telnet $REMOTE_2\r"
expect "*login:*"
send -- "root\r"
expect "*$*"
# Everything prior to this can't be changed. Everything after it can be.
send "if \[ -d $DIRECTORY_LOCATION \] ; then found=true; else found=false ; fi\r"
send -- "echo **$found**\r"
expect {
"*true*" {
exit 0
}
"*false*" {
exit 1
}
}
EOF
I believe this type of solution can work, but I am not sure how to use the remote variable that I store within the if statement, later on to allow me to choose which return code to use.

Windows process called by perl doesn't write to file properly

I'm trying to call a perl script from another perl script, read from serial port, and write to a file. I've distilled my code to isolate the problem, so it probably won't make sense what the point of the code is.
Caller:
use Win32::Process;
my $perl_path = $^X;
my $SerialLogProcess;
my $SerialLogObj;
my $serial_log_script = "callee.pl";
Win32::Process::Create($SerialLogObj, "$perl_path", "perl $serial_log_script " ,0,NORMAL_PRIORITY_CLASS,".");
$SerialLogProcess = $SerialLogObj->GetProcessID();
print "waiting for 3 secs";
sleep(3);
print "done";
`taskkill /F /T /PID $SerialLogProcess`;
Callee:
use Win32::SerialPort;
my $portObj = new Win32::SerialPort("\\\\.\\COM70") || die;
my $serialReading;
$portObj->baudrate(115200);
$portObj->parity("none");
$portObj->databits(8);
$portObj->stopbits(1);
system("rm -r \"log.txt\"");
open (LOGFILE, ">>log.txt") or die;
while (1){
$serialReading = $portObj->read(10);
print LOGFILE $serialReading;
#print LOGFILE " ";
}
So the caller creates a process for the callee script, and then kills it after 3 seconds. In those 3 seconds, I do something that gives guaranteed messages for the serial port to read. The log file is created, but nothing is written to it.
Heres what's weird: I can make the messages show up two ways. I run the callee script straight from the command line, or I can uncomment that last print. Unfortunately, these aren't solutions for me. I'm pretty stumped why I can't get my code to work properly, and it makes me think there is some kind of undefined behavior.
The output is buffered by default. The data will eventually be written once there's enough to write. Or you can use the following which will cause a flush for every print.
use IO::Handle qw( ); # Needed before Perl 5.14
open (LOGFILE, ">>log.txt") or die;
LOGFILE->autoflush(1);
But ug, why use a global variable???
open (my $LOGFILE, ">>log.txt") or die;
$LOGFILE->autoflush(1);
print $LOGFILE $serialReading;

Perl Net::SSH2 scp_put puts file and then hangs

I'm using Net::SSH2's scp_put method to place one file in my home directory on a Unix server from a Windows box. I am using Strawberry Perl 5.12 (portable version). I installed the libssh2 1.2.5 binaries and then Net::SSH2 from cpan.
Here's my code snippet:
sub uploadToHost{
my $file=#_[0];
my $host=#_[1];
my $user=#_[2];
my $pass=#_[3];
my $remotelocation=#_[4];
#makes a new SSH2 object
my $ssh=Net::SSH2->new() or die "couldn't make SSH object\n";
#prints proper error messages
$ssh->debug(1);
#nothing works unless I explicitly set blocking on
$ssh->blocking(1);
print "made SSH object\n";
#connect to host; this always works
$ssh->connect($host) or die "couldn't connect to host\n";
print "connected to host\n";
#authenticates with password
$ssh->auth_password($user, $pass) or die "couldn't authenticate $user\n";
print "authenticated $user\n";
#this is the tricky bit that hangs
$ssh->scp_put($file, $remotelocation") or die "couldn't put file in $remotelocation\n";
print "uploaded $file successfully\n";
$ssh->disconnect or die "couldn't disconnect\n";
} #ends sub
Output (edited for anonymity):
made SSH object\n
connected to host\n
authenticated \n
libssh2_scp_send_ex(ss->session, path, mode, size, mtime, atime) -> 0x377e61c\n
Net::SSH2::Channel::read(size = 1, ext = 0)\n
It then hangs forever (>40 minutes in one test) and needs to be killed.
What's strange is that it actually does scp the file to the remote server! It only hangs after it should have completed. I couldn't find references to this curious problem elsewhere on StackOverflow or elsewhere.
Can anyone point me in the right direction to either 1) stop it from hanging, or 2) implement (as a workaround) a timer that kills this one command after a few seconds, which is enough time to scp the file?
Thanks, everyone!
You can try using alarm() to prod your process into behaving, if you save this example as 'alarm.pl' you can see how it works:
use strict;
use warnings;
use 5.10.0;
# pretend to be a slow process if run as 'alarm.pl s'
if (#ARGV && $ARGV[0] eq 's') {
sleep(30);
exit();
}
# Otherwise set an alarm, then run myself with 's'
eval {
local $SIG{ALRM} = sub {die "alarmed\n"};
alarm(5);
system("perl alarm.pl s");
};
if ($#) {
die $# unless $# eq "alarmed\n";
say "Timed out slow process";
}
else {
say "Slow process finished";
}
Use Net::SFTP::Foreign with the Net::SSH2 backend, Net::SFTP::Foreign::Backend::Net_SSH2:
use Net::SFTP::Foreign;
my $sftp = Net::SFTP::Foreign->new($host, user => $user, password => $password, backend => Net_SSH2);
$sftp->die_on_error("Unable to connect to remote host");
$sftp->put($file, $remotelocation);
$sftp->die_on_error("Unable to copy file");
If that doesn't work either, you can try using plink (from the PuTTY project) instead of the Net::SSH2 backend.
I don't think it is hanging it is just REALLY SLOW. 10x slower than what it should be. The reason the file would appear to be there is that it allocates the file before it has finished transferring. This isn't really too unexpected, Perl finds new ways to disappoint and frustrate programmers on a daily basis. Sometimes I think I spend more time working around Perl's idiosyncrasies and learning 10 slightly different ways to do the same thing than doing real work.

No Gui Option?

Ok, well I'm really pushing the bounds as to what shoes is for here, so I don't expect any miracles: is there a way to optionally run a shoes app without a gui?
The reason I'd like to do this is I'm creating a tool for use by "non computer people", as well as "computer people", who would rather just run the program as a command line tool, maybe even on systems without X/gtk installed. (I work as a multidisciplinary researcher, and shoes is great for focusing on tools and not fiddling with gui design all day.)
Here's some example code:
if(ARGV[1] == "nogui")
puts "running computation on #{ARGV[2]}";
exit();
end
Shoes.app(:width => 200, :height => 100) do
#button = button("Quit").click() {
exit();
}
end
which works except I get a
Gtk-CRITICAL **: gtk_main_quit: assertion `main_loops != NULL' failed
error.
I haven't tried it, but I don't know that Shoes will even happily start on a system without X. You're probably better off creating a shell script that chooses which version to start. Something like this:
#!/usr/bin/sh
NOGUI=0
if [ $# -gt 0 ]; then
NOGUI=$1
fi
if [ $NOGUI = nogui ]; then
shift
echo "Running in command-line mode..."
ruby command-line.rb "$#"
else
echo "Starting Shoes..."
shoes shoes.rb "$#"
fi
If the first argument is nogui, the remaining arguments are sent to the Ruby version, otherwise all arguments (including the first) are sent to Shoes.
Now you just need to separate the actual performance logic out so that it can be imported into both versions.

Resources