Windows application and message from asynchronous request - c#

I have developed a class library (former console application). I want to build a windows forms application arround it to do different kind of actions with the application. For example to pass different values of a startup parameter to the class library.
The class library has a lot of console messages and an error object containing all kind of errors.
On the windows forms application I put 2 textboxes. My goal is to output the console messages to the first textbox (txtMessages) and the errormessages to the second textbox (txtErrorMessages).
The windows application will start the process in the class library as a new thread so it's asynchronous which will cause the windows forms application to instant refresh the textboxes
How can I achieve this?

You can e.g. expose 2 events from your library's class:
public event Action<string> outputMessage;
public event Action<string> errorMessage;
In the library, instead of writing to console you raise those messages. Then in the GUI part you subscribe for that 2 messages, and update your textboxes.
Don't forget you need to marshal the events to your GUI thread to update your controls. I think it'll be easier in the GUI part of the app. To do that, you can use any method from here in your event handlers.

Related

launch winforms app on schedule - provided conditions are met?

I am designing an app which basically is going to check for new data, my initial thought for this is to use a windows service. If i get any new data i need to display a winforms app which i'll populate with this data so that the user can acknowledge it.
I know there are restrictions running UI apps from a service so i'm just wondering what others believe is the best approach for both. Also i need to run this on XP
The timer that gets the data
how to launch the WinForms App
As im writing this i've also been toying with the idea of using a console app but nothing seems to be fitting together in terms of functionality.
You can use a regular Winforms app. As soon as the application loads, hide the entry form from within the Form_Load method, this will keep the form hidden from the user. Keep a timer on the entry form that frequently checks for relevant data and pops up windows as and when required.

Dispatcher is not coming on C# Windows Forms Application

I have a C# Windows Forms Application with a progress bar. I want to progress that dynamically based on some method status. I have that method in a separate class, and am creating a new thread for that method, with a delegate to pass the status of the method to the parent thread.
The same situation I am able solve in a WPF application using progressbar.Dispatcher but in a Windows Forms application there is no Dispatcher, even if I use the System.Threading namespace.
progressbar.Dispatcher seems to be available only in a WPF Application.
In winforms you can use the ProgressBar.Invoke or ProgressBar.BeginInvoke to update the control from another thread.
In Windows Form application BackgroundWorker should fit perfectly for your task. In particular, it has ReportProgress method to send progress depending on your calculations and ProgressChanged to track changes from UI thread. See MSDN article for full details
In WinForms the Invoke/BeginInvoke methods are directly on the control objects as you can see from the docs of System.Windows.Forms.Control. So you'd have progressBar.BeginInvoke(...) for example.

Is there any way to run windows form function from command line (cmd file)?

I need to be able to run a Windows Forms function or event (for example a button click) from a command line. How could I do this?
I can't use a console or windows service due to certain constraints.
If you mean re-use a method in your Windows Forms application in a command line (Console) application, then simply reference the assembly containing the class and call that method, a bit like this
static void Main()
{
Form1 form = new Form1();
form.SomeButton_Click();
}
Note that for this to work the SomeButton_Click method and the Form1 class must be public. If this is what you want to do then this is a good indication that the logic contained in SomeButton_Click should be refactored to some common utility class.
If alternatively you want to simulate a button click in a running Windows Forms application then you have a couple of options
Windows Automation (simulating mouse & keyboard events from code)
Inter process communication (sending a message from your command line program to your Windows Forms program to ask it to run that method)
There are many different ways to achieve either of these however both are more complex than just calling a method - it would help if you provided more detail on your problem.
You may be able to do this with a Powershell script: UI Automation with Windows PowerShell

Noob question - how to create a new windows form as part of a plugin?

I am writing a plugin for a C# application and would like to add a dialog window. I have no control over the application, rather, the application loads plugins dynamically using reflection. I am a newbie with windows forms (this is a forms application) but would like to have a dialog window come up to control my plugin. How can I accomplish this?
If I just add a windows form to my application via visual studio no form appears. Application.Run has presumably already been called by the main application. I am almost completely new to forms.
How can I start the form with with my plugin (the plugin has a method that is called when it is started) and make it active?
Edit: I should clarify, the main application application window will not respond (even to minimize or maximize the window) when a plugin is running, so presumably whatever thread is devoted to handling windows messages is used to run the plugin and is, temporarily, not handling any windows messages. Thus my form needs its own thread handling windows messages.
You will need to initialize your code from whatever method the plugin architecture defined as the entry point (where the application will call your plugin).
To show a form, you can call the Show method on it.
// In a method that the plugin framework calls
myPluginForm.Show();
The application that loads your plugin should have some facility to load a window. Check the API documentation. Also, do you know if there are other plugins that can create arbitrary new windows? Usually, the host application can allow the plugin to create certain predefined (by the host) types of windows (such as config, load a file, etc...).
It might also be possible to programmaticaly create a new form and then load it. See here for an example: http://msdn.microsoft.com/en-us/library/system.windows.forms.form.aspx and look for the "examples" section.

Windows Forms + commands from the console in C#

I've read a few topics about programs that combine Windows Forms and console applications, but it seems my question hasn't been solved yet. Is it possible to run a program from cmd-line and to be able to control the application via forms and via cmd-line commands? It means:
for ordinary users of the application to control the application via (Windows Forms) forms,
for debugging and advanced users to control the application via the console (and optionally see what's happening in Windows Forms))
I know that what I want is quite a big deal, and it will probably mean a lot of work, but still I would like to know how to do it properly.
It isn't difficult, just P/Invoke the AllocConsole() API function to create your own console. For example, make your Program.cs source code file look like this:
static class Program {
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
#if DEBUG
CreateConsole();
#endif
Application.Run(new Form1());
}
static void CreateConsole() {
var t = new System.Threading.Thread(() => {
AllocConsole();
for (; ; ) {
var cmd = Console.ReadLine();
if (cmd.ToLower() == "quit") break;
// Etc...
}
FreeConsole();
});
t.IsBackground = true;
t.Start();
}
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
private static extern bool AllocConsole();
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
private static extern bool FreeConsole();
}
You just need to start your Windows Forms application with an ApplicationContext instead of a form itself. You are then not depending on the main form to be shown and can act like an console application.
You could also just create a command-line executable and link with the Windows Forms libraries yourself to use them.
Another way would be to use some kind of starter, that fires up the Windows Forms application, and a command line tool that communicates with the Windows Forms application over local networking, or some other inter-process communication, D-Bus or similiar systems - many ways lead to Rome...
Yes, what you want is very possible. You have options. Some I can think of...:
Use UI Automation to write a controller application that can connect to the Windows Forms application and control it. This is new in Windows Vista. There are managed classes packaged in the System.Windows.Automation namespace, which first shipped in WPF, which arrived in .NET 3.0. (Now that I think about it, I'm not sure "new in Windows Vista" is true. It may be "new in .NET 3.0" which implies it also works on Windows XP. Hmmm....) UI Automation requires no code change to the Windows Forms application, but it can be sort of low-level, because you need to program each mouse click or cut/paste. See the answer to Stack Overflow question Is there a way to control a third-party EXE file from VB.NET?.
Modify your Windows Forms application to expose its function via a WM_COPYDATA interface. Then your client application can communicate with it. Again, the model here is two distinct applications, one of which can control or interrogate the other. The .NET Reflector tool is a good example of this approach. There's a ReflectorController, available as part of the ReflectorAddins project on CodePlex. The controller is a command-line tool, that can send WM_COPYDATA messages to Reflector, to tell it to open a new assembly, navigate to a particular class, and so on.
The code for the controller:
http://reflectoraddins.codeplex.com/sourcecontrol/network/Show?projectName=reflectoraddins&changeSetId=29526#19979
This approach will work for any Windows Forms application. You will need to override the WndProc method. To see how, check The Code Project article Use WM_COPYDATA to send data to/from C++ and C# Windows processes.
I also used this approach to build a Windows Forms-based progress monitor that can visually display the progress of long-running tests.
Within your application, expose a COM server object that can be programmed. This is exactly how Microsoft exposes Office function to applications. Office Automation allows any COM-capable program (C#, VBScript, PowerShell, Perl, PHP, etc.) to "drive" Office applications. The Office application is visible while that is happening. This approach would also require additional code in your Windows Forms application; specifically you have to host a COM object and hook it up to your UI layer. This may be preferable if you want maximum flexibility for superusers - they can write their own scripts to drive that component.
I'm sure there are other options.
I remember seeing IronPython being used in a demo controlling Windows Forms from Python's command line interface (IDLE).
Edit:
I could not find the original video but this one should show what is possible without too much effort. See this video and jump to 19:00.
This would be possible. You will have to look into threading the Windows Forms form, possibly with the use of a separate application domain within the same process. You might look into creating a proxy object (a kind of message class inheriting MarshalByRefObject).
Normally when looking at your application, you have an UI layer and a business layer (and a data layer, and who knows many more layers). You can think of the console client as an UI layer (with simple command inputs) and the Windows Forms client as another one.
Simply check at application startup for command-line arguments. If there are arguments specified, instantiate the simple console classes, otherwise instantiate the (probably more complex) Windows Forms classes.
If you want your changes to reflect in the Windows Forms application (while controlling it from the console application) setup your applications as much as you can with databinding. Let your business layer reflect what's actually going on in your application.

Categories

Resources