So there is a program someone wrote (that I don't have access to) that was written in C#, in which when I open it, it brings up a command prompt, asks several questions, and then returns an output.
What I want to do it write a batch file to automate entering all the arguments manually but nothing has really worked for me thus far. I tried "program.exe arg1 arg2.." in the command prompt and reading about the windows commands (I checked out ss64) but nothing seems to work.
So to summarize what happens is:
1) I open the program (a .exe file) in the command prompt (or click on it) where it asks me to enter a value or filename
http://i.stack.imgur.com/bZsSi.png
2) I press enter to continue to the next question and the command asks me to answer another question (unless I finished the last one, in which case the program finishes executing and then closes).
http://i.stack.imgur.com/nqJ5M.png
Now, how would I go about making a batch file that enters SWAIN.dat, n, 1000, etc... automatically into this program? Again, I don't have access to the original program. i only know it was written in C#.
Thank you very much.
You could create a VB script -
set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.Run "cmd"
WScript.Sleep 100
WshShell.AppActivate "C:\Windows\system32\cmd.exe"
WScript.Sleep 100
WshShell.SendKeys "program.exe{ENTER}"
WScript.Sleep 100
WshShell.SendKeys "SWAIN.dat{ENTER}"
WScript.Sleep 100
WshShell.SendKeys "1000{ENTER}"
etc...
You may try this:
(
echo SWAIN.dat
echo n
echo 1000
echo etc...
) | program.exe
Related
I have a simple c# program that expects command line input (from Console.ReadLine()) when ran. There's a lot of inputs I have to provide, so I was wondering how I could automate this process. I currently have a shell script that attempts to do this, but it's not working.
#!/bin/sh
dotnet run #run the program
1 #input first argument (this failed so I tried echo 1 instead but no luck)
# <- rest of command line inputs on each line
Not really familiar with shell scripts, and I'm not fixed on this solution if you had another solution in mind. My OS is MacOS.
OK, so what I tried was this:
I made a little mcve-Console App: (dotnet 6)
var input = Console.ReadLine();
while( !string.IsNullOrEmpty(input) )
{
Console.WriteLine("User input: {0}", input);
input = Console.ReadLine();
}
Then I made a little input.txt
This is a Text.
This is another Text.
1
2
3
This is the final Text.
and finally run.sh as follows:
#!/bin/sh
dotnet run < "input.txt"
Output was
User input: This is a Text.
User input: This is another Text.
User input: 1
User input: 2
User input: 3
User input: This is the final Text.
/bin/sh is linked to dash shell in my case.
If in run.sh you replace "input.txt" with "$1", then you can call it with ./run.sh whateveryourinputfileis.txt to make a little more flexible.
We have a C# console application, which takes various input(note- no command line input)
Eg
C:\MyTool.exe
Enter Option (1-4):
Enter Location(1-7):
Enter Region (1-3):
After providing these input one by one, tool process the input and produce some business result.
Now, I have a requirement to run these tool every hour with Option -1, Location -2, Region-1
What I am planning to do is to setup the Windows Schedular, which will call these EXE, but the problem is how can I provide the input which in may case (1, 2, 1) respectively to the console tool.
I am thinking is there is any way that I can provide the input upfront in the command line itself...
Eg C:\MyTool.exe << 1 2 1 So that I can create batch file of these command and schedule it accordingly.
Please suggest.
Thanks,
Siraj
Create an input file where the input options are separated by CRLF (carriage return, Line feed). For example, open a command prompt and go to the folder where your MyTool.exe is located. Then type: 'copy con input.txt<enter>1<enter>2<enter>1<enter><F6>' This will create the input file. Now use 'MyTool < input.txt'. This will run your tool with accepting these input parameters. This command can be used in the task scheduler.
So, I am making a hacking game, and in it you control a terminal. So far, I have done 'help' and 'cls' commands, that don't require parameters. But, for say a echo command, I need the computer to detect the keyword 'echo' and the rest of the text as what you want to 'echo'. How can I do this? Thanks for any help.
You can do something line this:
var input = Console.ReadLine(); //You might have this already in your code
if (input.StartsWith("echo "))
{
var text = input.Substring(5);
Console.WriteLine(text);
}
This checks to see if the input line starts with echo, and if it does, it prints to the console whatever is after the first 5 characters (which is the length of echo and one space)
I am sending commands to a Zebra QLn220 for it to print labels (naturally). I also have code, though, that assigns values to certain printer settings, such as:
const string quote = "\"";
string keepPrinterOn = string.Format("! U1 setvar {0}power.dtr_power_off{0} {0}off{0}", quote);
string advanceToBlackBar = string.Format("! U1 setvar {0}media.sense_mode{0} {0}bar{0}", quote);
string advanceToGap = string.Format("! U1 setvar {0}media.sense_mode{0} {0}gap{0}", quote);
PrintUtils.SendCommandToPrinter(keepPrinterOn);
if (radbtnBar.Checked)
{
PrintUtils.SendCommandToPrinter(advanceToBlackBar);
}
else if (radbtnGap.Checked)
{
PrintUtils.SendCommandToPrinter(advanceToGap);
}
This works - after running that code with radbtnBar checked, those settings are now (as seen via running "! U1 getvar "allcv"" in the Zebra Setup Utilities app):
power.dtr_power_off : off , Choices: on,off
media.sense_mode : bar , Choices: bar,gap
The problem is that after setting those values via the code above, and then attempting to print labels (after a lapse of at least 20 seconds, and have tested up to more than a minute), the first couple of attempts to print a label silently fail (there is no err msg, it is just that no printing takes place). On the third attempt, the label prints. Why would setting these vals cause the printer to temporarily "go deaf," and is there anything I can do to shake it back to wakefulness following the programmatic application of those settings so that it will print immediately?
Once the QLn220 finally regains responsiveness, it continues to print immediately on subsequent executions of the app with no delays; it's only after sending those commands ("power.dtr_power_off" and "media.sense_mode") that the printer is knocked out of its orbit for a season. A real zebra would never be as stubborn as a mule like this.
UPDATE
Banno's idea did the trick, apparently (appending crlfs ("\r\n")) to the commands to set the printer vars.
So it seems that what was happening was something like this:
Command 1 was sent to the printer to set a val (with no crlf).
Command 2 was sent to the printer to set another val (also with no crlf)
A label was then attempted to be printed; it didn't print. Seeing that it did have a crlf, though, the printer seemed to say, "Oh, you finally gave me one of the crlfs you owe me! But you're not getting off that easy - you still owe me one!"
A second attempt to print a label caused the printer to say, in effect, "Okay, then, you've paid your crlf debt; from now on, I will listen to the commands you send (as long as you terminate them with the crlf I so ravenously crave)."
UPDATE 2
Sometimes it still doesn't work (inconsistent behavior); I found that I had to "poke it" to get it to quit its somnambulism; see What Zebra QLn220 settings do I need to set (and to what value[s]) to get a setting to "stick"?
append "\r\n\" to each command
This one seems trivial but the answer has eluded me for a few days now.
I have a Windows batch file, that calls a C# program to do an extra verification that cannot be done in a batch file. After the verification is complete I need to return a status and a string back to the calling shell.
Now the return value is trivial and my C# console app simply sets a return value (exit code if you will). And I thought the string will also be a piece of cake. I attempted to define a new shell variable using the:
Environment.SetEnvironmentVariable("ERR", "Some text");
This call should (and does) define a shell variable within the current process - that is the very C# process that created the variable. The value is lost as soon as the C# app terminates and the shell that created the C# app knows nothing about the variable. So... A call with no particular use... At all... Unless perhaps if I created a child process from the C3 app, perhaps it would inherit my variables.
The EnvironmentVariableTarget.Machine and EnvironmentVariableTarget.User targets for the SetEnvironmentVariable call don't solve the problem either, as only a newly created process will get these new values from the registry.
So the only working solution I can think of is:
write to stdout
write to a file
encode extra meaning into the return value
The first two are a bit ugly and the last one has its limitations and problems.
Any other ideas (how to set a shell variable in the parent process)? Maybe such shell variable modifications are a security concern (think PATH)...
Thank-you for your time.
I had the same problem as Ryan and the only thing that came to my mind as a work-around was to write a batch in error out to set the variable and to call it from the batch.
ConsoleApplication1.exe:
'put some sensible code here
'put result in variable myResult
Dim myResult As String = Guid.NewGuid().ToString("D").ToUpperInvariant()
Console.WriteLine("Normal output from the consonle app")
Console.Error.WriteLine("#ECHO OFF")
Console.Error.WriteLine("SET zzzResult={0}", myResult)
Test.cmd (the calling batch):
#ECHO OFF
:Jump to folder of batch file
PUSHD %~d0%~p0
:Define a temp file
SET zzzTempFile=%TEMP%\TMP%Random%.CMD
:Call .NET console app
ConsoleApplication1.exe 2>%zzzTempFile%
:Call the generated batch file
CALL %zzzTempFile%
:Clean up temp file
DEL %zzzTempFile%
:Clean up variable
SET zzzTempFile=
:Do something with the result
ECHO Yeah, we finally got it!
ECHO:
ECHO The value is "%zzzResult%".
ECHO:
:Clean up result variable
SET zzzResult=
:Go back to original folder
POPD
That should do the trick. And yes, I do know this is an old post and Ryan is solving other issues by now, but there might be still somebody else out there having the same problem...
What you are asking is to be able to arbitrarily write to the memory space of a running process. For good reason, this is not possible without SeDebugPrivilege.
Any of the three solutions you list will work. Stdout is the standard way to communicate with a batch script.
By the way, you're writing a Windows batch file. I'm pretty sure the ship has already sailed on "a bit ugly".
If you want to put a value of some output into a variable in the batch you can use the following construct:
FOR /F "usebackq tokens=4 delims=\[\] " %i IN (`ver`) DO set VERSION=%i
ECHO %VERSION%
Output on my OS:
6.1.7601
'usebackq' means we are using back quotes which gives the ability to use a fileset in the command quoted with double quotes. You may not need this. 'tokens' means the index in the resulting string array to select (it can be a range M-N). If you need to skip lines use 'skip=X'). 'delims' are the string separators to use (like string-Split() in .Net).
You will put your console app instead of 'ver' and adapt the delimiters and tokens to match your specific output. If you have more variables to fill you will need to make the if a bit more complex but that should make a good start.
My BAT is a bit rusty, but I think it's possible to retrieve the 'exit' code from processes you've run externally, perhaps via %ERRORLEVEL%. If that's the case, make sure to exit your program via
Environment.Exit(123); // where 123 = error code
You can't add any messages, so you'll have to do that in the .bat file.
If this isn't the case, stdout is probably the best way.
After stumbling on this myself as well recently, I came up with this approach. What I did is run the bat file using the Process class, i.e.
// Spawn your process as you normally would... but also have it dump the environment varaibles
Process process = new Process();
process.StartInfo.FileName = mybatfile.bat;
process.StartInfo.Arguments = #"&&set>>envirodump.txt";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = false;
process.Start();
string output = process.StandardOutput.ReadToEnd();
process.WaitForExit();
// Read the environment variable lines into a string array
string[] envirolines = File.ReadAllLines("envirodump.txt");
File.Delete("envirodump.txt");
// Now simply set the environment variables in the parent process
foreach(string line in a)
{
string var = line.Split('=')[0];
string val = line.Split('=')[1];
Environment.SetEnvironmentVariable(var, val);
}
This seems to have worked for me. It's not the cleanest approach, but will work in a bind. :)