show another form - c#

I want to show windows of another application if it is hidden. More specifically, I want to show the main window of already launched application if the user tries to launch it again. I've already implemented monitoring of duplicate application launches. Tried to do as in here but failed. Thinking of doing it using remoting, but I understand that this is not the best practice, although I won't need to bother with Windows API in that case.

That's a pretty hackish way of doing things. I'd advise using named pipes (System.IO.Pipes) to signal the first copy of your app. The first copy, upon receiving the signal, will activate the window itself. And no worries about any permissions either.

Another pretty easy way to do it is using a Windows Event, represented in .NET as the System.Threading.EventWaitHandle class.
Create a thread in the application, that all it does is wait on a named event. When the event is signalled, this thread will use Form.BeginInvoke to make the main window appear, and go back to wait on the event.
From the new instance of the application, you will only have to signal the event.
This requires a little less work than using pipes.
Note that either way (using pipes, windows, or events), you always have to deal with permissions.
For example, if UAC is enabled, and the existing application instance is running as admin, the new instance may not be able to send it the message to show the window, unless you made sure to set the proper permissions (e.g. on the pipe or the event, whatever your method is) in advance.

I've already implemented it using remoting, but I'll consider other ways of doing this when I have more free time. Here's how I did it:
In the form class we have:
public Main()
{
InitializeComponent();
this.ShowFromFormShower = new FormShower.ShowFromFormShowerDelegate(this.ShowFromFormShower1);
FormShower.Register(this);
}
private void ShowFromFormShower1()
{
this.Show();
this.WindowState = FormWindowState.Normal;
this.BringToFront();
}
public PKW.FormShower.ShowFromFormShowerDelegate ShowFromFormShower;
Also a remoting class needs to be created:
public class FormShower : MarshalByRefObject
{
/// <summary>
/// For remote calls.
/// </summary>
public void Show()
{
if (FormShower.m == null)
throw new ApplicationException("Could not use remoting to show Main form because the reference is not set in the FormShower class.");
else
FormShower.m.Invoke(FormShower.m.ShowFromFormShower);
}
private const int PortNumber = 12312;
private static Main m = null;
public delegate void ShowFromFormShowerDelegate();
internal static void Register(Main m)
{
if (m == null) throw new ArgumentNullException("m");
FormShower.m = m;
ChannelServices.RegisterChannel(new TcpChannel(FormShower.PortNumber), false);
RemotingConfiguration.RegisterActivatedServiceType(typeof(FormShower));
}
internal static void CallShow()
{
TcpClientChannel c = new TcpClientChannel();
ChannelServices.RegisterChannel(c, false);
RemotingConfiguration.RegisterActivatedClientType(typeof(FormShower), "tcp://localhost:"+PortNumber.ToString());
FormShower fs = new FormShower();
fs.Show();
}
}
So if the user tries to launch the application a second time the application launches FormShower.CallShow method.

Related

C# form is blocked after creation

I am creating a Form when a certain event occurs. I put this created Form into a static member of the class where it is created. I debugged the code and everything works fine but the Form stays blocked and the user can't do anything in this window. It just appears with a loading animation (see picture). So nothing in the opened window is clickable, you can't even close it.
class CallManagementObserver : CallObserver
{
private static FrmIncomingCall frmCurrentCall;
public CallManagementObserver()
{
}
public void callChangedEvent(CallEv[] events)
{
foreach (CallEv currentEvent in events)
{
switch (currentEvent.getID())
{
case TermConnRingingEv.ID:
// Incoming call
frmCurrentCall = new FrmIncomingCall(currentEvent);
frmCurrentCall.Show();
frmCurrentCall.Update();
break;
case CiscoCallInfoChangedEv.ID:
// User accepted external call on terminal
frmCurrentCall.Close();
break;
case TermConnActiveEv.ID:
// User is in call
frmCurrentCall.Close();
break;
case ConnDisconnectedEv.ID:
// Caller has hung up
frmCurrentCall.Close();
break;
default:
break;
}
}
}
}
}
As you can see above I wrote my own Form class whose code is here:
public partial class FrmIncomingCall : Form
{
Call incomingCall;
CallEv currentEvent;
public FrmIncomingCall(CallEv currentEvent)
{
InitializeComponent();
this.currentEvent = currentEvent;
this.incomingCall = currentEvent.getCall();
}
private void initGui()
{
Connection[] callConnections = incomingCall.getConnections();
Address caller = callConnections[1].getAddress();
lblIncomingCallSource.Text = caller.getName();
}
private void btnAcceptCall_Click(object sender, System.EventArgs e)
{
TermConnEv termConnEv = (TermConnEv)currentEvent;
TerminalConnection termConn = termConnEv.getTerminalConnection();
termConn.answer();
}
private void frmIncomingCall_Load(object sender, System.EventArgs e)
{
initGui();
}
}
When I show the Form via ShowDialog() it is usable but the program stops (since this is what dialogs are made for I guess).
Any ideas what I'm doing wrong? Nothing freezes, the program is running correctly.
Well, your application is poorly designed... It seems that you have no idea of what multithreading is and why you should use it.
If the application hangs forever, then either there is a deadlock (something like the dialog wait on the calling system and the calling system wait on the dialog).
As I have no idea what CallEv is and how it is intended to be used.
Well, if the calling system works and the UI is never updated, then obviously, you never let the UI have time to be updated because your UI thread is 100% of the time using the calling system or waiting on it.
That means that the calling system should probably be used from another thread and that you should have some communication between both threads...
It might also be possible that the calling system might be used in many different ways (as it would be the case for serial port and TCP communication) where one could use what fit most with his application.
Another problem with your code is that when you close a dialog, as far as I know it cannot be used anymore without recreating the dialog as the dialog would be disposed... So you would need to set the formCurrentCall to null and update any affected code. Alternatively, you might hide the form instead and show it again when required.
In any case, it is hard to help you because we don't have any idea of what is CallEv and other classes or events in your code. Also, we have no idea which code is executing when the UI is not responding (or updated). So the question do not have enough informations. In fact, such problem are way easier to debug using a debugger as it is far easier to see what code is run and which line of code take time to execute or even to see which code is not executed.

Trying to close a form after the next one is shown in C# cf

I've been studying Android lately and I tried to port one of its functions to C# compact framework.
What I did is create an Abstract class that I call Activity.
This class looks like this
internal abstract class Activity
{
protected Form myForm;
private static Activity myCurrentActivity = null;
private static Activity myNextActivity = null;
internal static void LoadNext(Activity nextActivity)
{
myNextActivity = nextActivity;
if (myNextActivity != null)
{
myNextActivity.Show();
if (myCurrentActivity != null)
{
myCurrentActivity.Close();
myCurrentActivity = null;
}
myCurrentActivity = myNextActivity;
myNextActivity = null;
}
}
internal void Show()
{
//PROBLEM IS HERE
Application.Run(myForm);
//myForm.Show();
//myForm.ShowDialog();
//
}
internal void Close()
{
myForm.Close();
}
internal void GenerateForm()
{
///Code that uses the Layout class to create a form, and then stores it in myForm
//then attaches click handlers on all the clickable controls in the form
//it is besides the point in this problem
}
protected abstract void Click(Control control);
//this receives all the click events from all the controls in the form
//it is besides the point in this problem
}
The problem I have is with running the part of the Show() command
Basically all my classes implement the above class, load an xml file and display it.
When I want to transition to a new class/form (for example going from ACMain to ACLogIn)
I use this code
Activity.LoadNext(new ACLogIn);
Which is supposed to load the next form, show it , and unload the current form
I have tried these solutions (in the Show() method) and here is the problem with each one
using myForm.ShowDialog()
This works, but blocks execution, which means that the old form does not close, and the more I move between the forms the more the process stack increases
using myForm.Show()
This works, closes the old form after the old one is shown, but immediately after that closes the program and terminates it
using Application.Run(myForm)
This works only on the first form loaded, when I move to the next form, it shows it then throws an exception saying "Value does not fall within the expected range"
Can someone help me fix this or find an alternative?
If you're really after creating your own framework for this navigation, you need to re-work you thinking. The Form instance passed into Application.Run must never close - when it does, Application.Run finishes execution and (typically) your static void Main entry point exits and the app terminates.
What I would propose is that you change your Activity to either being a UserControl:
public abstract class Activity : UserControl
{
....
}
or Composing one
public abstract class Activity
{
private UserControl m_control;
....
}
Then instead of closing and showing Forms, parent all of the Activities inside the main Form as a container.
As fair warning, this is going to get complex when you start wanting to show things in a Tab motif instead of a Stack, or having split views. Frameworks seem simple to create, but they're not so I'd at least consider using something already done unless you have compelling reasons to want to roll your own.
Application.Run is generally used with the overload that takes a Form parameter. This would be the "main" form that would be responsible for starting/showing other forms. This "main" form could be "hidden". But, I think that's a little awkward.
Alternatively, you don't need a main form, you can use Application.Run() to start a message pump to process Windows messages; but, then the thread is busy processing messages and cannot show dialogs (they must be shown in the thread that is running Application.Run). You can get around this by creating one or more form objects before calling Application.Run and these form objects could create a Timer object that would call Form.Show() or Form.ShowDialog() on the Timer.Tick event handler so that for form is shown after the call to Run. I think this is a little awkward as well.
Both of these solutions kind of circumvent the way you're expected to use Windows and WinForms; so, I think you need to think about re-designing this application to work with the way that Windows and .NET works.

Application.Current "null" in console application

I'm currently trying to use a WPF component that makes use of Application.Current from a WPF application, however due to several reasons I never call Application.Run (nor is that an option). The result is a NullReferenceException.
I'm basically trying to display multiple instances of the same WPF window from what would be a console application.
Any advice (and code samples in C#/F#) would be welcome!
Thanks in advance
Just to offer an alternative solution.
It is possible to keep an application running without any windows open. To me this feels less 'hackish'. :) http://msdn.microsoft.com/en-us/library/system.windows.application.shutdownmode.aspx
public class AppCode : Application
{
// Entry point method
[STAThread]
public static void Main()
{
AppCode app = new AppCode();
app.ShutdownMode = ShutdownMode.OnExplicitShutdown;
app.Run();
...
app.Shutdown();
}
}
EDIT:
Ok this got a bit cumbersome. Application.Run will block, so it needs to run in its own thread.
When it does run in its own thread, any interaction between your main thread and your ui thread had best be done by Application.Current.Dispatcher.Invoke. Here is some working code, that assumes you have a class that inherits from Application. I'm using a modified App.xaml/App.xaml.cs that a WPF project template creates for you, to get nice handling of ResourceDictionaries for free.
public class Program
{
// Entry point method
[STAThread]
public static void Main()
{
var thread = new System.Threading.Thread(CreateApp);
thread.SetApartmentState(System.Threading.ApartmentState.STA);
thread.Start();
// This is kinda shoddy, but the thread needs some time
// before we can invoke anything on the dispatcher
System.Threading.Thread.Sleep(100);
// In order to get input from the user, display a
// dialog and return the result on the dispatcher
var result = (int)Application.Current.Dispatcher.Invoke(new Func<int>(() =>
{
var win = new MainWindow();
win.ShowDialog();
return 10;
}), null);
// Show something to the user without waiting for a result
Application.Current.Dispatcher.Invoke(new Action(() =>
{
var win = new MainWindow();
win.ShowDialog();
}), null);
System.Console.WriteLine("result" + result);
System.Console.ReadLine();
// This doesn't really seem necessary
Application.Current.Dispatcher.InvokeShutdown();
}
private static void CreateApp()
{
App app = new App();
app.ShutdownMode = ShutdownMode.OnExplicitShutdown;
app.Run();
}
}
The following is the intended behavior of Application class:
The first open window is the MainWindow.
The only window in the list becomes the MainWindow (if others are to
be removed).
Application Class is designed to exit if no windows are present in
windows list.
Check this link.
So basically you cannot run an Application, without any window open. Keep a window open but hidden.
If I have misunderstood your problem, then perhaps the following similar cases might help:
Managing Application Resources when WPF is Hosted.
When running unit tests in Visual Studio 2008

How to implement single instance per machine application?

I have to restrict my .net 4 WPF application so that it can be run only once per machine. Note that I said per machine, not per session.
I implemented single instance applications using a simple mutex until now, but unfortunately such a mutex is per session.
Is there a way to create a machine wide mutex or is there any other solution to implement a single instance per machine application?
I would do this with a global Mutex object that must be kept for the life of your application.
MutexSecurity oMutexSecurity;
//Set the security object
oMutexSecurity = new MutexSecurity();
oMutexSecurity.AddAccessRule(new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null), MutexRights.FullControl, AccessControlType.Allow));
//Create the global mutex and set its security
moGlobalMutex = new Mutex(True, "Global\\{5076d41c-a40a-4f4d-9eed-bf274a5bedcb}", bFirstInstance);
moGlobalMutex.SetAccessControl(oMutexSecurity);
Where bFirstInstance returns if this is the first instance of your application running globally. If you omited the Global part of the mutex or replaced it with Local then the mutex would only be per session (this is proberbly how your current code is working).
I believe that I got this technique first from Jon Skeet.
The MSDN topic on the Mutex object explains about the two scopes for a Mutex object and highlights why this is important when using terminal services (see second to last note).
I think what you need to do is use a system sempahore to track the instances of your application.
If you create a Semaphore object using a constructor that accepts a name, it is associated with an operating-system semaphore of that name.
Named system semaphores are visible throughout the operating system, and can be used to synchronize the activities of processes.
EDIT: Note that I am not aware if this approach works across multiple windows sessions on a machine. I think it should as its an OS level construct but I cant say for sure as i havent tested it that way.
EDIT 2: I did not know this but after reading Stevo2000's answer, i did some looking up as well and I think that the "Global\" prefixing to make the the object applicable to the global namespace would apply to semaphores as well and semaphore, if created this way, should work.
You could open a file with exclusive rights somewhere in %PROGRAMDATA%
The second instance that starts will try to open the same file and fail if it's already open.
How about using the registry?
You can create a registry entry under HKEY_LOCAL_MACHINE.
Let the value be the flag if the application is started or not.
Encrypt the key using some standard symmetric key encryption method so that no one else can tamper with the value.
On application start-up check for the key and abort\continue accordingly.
Do not forget to obfuscate your assembly, which does this encryption\decryption part, so that no one can hack the key in registry by looking at the code in reflector.
I did something similar once.
When staring up the application list, I checked all running processes for a process with identical name, and if it existed I would not allow to start the program.
This is not bulletproof of course, since if another application have the exact same process name, your application will never start, but if you use a non-generic name it will probably be more than good enough.
For the sake of completeness, I'd like to add the following which I just found now:
This web site has an interesting approach in sending Win32 messages to other processes. This would fix the problem of the user renaming the assembly to bypass the test and of other assemblies with the same name.
They're using the message to activate the main window of the other process, but it seems like the message could be a dummy message only used to see whether the other process is responding to it to know whether it is our process or not.
Note that I haven't tested it yet.
See below for full example of how a single instace app is done in WPF 3.5
public class SingleInstanceApplicationWrapper :
Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase
{
public SingleInstanceApplicationWrapper()
{
// Enable single-instance mode.
this.IsSingleInstance = true;
}
// Create the WPF application class.
private WpfApp app;
protected override bool OnStartup(
Microsoft.VisualBasic.ApplicationServices.StartupEventArgs e)
{
app = new WpfApp();
app.Run();
return false;
}
// Direct multiple instances.
protected override void OnStartupNextInstance(
Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventArgs e)
{
if (e.CommandLine.Count > 0)
{
app.ShowDocument(e.CommandLine[0]);
}
}
}
Second part:
public class WpfApp : System.Windows.Application
{
protected override void OnStartup(System.Windows.StartupEventArgs e)
{
base.OnStartup(e);
WpfApp.current = this;
// Load the main window.
DocumentList list = new DocumentList();
this.MainWindow = list;
list.Show();
// Load the document that was specified as an argument.
if (e.Args.Length > 0) ShowDocument(e.Args[0]);
}
public void ShowDocument(string filename)
{
try
{
Document doc = new Document();
doc.LoadFile(filename);
doc.Owner = this.MainWindow;
doc.Show();
// If the application is already loaded, it may not be visible.
// This attempts to give focus to the new window.
doc.Activate();
}
catch
{
MessageBox.Show("Could not load document.");
}
}
}
Third part:
public class Startup
{
[STAThread]
public static void Main(string[] args)
{
SingleInstanceApplicationWrapper wrapper =
new SingleInstanceApplicationWrapper();
wrapper.Run(args);
}
}
You may need to add soem references and add some using statements but it shoudl work.
You can also download a VS example complete solution by downloading the source code of the book from here.
Taken From "Pro WPF in C#3 2008 , Apress , Matthew MacDonald" , buy the book is gold. I did.

Message pump in .NET Windows service

I have a Windows Service written in C# that handles all of our external hardware I/O for a kiosk application. One of our new devices is a USB device that comes with an API in a native DLL. I have a proper P/Invoke wrapper class created. However, this API must be initialized with an HWnd to a windows application because it uses the message pump to raise asynchronous events.
Besides putting in a request to the hardware manufacturer to provide us with an API that does not depend on a Windows message pump, is there any way to manually instantiate a message pump in a new thread in my Windows Service that I can pass into this API? Do I actually have to create a full Application class, or is there a lower level .NET class that encapsulates a message pump?
Thanks all for your suggestions. Richard & overslacked, the link you provided in the comments was very helpful. Also, I did not have to allow the service to interact with the desktop in order to manually start a message pump with Application.Run. Apparently, you only need to allow the service to interact with the desktop if you want Windows to start a message pump automatically for you.
For everyone's edification, here is what I ended up doing to manually start a message pump for this 3rd party API:
internal class MessageHandler : NativeWindow
{
public event EventHandler<MessageData> MessageReceived;
public MessageHandler ()
{
CreateHandle(new CreateParams());
}
protected override void WndProc(ref Message msg)
{
// filter messages here for your purposes
EventHandler<MessageData> handler = MessageReceived;
if (handler != null) handler(ref msg);
base.WndProc(ref msg);
}
}
public class MessagePumpManager
{
private readonly Thread messagePump;
private AutoResetEvent messagePumpRunning = new AutoResetEvent(false);
public StartMessagePump()
{
// start message pump in its own thread
messagePump = new Thread(RunMessagePump) {Name = "ManualMessagePump"};
messagePump.Start();
messagePumpRunning.WaitOne();
}
// Message Pump Thread
private void RunMessagePump()
{
// Create control to handle windows messages
MessageHandler messageHandler = new MessageHandler();
// Initialize 3rd party dll
DLL.Init(messageHandler.Handle);
Console.WriteLine("Message Pump Thread Started");
messagePumpRunning.Set();
Application.Run();
}
}
I had to overcome a few hurdles to get this to work. One is that you need to make certain to create the Form on the same thread that you execute Application.Run. You also can only access the Handle property from that same thread, so I found it easiest to simply initialized the DLL on that thread as well. For all I know, it is expecting to be initialized from a GUI thread anyway.
Also, in my implementation, the MessagePumpManager class is a Singleton instance, so that only one message pump runs for all instances of my device class. Make sure that you truly lazy-initialize your singleton instance if you start the thread in your constructor. If you start the thread from a static context (such as private static MessagePumpManager instance = new MessagePumpManager();) the runtime will never context switch into the newly created thread, and you will deadlock while waiting for the message pump to start.
You have to make a Form, Windows services do not interact with the desktop by default, so you have to set the service to interact with the desktop and installing it can be a bit of a pain. The Form will not be visible though. Microsoft has been deliberately making this harder and harder to do because of security issues.
Just make a message-only window, denoted by the HWND_MESSAGE parameter in the call to CreateWindowEx. Granted, this is C code, but you can easily make these structs and P/Invoke calls in C#.
WNDCLASS w;
HWND handle;
w.hInstance = (HINSTANCE)GetModuleHandle(...); // Associate this module with the window.
w.lpfnWndProc = ... // Your windowproc
w.lpszClassName = ... // Name of your window class
RegisterClass(&w)
handle = CreateWindowEx(0, w.lpszClassName, w.lpszClassName, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, wc.hInstance, NULL);

Categories