Click here to Skip to main content
15,881,600 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
Hi there
I am working on a download application, just like torrent app.
my problem is i am able to hide the application and run the process in background(Download of file), but how to view the same form again using the desktop icon. i tried

C#
Form1 v = new Form1();
v.visible=true;


in main() method but it creates new instance(I know the problem). I also tried

C#
Form1.ActiveForm.Show();


it is also a bug

Form1.Show


also didn't work
Posted
Updated 4-Feb-11 9:24am
v3
Comments
sk saini 3-Feb-11 23:30pm    
Please post your form/application hiding code lines too so that solution may be given exactly the way your problem arises.
Sergey Alexandrovich Kryukov 3-Feb-11 23:43pm    
I changed the title to bring attention to the question in a relevant way, scratched the urgency :-)
(I provided comprehensive answer, anyway :-)

Why don't you

0) minimize the app to the system tray

1) make it a single instance app that will normalize itself if it's already running.

That way, it will still work, and clicking on the desktop app will simply show it on the desktop.
 
Share this answer
 
Comments
Sergey Alexandrovich Kryukov 4-Feb-11 15:33pm    
This is good alternative, especially in "urgent" situation. A 5.
--SA
MCY 4-Feb-11 15:33pm    
yeah, classic and elegant approach
Now, your method will not work.

You should not do anything like that in the "main" function.
My question is: what do you want use to trigger the form re-appearance? The end of download? Otherwise, you need some other form/control to show the form. The best would be implementing the both.

First, let me resolve your problem with Show. This method of your form works, I just tested:

C#
void StartDownloading(/*...*/) {
    this.Hide();
    BackgroundWorker worker = new BackgroundWorker();
    worker.DoWork += delegate(
        object workerSender, DoWorkEventArgs eventArgs) {
        //download file until finished or failed
        this.Invoke(new Action<Form>((form) => {
           form.Show(); }), this);
        };
    worker.RunWorkerAsync();
}


Additionally, in your actual download function, you should send notification to a UI control to show downloading progress on every block of data received and show status. Again, for sending such notification from the worker thread (under DoWork) you should always use Control.Invoke. Invocation mechanism actually serializes delegates: it posts a delegate instance to queue of the UI thread gets it from the queue in its main loop and actually calls the delegate in UI thread.

More advanced advice: you should develop tray application, so the visible tray control in the system tray would always allow you to make the form visible, see status, abort download, etc.
You could start with this simple sample:

http://alanbondo.wordpress.com/2008/06/22/creating-a-system-tray-app-with-c/[^].

Please see my other answer on inter-process aspect of this. This is more complex matter; I added it in response to the follow-up request, but I could see the need in it from the question in first case. It was not property formulated, probably, due to lack of understanding that running the application again always means a new process. Also, this matter is too complex to cover at once.

Good luck,
—SA
 
Share this answer
 
v4
Comments
Rajesh Anuhya 4-Feb-11 0:26am    
Good call
JF2015 4-Feb-11 0:35am    
Once again good advice - great that you take so much time to help the OP's here.
Boost2010 4-Feb-11 3:17am    
Thanks for your suggestions, The thing i am trying to do is like hide the Form using
this.Visible=false;
now the process is running in background.
if i want to veiw the form again i simply click on the desktop icon or open it from Start menu,
For that i was trying to Something like form.show method in Main() and get back the focus of main again.
Th above method is great but how to open that form on simply clicking on the desktop icon as other applications do.
Thanks in advance.
Sergey Alexandrovich Kryukov 4-Feb-11 3:58am    
First, did my method help you to make the form self-showing on completion. If yes, please accept my answer, because it answered exactly what you asked (Voting would not hurt as well.)

Now, about second part: showing on click. What are you talking about? Click on what? If the form is hidden, there is nothing to click on. Or you have another form of the same Application? (Would be not so nice.) That's why I advised tray application. Please see the reference or even make this sample project and see. I tell you, this is the best way, also, very expected by the users.

--SA
Boost2010 4-Feb-11 6:24am    
Thanks i have already voted, actually i want to unhide the application by clicking on its shortcut icon which is placed on Desktop after its installation, or by running application from start menu.
Answering follow-up question: how to show this form again by a click.

What makes this thing very different is your comment:


"I want to unhide the application by clicking on its shortcut icon which is placed on Desktop after its installation, or by running application from start menu."


Do you realize that in item on start menu is not your part of your application? The shortcut icon is the same thing. It will simply run another instance of the same application and show yet another form instead of the one which is hidden. You should not let it happen. This is called single-instance or singleton application behavior. There is no special support of this feature in .NET (probably because if can be done is different ways depending on other requirements).

Let me show only one way I use. You always have process "instance" #1. If you run it again you will always have a process "instance" #2. You can only prevent more processes to be run. You will need #2 anyway to notify #1 to show the form. Hence, whatever you can do, it always involves inter-process communications. This is how (just one way):

Remoting solution:




  1. Use remoting (based on pipes) to communication between instances. You only need to send a notification, no real data needed. The application should act as a listening part (call is "server" and as a connecting part (called it "client")
  2. When in the entry point, before running Application the instance should decide is it #1 or #2. Act as a client and try to connect. If connection is failed: it's #1, proceed with application. If connected, this is #2. Call a function of a remote object (see below) to show the main form. Don't do Application.Run, exit immediately.
  3. When the remoting "server" receives the connection, it's #1. It should show the form in question.
  4. For remoting, use IpcClientChannel and IpcServerChannel. A channel requires a channel name. You can use any string, but how to make it unique? You can include the unique location of your application: System.Reflection.Assembly.GetEntryAssembly().Location. It will return the unique location (assuming application installed only in a single location) of the main module of the entry assembly (usually this is your .exe file).
  5. For remoting you will need a server object and some (rudimentary) interface, call it IShowMainForm,and call the server object class ShowMainForm. So the server object will be class ShowMainForm : System.MarshalByRefObject, IShowMainForm {}. In this class, it is important to implement (override) InitializeLifetimeService. Do it in the simplest way: public override object InitializeLifetimeService() { return null; }. If you forget it, the server will be time-outed.
  6. In the interface IShowMainForm you need just one function void Show. This function is called on the remote object by the process #2 (see above) and implemented by the application's ShowMainForm. It should show your main form and also call it's method Activate.


In the code, this is easy enough, will be few tens of lines, but you need to implement rudimentary remoting. There are no simple ways. The idea is very easy to implement, but .NET code behind remoting is quite sophisticated.

Alternative solutions:



Another option (may be easy, I did not try) is self-hosting WCF. One simple solution is to list all processes, recognize #1 by its location (see my advice about channel name based on unique location, same thing here). The problem is: who to send notification to show main form? I don't know, so what, remoting again? So, this would not add much.

There are more simple inter-process communication (people ofter use system-wide Mutex or event wait handle), but the problem is how to trigger the event to show the main form (some solutions of single-instance application do not provide it).

You can always ignore the problem of second instance completely and deal with the consequences (customer support will answer: "you're not supposed to run it again"). If you use simpler alternative solution without sending notification to #1, you can simply terminate #2 every time it detects #1. This can be more simple. In this case, you will need to show a form by clicking on something else. This "something else" can be a tray icon. Implement a tray icon application (use the reference I gave you in my other answer to start with). This tray icon application will also show the form on click on the system tray. You should show the form in all cases, regardless the status. This would be exact same form which is now your main form.

I would implement both tray icon application and the remoting solution for inter-process communication. Only in this case you will have the features adequate to the application purpose.

The application you're doing is not going to be very simple. So, I would share what I did... See below.

Very alternative solution :-)



I have done a good downloading application for myself. This is a console application based on command line. It can work with the partially downloaded files (complete them). I even posted the full source code in one of my answers. For the tasks like that I hate any UI solution, no matter what is does. It takes so much time and hassle not only to write one, but even to simply use it: click here, click there, copy-paste URL... boring and cumbersome. With good command line I can take existing list of URLs, combine them in a simple batch file and run, get the log in the other file. Easy and simple.

—SA
 
Share this answer
 
Comments
Boost2010 5-Feb-11 12:09pm    
Thanks For you support Forum!

But on my research i have found a nice shortcut..
very effective and true no need of tray icon, dll imports, or any delegate, enum etc

only a four line code in main form and done.
#realJSOP 5-Feb-11 13:16pm    
So update your question with your solution.
Sergey Alexandrovich Kryukov 5-Feb-11 15:32pm    
John, Actually, I do know more simple solution good for this task (I mean single-instance), but after that claim (and probably votes) want to wait and see what it is.
The situation turns ridiculous; at the same time I do understand that in case of the "urgent" situation mentioned by OP most of the solutions can be prohibitively difficult to implement...

--SA
Sergey Alexandrovich Kryukov 5-Feb-11 15:10pm    
I'm just curious: who is so clever to vote "1"? Maybe this person can share better solution.
--SA
Sergey Alexandrovich Kryukov 5-Feb-11 15:11pm    
Boost2010: please share this solution. I really doubt.
--SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900