Expect Interact and special characters - macros

trying to create a macro program with expect to help me manage my cisco devices>
I want to keep all native cisco functions like tab complete ETC.
initially I wanted to type "!...!" where my macro is inside the bangs, my code looked like this:
interact {
-re "!(.+)!" { #find correct macro }
}
but with this method, there is no feedback to the user. what happens if they misspell? etc then they can't see their corrections with backspace.
then I started thinking about just capturing each character press and building a string
interact {
#book says backspace character
"\b" {
set command [lreplace $command end end]
}
#detect return, sending command
-re "\r" {
set command [join $command ""]
if [regexp "^!" $command] {
#send ctrl+u to erase line sent
send "\025"
findMacro $command
}
set command ""
send "\r"
}
#send tab for tab completion
"\t" { send "\t" }
-re "(.)" {
send $interact_out(1,string)
lappend command $interact_out(1,string)
}
}
but I can't "expect" the backspace. I've tried 0x08.. etc nothing is working. in the end I'm not even sure this is the way to go simply because there are to many other buttons a user could push and mess up my string I'm building.
the real solution, I think, is to wait until "\r" is pressed, and then run a regex on that line. but I'm not sure how to do that.

Related

Mirc script to find exact match in customer list

I am using this to find customer name in text file. Names are each on a separate line. I need to find exact name. If searching for Nick specifically it should find Nick only but my code will say found even if only Nickolson is in te list.
On*:text:*!Customer*:#: {
if ($read(system\Customer.txt,$2)) {
.msg $chan $2 Customer found in list! | halt }
else { .msg $chan 4 $2 Customer not found in list. | halt }
}
You have to loop through every matching line and see if the line is an exact match
Something like this
On*:text:*!Custodsddmer*:#: {
var %nick
; loop over all lines that contains nick
while ($read(customer.txt, nw, *nick*, $calc($readn + 1))) {
; check if the line is an exact match
if ($v1 == nick) {
%nick = $v1
; stop the loop because a result is found
break;
}
}
if (%nick == $null) {
.msg $chan 4 $2 Customer not found in list.
}
else{
.msg $chan $2 Customer found in list!
}
You can find more here: https://en.wikichip.org/wiki/mirc/text_files#Iterating_Over_Matches
If you're looking for exact match in a new line separate list, then you can use the 'w' switch without using wildcard '*' character.
From mIRC documentation
$read(filename, [ntswrp], [matchtext], [N])
Scans the file info.txt for a line beginning with the word mirc and
returns the text following the match value. //echo $read(help.txt, w,
*help*)
Because we don't want the wildcard matching, but a exact match, we would use:
$read(customers.txt, w, Nick)
Complete Code:
ON *:TEXT:!Customer *:#: {
var %foundInTheList = $read(system\Customer.txt, w, $2)
if (%foundInTheList) {
.msg # $2 Customer found in list!
}
else {
.msg 4 # $2 Customer not found in list.
}
}
Few remarks on Original code
Halting
halt should only use when you forcibly want to stop any future processing to take place. In most cases, you can avoid it, by writing you code flow in a way it will behave like that without explicitly using halting.
It will also resolve new problems that may arise, in case you will want to add new code, but you will wonder why it isn't executing.. because of the darn now forgotten halt command.
This will also improve you debugging, in the case it will not make you wonder on another flow exit, without you knowing.
Readability
if (..) {
.... }
else { .. }
When considering many lines of codes inside the first { } it will make it hard to notice the else (or elseif) because mIRC remote parser will put on the same identification as the else line also the line above it, which contains the closing } code. You should almost always few extra code in case of readability, especially which it costs new nothing!, as i remember new lines are free of charge.
So be sure the to have the rule of thump of every command in a new line. (that includes the closing bracket)
Matching Text
On*:text:*!Customer*:#: {
The above code has critical problem, and bug.
Critical: Will not work, because on*:text contains no space between on and *:text
Bug: !Customer will match EVERYTHING-BEFORE!customerANDAFTER <NICK>, which is clearly not desired behavior. What you want is :!Customer *: will only match if the first word was !customer and you must enter at least another text, because I've used [SPACE]*.

Exiting a secondary Perl script and returning to the main program

I am running a Perl script to control two other scripts. The user of the main program can call the two secondary scripts with the following line.
do 'Task_A.pl';
The script then runs Task_A.pl but I would like to find a way of then exiting Task_A.pl and return to the main program. If possible I would like to return to the function where I last called the secondary script. I am not sure as to what this is called but I appreciate any input for a possible solution.
This is the whole main program, not much to it at the moment.
my $selecion;
#Looping variables.
my $program_loop = 1;
while ($program_loop == 1)
{
print "Please choose one of the programs listed in the menu.\n";
#Program menu where the user chooses from the presented options.
print "[1] - Script A.\n";
print "[2] - Script B.\n";
print "[3] - Exit program.\n";
my $user_input = <>;
if ($user_input == 1) # <-- Scrip_A.pl
{
do 'Task_A.pl';
}
elsif ($user_input == 2) # <-- Scrip_B.pl
{
do 'Task_B.pl';
}
elsif ($user_input == 3) # <-- Exit Program
{
#The user can choose to exit from the menu.
print "The program will now exit.\n";
exit;
}
}
do does not start another process. If that's what you want, use "system()".
If you want do, then it's probably best to just put everything into a function in the file to be evaluated and call the function at the end of the file.
Use "return" to leave the function and return to next instruction after do.

Is there a way to store message box settings to be used repetitively in Powershell?

I'd like to use the same message box repetitively in a Powershell script, without having to reiterate all the settings each time. I initially thought that I would store it as a variable:
$StandardMessage = [System.Windows.Forms.MessageBox]::Show("Repetitive Message.", "Chores.")
But as I found out this simply stores the user's response to the message box in the variable.
What I would like to do is something similar to the following pseudo-code:
$StandardMessage = [System.Windows.Forms.MessageBox]::Show("Repetitive Message.", "Chores.")
While(true){
If(condition){
$StandardMessage
}
If(condition2){
$StandardMessage
}
}
Where the conditions would be time-based. This is essentially displaying a message at specified times during the day.
Asked another way (and perhaps more clearly): Is it possible to 'define' a messagebox without actually 'showing' it?
You need to use a Function my good man!
Function Show-MyMessage{
[System.Windows.Forms.MessageBox]::Show("Repetitive Message.", "Chores.")
}
While(true){
If(condition){
Show-MyMessage
}
If(condition2){
Show-MyMessage
}
}
Edit: Personally I have this function on hand for several of my scripts to use as needed:
Function Show-MsgBox ($Text,$Title="",[Windows.Forms.MessageBoxButtons]$Button = "OK"){
[Windows.Forms.MessageBox]::Show("$Text", "$Title", [Windows.Forms.MessageBoxButtons]::$Button, [Windows.Forms.MessageBoxIcon]::Information) | ?{(!($_ -eq "OK"))}
}
Then I can just call it as needed, like:
Show-MsgBox -Title "You want the truth?" -Text "You can't handle the truth!"
And I've got a pop up with the text and title I want, and an OK button.
Buttons can be specified (there's a pop-up for it in the ISE to give options), and title can be excluded if I am feeling lazy. Only thing I really have to feed it is the message.

mIRC Bot simulate keystrokes

I would like to program my mIRC bot so every time someone writes "W" in the chat, the bot simulates the W key on my keyboard.
I have tried:
on *:text:W:#:sendkeys {W}
alias sendkeys var %a = $ticks
.comopen %a WScript.Shell | if !$comerr {
.comclose %a $com(%a,SendKeys,3,bstr,$1-)
}
This doesn't seem to be working. Any advice?
The code is fine, the blocks in which you execute that code are incorrect. Due to a lack of brackets, your alias will only execute the var command, and be done after that.
Taken from the mIRC help files:
The { } brackets: You can create multi-line scripts by using the { } brackets. This allows you to create an alias which performs several commands.
alias sendkeys {
var %a = $ticks
.comopen %a WScript.Shell
if !$comerr {
.comclose %a $com(%a,SendKeys,3,bstr,$1-)
}
}

How do I send a Carriage Return with Windows Netcat?

I want to type directly into the Powershell prompt too, not pipe in a text file.
Foo`r doesn't work for me. For example:
echo "RJ`r`n" | .\nc.exe -u 192.168.1.247 2639
but what I'd really like to do is just
.\nc.exe -u 192.168.1.247 2639
then start typing into the prompt.
Try:
"Foo`ndoes work for me"
If you need a full CRLF sequence then:
"Foo`r`ndoes work for me"
Note that the escapes chars only work in double-quoted strings - not single quoted strings.
Update: Redirect in < is not supported in PowerShell at this time so you can only get stdin to the exe from the interactive prompt using the pipeline. Is it possible nc.exe is expecting another character (or escape char) to terminate the input? I know that console exes can receive stdin from PowerShell. If you have the C# compiler, you can see this by compiling the following source (csc echostdin.cs):
using System;
public class App
{
public static void Main()
{
int ch;
while ((ch = Console.In.Read()) != -1)
{
Console.Write((char)ch);
}
}
}
Then execute the exe:
PS> "foo`r`n" | .\echostdin.exe
foo
PS>