So I have a program that takes in the user credentials via Windows form, Now through the MessageBox I am currently displaying the user input, what I am trying to do is pass it into my console application so that if the user enters in the correct credentials it then continues in the console application, how do I go about doing this?
you may need to add a while loop to look for a txt file in your console application. In your windows forms application, you can write a success or failure message into a txt file. (Add encryption for security) The moment you write down the information your console app should read it and continue from there.
Algorithm:
1.console application start
2. console app while loop until txt file detected
3. forms app show input screen
4. user enter credential
5. write success or failure into txt file
6. read txt file
7. continue based on credential result
8. Remove txt file
Since the form is also in the console app project (I assume it from your wordings) you can do the following
class Program
{
public static object abc;
static void Main(string[] args)
{
//do something here if required
Form1 frm = new Form1();
if (frm.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
//login success do what ever on success
Console.WriteLine("Login success");
Console.WriteLine(abc.ToString());
}
else
{
Console.WriteLine("Login failure");
Console.WriteLine(abc.ToString());
//login failure
}
Console.ReadLine();
}
}
and the login button click event in your login form class
private void Login_Click(object sender, EventArgs e)
{
if(true)
{
Program.abc = "any success object here";
//on successful login
this.DialogResult= System.Windows.Forms.DialogResult.OK;
}
else
{
Program.abc = "any failure object here";
this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
}
}
Thanks,
Esen
you could host a wcf service within your form app. then make the console app a client. creating a service oriented system is surprisingly easy with wcf. See here for a tutorial. you will learn a lot if you follow this approach
Use IPC (Inter process communication) with Named Pipes.Its easy to implement between two processes check out http://msdn.microsoft.com/en-us/library/bb546085.aspx
Essentially you'll probably have to use some native Windows API functions (Alloc/FreeConsole) and use a WinForms controller.
Semi-pseudocode:
[DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool AllocConsole();
[DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool FreeConsole();
//--- form code
if (Do_validation() && AllocConsole())
{
this.Hide();
this.ShowInTaskbar = false;
Enter_Console_Code();
FreeConsole();
System.Threading.Thread.Sleep(50); //FreeConsole sometimes doesn't finish closing straight away which means your form flickers to the front and then minimizes.
this.ShowInTaskbar = true;
this.Show();
}
//---
private void Enter_Console_Code()
{
string line = string.Empty;
while ((line = Console.ReadLine()) != "q")
Console.WriteLine(line); //pointless code ftw!
}
Essentially what this code does is do your "GUI" validation step, and then if that's successful it attempts to allocate a console for the application. Once the console is allocated it enters "Console Mode" by completely hiding the GUI and displaying only the new console (closing the console closes the application by the way). Your "Console Mode" code is executed, then the console is closed and the GUI comes back.
Related
I'm trying to pull a WinForms application through the Windows App Certification Kit and gets a fail on this test:
<TEST INDEX="17" NAME="Multi user session test" DESCRIPTION="Multi User checks Application invocation in multiple sessions." EXECUTIONTIME="00h:00m:24s.22ms">
<RESULT><![CDATA[FAIL]]></RESULT>
<MESSAGES />
I guess that this is because I only allow one instance of the application to run, like this:
using ( var p = System.Diagnostics.Process.GetCurrentProcess() )
if ( System.Diagnostics.Process.GetProcessesByName( p.ProcessName ).Length > 1 )
{
MessageBox.Show(
"An instance of xxx is already running!",
Title,
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation );
return;
}
It is a tray-application activated by a hot-key combination, registered with this function:
[DllImport( "user32", EntryPoint = "RegisterHotKey", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true )]
public static extern int RegisterHotkey( IntPtr hWnd, int id, int fsModifiers, int vk );
So I guess I have two questions:
1) How can I correctly prevent multiple sessions being run within the same user session but allow several instances across multiple user sessions?
2) Will I be able to register the same hot-key in different user sessions? Or must I somehow unregister and re-register the hot-key when user sessions are switched?
TIA
You can achieve the same effect using a Mutex. See MSDN for details, but the short version is that any mutex created with a name starting with "Local\" will be per-session. Enter a mutex named "Local\MyAppName" and only one instance of your app can run per-session.
Hotkeys are registered per-session and it will not be a problem to register the same hotkey in multiple sessions.
Example Use (from Run single instance of an application using Mutex):
bool ownsMutex = false;
// NOTE: Local is the default namespace, so the name could be shortened to myApp
Mutex myMutex = new Mutex(false, #"Local\myApp");
try
{
ownsMutex = myMutex.WaitOne(0)
}
catch (AbandonedMutexException)
{
ownsMutex = true;
}
if (!ownsMutex)
{
MessageBox.Show("myApp is already running!", "Multiple Instances");
return;
}
else
{
try
{
Application.Run(new Form1());
}
finally
{
myMutex.ReleaseMutex();
}
}
Can anyone help me output a message to a console box when my .exe is called with the wrong parameters?
Yesterday, some very kind people helped me work out how to call my app without a UI
Here is the thread
command line to make winforms run without UI
So, I have told my app to respond to "/silent archive=true transcode=true" and runs without a UI. Great!
Is it possible to output a message to the command window if they get the command incorrect?
as in "Parameters must be specified like this: /silent archive=true transcode=true"
I have tried this but nothing displays in the dos window..
static void Main(string[] args)
{
if (args.Length > 0)
{
if (args[0] == "/silent")
{
bool archive = false;
bool transcode = false;
try
{
if (args[1] == "transcode=true") { transcode = true; };
if (args[2] == "archive=true") { archive = true; };
Citrix_API_Tool.Engine.DownloadFiles(transcode, archive);
}
catch
{
Console.Write ("Hello");
Console.ReadLine();
return;
}
}
}
else
internal sealed class Program
{
[DllImport("kernel32.dll")]
private static extern bool AttachConsole(int dwProcessId);
private const int ATTACH_PARENT_PROCESS = -1;
[STAThread]
private static void Main(string[] args)
{
if(false)//This would be the run-silent check.
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
try
{
throw new Exception("Always throw, as this tests exception handling.");
}
catch(Exception e)
{
if(AttachConsole(ATTACH_PARENT_PROCESS))
{
//Note, we write to Console.Error, not Console.Out
//Partly because that's what error is for.
//Mainly so if our output were being redirected into a file,
//We'd write to console instead of there.
//Likewise, if error is redirected to some logger or something
//That's where we should write.
Console.Error.WriteLine();//Write blank line because of issue described below
Console.Error.WriteLine(e.Message);
Console.Error.WriteLine();//Write blank line because of issue described below
}
else
{
//Failed to attach - not opened from console, or console closed.
//do something else.
}
}
}
}
A problem is that the console would have already returned to taking input from the user. Hence you really want to try to have your exception as fast as you can if you're going to have it, so a fast validation check rather than an exception that might happen down the line, is preferable.
Is there a way for a Console app know whether it has been called from a batch file as opposed to directly at the command prompt?
The reason for asking is to find a way to decide whether to initiate a Console.ReadLine loop or similar to await further input, or whether to exit immediately.
Alternatively, is there a way for a batch file to continue sending input to a Console App that is awaiting further input via ReadLine?
Yes, I know - that's 2 questions. If anyone comments that there's an answer to the second question I'll ask that separately.
Why not pass in a commandline argument to the console app to determine whether to quit immediately or wait.
The batch file can set an environment variable and you can check that in your console application:
in the batch file:
set waitOnDone=0
yourExeFile -arguments
in your Console Application:
var env = System.Environment.GetEnvironmentVariable("waitOnDone");
if (String.IsNullOrEmpty(env) || env != "0")
{
// do something
}
If the batch file knows the input then save the input to a file and feed that to your program like
prog.exe <argument.txt
in the batch file. I think you need not change the source code for this.
Possibly your problem is to read only from stdin if there is a redirecton (from your batch file).
This can also be solved (with dotnet) by detecting if there is an input stream.
Solution from #Hans Passant, SO: how to detect if console in stdin has been redirected
using System.Runtime.InteropServices;
public static class ConsoleEx
{
public static bool OutputRedirected
{
get { return FileType.Char != GetFileType(GetStdHandle(StdHandle.Stdout)); }
}
public static bool InputRedirected
{
get { return FileType.Char != GetFileType(GetStdHandle(StdHandle.Stdin)); }
}
public static bool ErrorRedirected
{
get { return FileType.Char != GetFileType(GetStdHandle(StdHandle.Stderr)); }
}
// P/Invoke:
private enum FileType { Unknown, Disk, Char, Pipe };
private enum StdHandle { Stdin = -10, Stdout = -11, Stderr = -12 };
[DllImport("kernel32.dll")]
private static extern FileType GetFileType(IntPtr hdl);
[DllImport("kernel32.dll")]
private static extern IntPtr GetStdHandle(StdHandle std);
}
And it can be used like this
if (ConsoleEx.InputRedirected)
{
string strStdin = Console.In.ReadToEnd();
}
I have read that Win32 will not allow remote invocation of a process that is interactive and I suspect a Console Application is considered to be interactive by Windows and so instead, if I could convert the following code in to a batch file then I am hoping I can remotely run the batch file on the server computer from a client. Feel free to correct this logic if I'm wrong.
The code is:
namespace PRIMEWebFlyControl
{
class Program
{
// name of the process we will retrieve a handle to
private const string PROCESS_NAME = "PRIMEPipeLine";
private static Process ProgramHandle;
private static string command;
static void Main(string[] args)
{
//Console.WriteLine("This program has been launched remotely!");
TextReader tr = new StreamReader("C:\\inetpub\\wwwroot\\PRIMEWeb\\Executables\\FlyCommand.txt");
command = tr.ReadLine();
tr.Close();
ExecuteCommand();
}
[DllImport("user32.dll")]
static extern bool SetForegroundWindow(IntPtr handle);
private static void ExecuteCommand() {
if (AssignProcessHandle()) {
IntPtr p = ProgramHandle.MainWindowHandle;
SetForegroundWindow(p);
SendKeys.SendWait(command + "~"); // "~" is equivalent to pressing Enter
}
}
private static bool AssignProcessHandle()
{
// ask the system for all processes that match the name we are looking for
Process[] matchingProcesses = Process.GetProcessesByName(PROCESS_NAME);
// if none are returned then we haven't found the program so return false;
if (matchingProcesses.Length == 0) return false;
// else, set our reference to the running program
ProgramHandle = matchingProcesses[0];
// return true to indicate we have assigned the ref sucessfully
return true;
}
}
}
As you will notice the code contains method calls of Windows library methods like SetForegroundWindow() and as I am unfamiliar with batch files, I wondered how the same thing might be achieved.
Many thanks
If I understand well, you are looking for a command line that will execute a bunch of commands that exist inside a text file named (C:\inetpub\wwwroot\PRIMEWeb\Executables\FlyCommand.txt)
Here is what you need to do:
cmd < C:\inetpub\wwwroot\PRIMEWeb\Executables\FlyCommand.txt
In case the path contains spaces, use the following command:
cmd < "C:\inetpub\wwwroot\PRIMEWeb\Executables\FlyCommand.txt"
I am calling an external command line app that continously spits out information into the console window. I'd like to read the information and pass it into my code in order to report progress.
But... I never get any values back at all. If I use sr.ReadToEnd(), it gets stuck until the app closes and just an empty string comes back. What do I need to do to read the text in the command line window of the external app correctly?
Here is my code for the test, doesn't have to be threaded, the stream comes back empty no matter what I seem to do:
private void runApp(string args, string app)
{
ProcessStartInfo pInfo = new ProcessStartInfo(app, args);
pInfo.CreateNoWindow = true;
pInfo.RedirectStandardOutput = true;
pInfo.UseShellExecute = false;
Thread t = new Thread(getProgress);
t.Start();
p = Process.Start(pInfo);
p.WaitForExit();
p.Close();
}
private void getProgress()
{
StreamReader sr = p.StandardOutput;
//Get's stuck here until the app closes, nothing is ever outputted
string output = sr.ReadLine();
//Just for testing, debugging here
while (true)
{
Console.WriteLine(output);
System.Threading.Thread.Sleep(1000);
}
sr.Close();
}
I'm thinking that the thread is started before the process and somehow you are deadlocking. Check out http://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.redirectstandardoutput.aspx
I see this subject is asked again and again every few days... see my answer here:
Running a c++ console app inside a C# console app