I am writing a launcher in C# that processes user input and I would like its corresponding output string to be piped into an external program. The external program is a precompiled C# executable that is end-of-life, so I cannot easily modify it.
I can easily launch the desired program using ExternalProcess, but do not see any means for sending data over. My desired function calls go something like:
string myString = "string to pass over"
Clipboard.SetText(myString);
Process ExternalProcess = new Process();
ExternalProcess.StartInfo.FileName = "Notepad.exe";
ExternalProcess.Start();
// some kind of paste command here...
// ExternalProcess.magicpaste(myString);
ExternalProcess.WaitForExit();
Is there a better way to go about this? I realize the purported security implication in piping text this way, but I need to create a simple launcher program to support a legacy project.
Given your answer in the comments that you need to put some text in a field, I'm afraid you're going to have to get your hands dirty.
That text box (I assume that's what it is) in this legacy application, will be a window. And you're going to have to find it, and send it a message using Platform-Invoke. This question should get you started.
If said control has a name, you can find it using Spy++.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I'm new to programming and I want to learn with c# for now, I want to make a program that take the input "the user" put in "textbox1" in to my test.bat file
Text in "test.bat"
Set A="textbox1.text"
Echo %A%
Here's the image of the ui in the visual basic I wrote with the textbox
With the "button1" click it will start the test.bat and show the textbox1 text in the cmd if its possible
I would love to get it to work.
Thanks for the help !!
Your desires can be met with a couple of lines of code employing the File.WriteAllText to create the file with its contents and the Process.Start method to run it. Ctrl-F on that page for /k if you're having trouble getting your console window to remain open to actually see the message
I'll leave the task of formulating the string contents to be written to the file, to you. Remember that the documentation usually has examples on how to use every method it describes so a ready source of pre written code is available
Final tip; you're allowed to rename controls after you drop them on a form, and you really should take the 2 seconds needed to do so, so that you aren't one day asking us for help with code that is full of label27, textbox56 - it makes a program far harder for everyone to understand (look up what "obfuscation" is), including you, and is nonsensical when it's so easy to rename them to batchFileMessageTextBox or saveAndLaunchBatFileButton
To my understanding,you want to use C# to create a dialog box to take user input and show it in console,well its not possible directly but you can store the input given by user in a file and then use a batch file to read it.i am not a c# programmer so i don't know how to work with dialog box in c# but the Following link provides your solution and then use the following batch file to read the input in file:
#echo off
set /p var=<file.txt
echo %var%
pause >nul
There are a couple of simple approaches to this. One is to do what you asked; to write the input text to a file named "textbox1.text" (really should be "textbox1.txt", though, since ".txt" is a common suffix for text files and ".text" isn't) and then let the batch script read it.
It's a whole lot easier to simply write the text to the standard output stream using Console.WriteLine() and let the batch file capture that and do what it wants with the text. Either way, you're going to need a character that's known not to ever be an input character.
I'll give the second approach as an example, but I won't use Forms or WPF. It's too hard to show what goes where. You seem to want a window with a text box, though, so I'll use the following "ConsoleApp1.cs" program and borrow the InputBox() function from Visual Basic (a neat console CS trick on its own!):
using System;
using Microsoft.VisualBasic;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
string answer = Interaction.InputBox("Tell me something");
Console.WriteLine(answer);
}
}
}
Compile that into a .exe file and copy it to the directory you're using for running .bat files. Now try the following within a batch file:
rem #echo off
for /F "delims=~" %%t in ('ConsoleApp1.exe') do set a=%%t
echo.%a%
That's the easy way to get one line of text from a CS program into the .bat file that called it. If you insist on having the CS program create a text file named "textbox1.text", go ahead. Look up how to use the StreamWriter class to do that. Then your .bat file will use a slightly different form of the FOR command:
for /F "delims=~" %%t in (textbox1.text) do set a=%%t
Either way, you need the character after delims= to be a delimiter character that will not by typed by the user. The FOR /F command always parses input lines into tokens separated by whatever delimiter characters you specify (or spaces by default). I use either ~ or ' as characters that don't normally show up in commands or file names.
Justaus3r made a valuable suggestion to use a redirected SET /P command. You can use that, with the above CS program to get the Console.WriteLine output into a variable with no delimiter worries:
ConsoleApp1.exe >textbox1.text
set /P a=<textbox1.text
That works. Piping output from ConsoleApp1 directly to SET ought to work too, but for some reason it doesn't. I've had a number of issues with old batch files that worked in Win7 that don't in Win10. This fails in both CMD and PowerShell, though, so there's something weirder going on that MS just isn't maintaining CMD any more.
I'm trying to work on an environment that its main function is to adopt Visual Programming to create NetLogo code (similar to Google's Blockly).
Right now, I'm using Unity3D to do the job and wondering if it's possible to access NetLogo from it. The objective is to send the generated code directly into the Code Tab, opening a blank project already with the code in the tab (without the user copying and pasting it there).
What I know up until now is that I can open NetLogo from Unity with a function called Process.Start, which takes 2 arguments: the first is the name of the target program to be executed ("NetLogo.exe"), the second one is a list of arguments that can be passed to the targeted program, which solely depends on each program, as found here and here. However, I didn't understand much about these arguments, which is why I recurred to ask.
Do I need to also work on a Java/Scala environment to do this for me with the Extensions API, or can I use these arguments in Process.Start to do it?
Thanks in advance.
You could create a fully formed .nlogo file (it's basically a text file with a specific format), and then launch NetLogo using your Process.start command with that filename as an argument so that NetLogo will open that specific file.
You could even create a .nlogo file as a template (with whatever interface items you want), and then use string search/replace to substitute in the code that you want in the code tab.
Alternatively, fancier things are possible with the Controlling API , but I don't know much about calling JVM code from within Unity, and I suspect that will be a bigger headache than you want... unless you really need a more tight-knit connection to NetLogo, or unless the performance overhead of starting a new NetLogo process each time is unacceptable.
To be honest, I can't say I actually know where to begin with this question. So, I'll start from the beginning.
I have C# code that invokes Process.Start based on a OFD box. Basically allowing the user to open anything from the box, this is absolutely intended.
System.Diagnostics.ProcessStartInfo starter = new System.Diagnostics.ProcessStartInfo(OFPbasicfile.FileName);
starter.UseShellExecute = true;
System.Diagnostics.Process alpha = new System.Diagnostics.Process();
alpha = System.Diagnostics.Process.Start(starter);
Now, it perfectly executes and opens, but I've noticed something of an odd duck. If the first file opens say a .docx file I can then read alpha.ID just fine. However, the next time it opens a .docx file alpha.ID will be assigned a new process ID that corresponds to nothing in the task list. Worse yet, I get absolutely no useful information from alpha as it now has a handler to a non-existent process.
Near as I can figure this is probably something to do with the fact that the program doesn't realize everything perfectly. It tries to create a new process and reserves the ID for it, but then the running instance of word, etc. takes ownership of the started file and my program never gets advised of this change.
Ideally I was trying to find a way to track any and every file opened (process ID, window handles, however worked), but now I'd be more than happy if alpha would just recognize that the process is opened by Word (Or Excel, or what have you).
The basic question boils down to this: When using Process.Start is there any way to ensure it gives the proper process ID (or just the program used to open it) every time?
Or, alternatively: Is there any way to set a process variable with a reference to the exact window it opened?
I've an application same as command line application. I type command, it send command to server and display result on screen.
My application is an executable application on windows and has two feature that help me to easy work: record script and play script.
Now, I want to send command to running application and raise play script button to run sent command on it.
Is there any way to solve this problem in c# language?
Uh-oh. I hope I understood you correctly. I assume you have a third-party application that interacts with some server and is operated by two distinct commands, play and record. You want to write a new application that would invoke these commands somehow, and the problem is this invocation.
You can do it in C#, but the way you do it depends on the way you operate the program. I will show you some cases:
The program is a command line tool. Input is sent via command line parameters when the program is run. Output is gathered via redirections of the standard output of the program. Look at System.Diagnostics.Process.Start and its parameters, namely ProcessStartInfo which contains parameters and input/output redirection options.
The program is a console tool that is not operated via command line parameters. Use the same as above, but feed input via input redirection.
The program is a GUI program with no ability to get input in text form. This is most likely the case. Here you will have to either find a specific way to operate the program such as with an advanced technique called hooking. Or you can send commands as if a user is issuing them. Look at System.Windows.Forms.SendKeys method. It might help. How to get a result here is a big question. You can either parse the screen or monitor some state of a program or something else. No ready solution for everyone here.
Currently running this code to open Business Vision (an application written by someone else that i don't have access to the code of):
ProcessStartInfo myProcessStartInfo = new ProcessStartInfo(BusinessVisionPath);
myProcessStartInfo.UseShellExecute = false;
myProcessStartInfo.RedirectStandardOutput = true;
myProcess.StartInfo = myProcessStartInfo;
myProcess.Start();
StreamReader myStreamReader = myProcess.StandardOutput;
Boolean done = false;
while (done == false)
{
int s = myStreamReader.Read();
Console.WriteLine(s);
if (s == -1)
{
done = true;
Process IProcess = new Process();
ProcessStartInfo IProcessStartInfo = new ProcessStartInfo(QuickPrinterPath);
IProcessStartInfo.WindowStyle = ProcessWindowStyle.Maximized;
IProcess.StartInfo = IProcessStartInfo;
IProcess.Start();
}
}
myProcess.Close();
Console.ReadLine();
Anyways,
this code currently opens my printer program when BusinessVision closes.
Questions:
How (if possible) can i open my program when a certain message box pops up within BV ("Are you sure you want to print an invoice"?)
Is it possible to get any data from the application ? like raw data that i can parse through as it runs or something?
You might want to look into Microsoft's UI Automation. It allows you to read data from the windows of other applications, and interact with other applications' UI programmatically. I used this a couple years ago to automate a bunch of tests on an old VB6 app we had. My code would find the main window of the application, then drill down to the menus/controls/etc that I was interested in. From there I could automate clicks and keystrokes, and then scrape the text/data I wanted from the labels in various windows. I could then pull the data into my .NET app and do what I wanted with it.
In your case you would need some always-running app (such as a Windows service) to constantly monitor the BV program and detect when the message box appears, and then react accordingly by launching your program.
It takes a fair amount of work to understand and get working, but it's very powerful. There are free apps out there that will make it easier to browse the visual hierarchy of windows and see what kind of information is available. Check out Microsoft's UISpy:
http://msdn.microsoft.com/en-us/library/ms727247.aspx
Here are some other links to get you started:
http://en.wikipedia.org/wiki/Microsoft_UI_Automation
http://msdn.microsoft.com/en-us/library/ms747327.aspx
You can try to use one of the approved way to access data.
In the case of Sage BusinessVision there is:
Data import and export as csv availlable manualy from the application.
Direct acces to the Pervasive database, documentation availlable in the help section of the application in a file called BusinessVision Database Structure Reference.chm
API availlable to Sage partners.
1 is the most simple way and nothing is automatic.
2 is more challenging but will give you acces to the underlying data live.
3 requires that you pay and that you meet requirement by Sage.
If you combine 2. and some UI automation you could build some trigger on certain UI events and bring foward new windows filled with data from the database.
Note that UI automation will be extremly fragile to new version of the application and will certainly need to be reworked every time.
You could, although I'm not sure I'd recommend it, Enumerate top level windows, and check if one of them matches the pop-up box.
Except for files or database entries that the application creates, not that I am aware of, unless you want to get into Binary Patching of the application.
If the target is a .NET exe, perhaps the developers were sloppy and exposed their classes and methods publicly. In that case, load the exe as if it were a DLL dependency for your application and call their methods directly.
You could always try a decompiler :)
dotPeek