|
The only scheme I can think of to accomplish such things would be using two EXE files: one is your actual application, the other small one contains the logic to close the app, download/install the new version, and launch it again.
BTW: I don't expect an automatic install, I'd rather hope the new files overwrite existing files and no renewed install is involved at all.
Remark: Are you sure you want to put your stuff in system32? that will probably go wrong on modern Windows editions (Vista, Win7) due to security, and possibly also on 64-bit Windows (Win7 often is 64-bit).
|
|
|
|
|
Thank you for your insight, Luc. No..I am not sure about the System 32 thing. On my Win XP system, it seems like that was the place to put these. That can be easily changed. Thank you for your advice. Re: the second EXE....I am not sure just what that would look like in code, or how to call it, or from where. If you have some kind of template or flow that can get me started, I would appreciate that. I wish I knew how Adobe does it. It's very clean and really fully automatic. That is what I am trying to duplicate here. Thank you for your help.
Best Regards, Pat
|
|
|
|
|
I don't have a simple code example around. There are many programs that update themselves, FireFox is one example. One EXE can call another through Process.Start() .
I suggest you learn to use Google and search for some articles. Maybe this one[^] is OK, I don't know, I haven't read it.
|
|
|
|
|
Hi,
I didn't setup such a system myself, but I'm aware of an application that has this feature. It's source code is available, thus you can watch for it and try to adapt it to your needs.
This application is called EveHQ ; it's related to a MMORPG, and you can watch for the source code @ evehq.battleclinic.com[^].
The relevant project is named EveHQPatcher inside the solution. If you use part of this code, don't forget to give credits to the original developper (and maybe contact him before doing so).
I hope it will help you solve your problem.
Kind regards.
|
|
|
|
|
Thank you Phil. The funny thing is that I actually have all the components working except for the final install. I suppose, technically, I could set up a simple message box that points to the location and tells the user to do the install by clicking on the downloaded setup file when he attempts to restart the application, but I wanted to make it all happen automatically when the program was restarted. A suggestion was made about running an exe inside of an exe, but I do not really understand that and I have no sample of how to do it. I will definitely look into your suggestion though, and I appreciate your time. Thank you.
Best Regards, Pat
|
|
|
|
|
You're welcome Pat
|
|
|
|
|
Hi,
First write code to check for new version of your binaries in your main application.
When your main application starts, check for new version of binaries.
And checks every half and hour or whatever u like, whether any new version of binaries are available or not.
If there is any new version of binaries are available than download and install it.
While installing new binaries, prompt the user that New binaries are available and your application is going to close, after installing new binaries start your main application.
I hope you got cleared.
I am not surfing codeproject regularly, So if u want any more information get back to me at sunil.gohel@hotmail.com
Regards,
Sunil G.
modified on Monday, August 30, 2010 9:19 AM
|
|
|
|
|
Hello Sunil,
Thank you for your advice here. OK, I have reached this point in the application. The application recognizes the new file is available and downloads it to a folder...then shuts down. So, how do I make the application do the install after it is restarted? I suppose I am looking for a piece of code that will run the new exe file but only after the application has shut itself down, and then (would be nice) perhaps even relaunch after the update has been installed.
In short, how do I accomplish this
<<<<<'after installing new binaries start your main application.'>>>>>
in C# code?
Thank you, Pat
|
|
|
|
|
Hi,
There should be 2 exes one is your main exe and 2nd should be the exe which checks new version download it and install.
When new version binaries are successfully downloaded prompt the user accordingly and shuts your main exe through 2nd exe, after successfully installation of new binaries call your main exe through 2nd exe.
I hope u got cleared
Regards,
Sunil G.
|
|
|
|
|
I use the following for my one EXE updating solution. It may not follow best practices, but it works.
The idea is that you rename your current exe to a temp file, rename your new exe to your "normal" filename, then restart the process. You can rename the exe while its running, but you don't delete it. Instaed, you delete the "old" exe during your next update (or after the restart) and that way its no longer loaded in memory.
void UpdateAndRestart()
{
string myNewExeLoc = @"C:\My Folder\myNewExe.new";
string myCurrentExe = System.Reflection.Assembly.GetExecutingAssembly().Location;
string myBakExe = myCurrentExe + ".bak";
if (System.IO.File.Exists(myBakExe))
System.IO.File.Delete(myBakExe);
System.IO.File.Move(myCurrentExe, myBakExe);
System.IO.File.Move(myNewExeLoc, myCurrentExe);
System.Diagnostics.Process newP = new System.Diagnostics.Process();
newP.StartInfo.FileName = myCurrentExe;
newP.StartInfo.Arguments = "/updated"
newP.Start();
System.Environment.Exit(0);
}
Edit:
I should note that I use a System.Threading.Mutex to make sure that only one version of my program is running at a time, so I can be sure that when I delete the old filename that there isn't still a version loaded in memory. I also check for the "/updated" argument on startup and deconflict any issues with the Mutex if the other version still hasn't unloaded (to mitigate race-condition errors).
|
|
|
|
|
Interesting. I wasn't aware an EXE could rename itself. If that is true under all normal circumstances, your scheme should be quite adequate and simpler than the two-EXE scheme I suggested.
|
|
|
|
|
Yes, I've been using the "rename the current exe" trick for several years now. In pseudo-code
compute "old" name (foo_old.exe?)
delete old named file
rename current file to old named file
rename new file to current file name
run current file
exit "this" image (now the old named file)
The hard part is dealing with any error conditions that happen during the sequence, those could lead to an unusable application (no current file)
|
|
|
|
|
Thank you one and all, and I mean that sincerely. I learned a lot just researching your suggestions. It looks like more than one of these solutions will work, however, in an effort to keep it as simple (to me) as possible, this is what I have done (and it works). First, I created 2 databases...one internal (.mdb) and another external (Ms Sql). Each has a table with the most current version listed. To begin with, I created a splash page that checks for the most current version in the remote DB. If that does not match the internal DB that is called from the Splash page, it commands a download from my server with the newest version (simply called setup so there is no difference in the name). The WebClient class does an asynchronous download and then sets a value in the local DB so that the next method called will recognize that a download has been received (in a local folder) but not installed. The application is then forced to shut down. On restart, the CheckForNewInstall Method (also on the Splash page) then runs the install using the Process.Start Method and installs the update and also updates the local DB value so the application knows the install has completed successfully and now matches the remote DB value. I was fearful that running the update from the Splash page before it was completely shut down would throw an Exception, but it does not. I have tried it on 3 remote computers that are running the application now (all using Win XP SP3) and it works every time.....go figure.
I wanted to throw this out there in the event that it might help someone else. I can list the actual code if it would be of help to someone or I can place it in a file on my website for download, in as much as you all have helped me. It is much appreciated. Thanks again...Best Regards, Pat
|
|
|
|
|
Glad to hear it! Happy Coding!
Matt
|
|
|
|
|
Something else I do to deal with the possible race condition that you're talking about is I pass the Process ID of the current (old) exe to the new exe via arguments.
Here is a slightly modified version of what I posted earlier:
void UpdateAndRestart()
{
string myNewExeLoc = @"C:\My Folder\myNewExe.new";
string myCurrentExe = System.Reflection.Assembly.GetExecutingAssembly().Location;
string myBakExe = myCurrentExe + ".bak";
if (System.IO.File.Exists(myBakExe))
System.IO.File.Delete(myBakExe);
System.IO.File.Move(myCurrentExe, myBakExe);
System.IO.File.Move(myNewExeLoc, myCurrentExe);
System.Diagnostics.Process p = System.Diagnostics.Process.GetCurrentProcess();
System.Diagnostics.Process newP = new System.Diagnostics.Process();
newP.StartInfo.FileName = myCurrentExe;
newP.StartInfo.Arguments = string.Format("/restart {0}", p.Id);
newP.Start();
System.Environment.Exit(0);
}
void Main(string[] args)
{
if (args.Length > 0)
{
switch (args[0].ToLower())
{
case "/restart":
int oldPid;
if (args.GetUpperBound(0) < 1 || !int.TryParse(args[1], out oldPid))
break;
Process p = System.Diagnostics.Process.GetProcessById(oldPid);
if (p != null)
p.Kill();
break;
}
}
}
|
|
|
|
|
Matt,
Thank you for your excellent and detailed response. Although my simpler solution seems to be working, I do not trust it. Frankly, it's very confusing to have something work and not really understand it, especially when everything I have ever done says that you cannot run these two .exe's simultaneously (I keep waiting for it to crash...it's very disconcerting). I am going to see if I can get your solution to work with my application...at least I can understand the logic behind it. I will keep you informed. I am also marking your answer as the solution, since I am sure that it is at least one correct way of resolving this issue. Thanks again...Best Regards, Pat
|
|
|
|
|
No problem. I've gotten a lot of help from this forum so it's nice to be able to give back a bit.
To address your questions, you are able to run multiple instances of an exe at the same time (calculator.exe) because Windows reads the exe from disk to RAM, then executes the code from memory. So when you run a program again while another instance is still running, windows is actually giving each program it's own memory space with it's own global variables, etc.
Now, as far as I can tell, Windows doesn't let you delete an EXE while an instance of the code is loaded in memory. That is why in the solution we rename it (Move) then delete it the second time around once we know that the instance which was using the "old" code is now terminated. That is why I suggest passing the PID of the previous instance to the new one. We must make sure the old process is terminated before we try to delete the old EXE.
Now for most simple programs, having multiple instances loaded in memory isn't a big deal, and is sometimes desirable (notepad.exe). Where it becomes an issue is when both of them try to use the same resource and they aren't aware of each other. It very similar to the issues you could run in to when multithreading.
Luckily, Windows again gives us a few tools to deal with multiple instances of our app. I believe the System.Threading.Mutex is the easiest to use, and I think the MSDN code samples are pretty straight forward. The bottom line is that it gives you a single, system wide "token" that your program can check for on startup, and if the token is already in use, then it knows that there is another instance already running. I'm sure this is very similar to how a lot of apps implement the logic of Activating an existing instance when you try and run a new one, like Skype or MSN Messenger.
You can also set up a Client/Server type setup where the first instance starts a TCP server and all the other instances check for the server on startup. If it exists, then you can use the Client/Server to have your instances talk to one another. I believe in .NET 3.0 you can also use Named Pipes to talk between instances, but as I'm only able to program to .NET 2.0 for work, I don't have any experience with them.
The Mutex method can be implemented with a few lines of code (wrap it in a using statement!) and it is a proactive way to make sure that only one instance of your app is running at a time.
Wow, that turned in to a short story. Hope it all works out for you and you can get your head wrapped around everything!
Matt
|
|
|
|
|
hi all
i am a newbie to C# and i am trying to devlop a application for SENDING SMS through PC and i am trying to decode a application (myphoneexplorer) using portmonitor.
now i am in a portion of understanding the handling the setting of COMPORT.
this is the portmon result
IRP_MJ_CREATE Options: Open
IOCTL_SERIAL_SET_BAUD_RATE Rate: 921600
IOCTL_SERIAL_SET_LINE_CONTROL StopBits: 1 Parity: NONE WordLength: 8
IOCTL_SERIAL_SET_CHAR EOF ERR BRK EVT XON XOFF
IOCTL_SERIAL_SET_HANDFLOW Shake:1 Replace:40 XonLimit XoffLimit
IOCTL_SERIAL_SET_QUEUE_SIZE InSize: 16384 OutSize: 16384
IOCTL_SERIAL_SET_QUEUE_SIZE InSize: 16384 OutSize: 16384
IOCTL_SERIAL_SET_WAIT_MASK Mask: RXCHAR
IOCTL_SERIAL_SET_TIMEOUTS RI:20 RM:10 RC:2000 WM:10 WC:200
Can somebody guideon this explain the pasted content and how to set it through C#
Regards
Venkat.S
|
|
|
|
|
dear all
i am newbe with C#, i got a problem when i am debug, the issue is as following:
Error 2 The type 'UIS_Application.MainDialog' already contains a definition for 'toolBtnRun' C:\Documents and Settings\LI ZHIYUAN\Desktop\UIS Application\UIS Application\UIS Application\MainDialog.Designer.cs 555 54 UIS Application
how to solve this issu. thanks a lot.
|
|
|
|
|
So you declared toolBtnRun more than once. Use "Find in Files (entire project)" to locate the redundant one(s).
|
|
|
|
|
thanks sir, acutally i found already by this way, i couldn't find where i definded more than one. and moreever i couldn't display the "MainDialog GUI", when i double clicked the "maindialog" then the following dialog display and content is : object reference not set to an instances of an object. how to solve it. thanks
|
|
|
|
|
the object reference not set to an instances of an object refers to the fact that you have no
instance of MainDialog initialized.
Ex:
SomeClass sc;
sc.SomeProperty = "Blah";
would yield the same error message => object reference not set to an instances of an object
That is because the sc isn't initialized. In fact it's null. It references/points to nothing.
Needed sc = new SomeClass(); before using the reference.
I bug
|
|
|
|
|
thanks sir, i solved already according to your help.
here another problem for me, when i set the "maindialog" as topmost, however when i click the mnubutton to display a dialog, it can't be display outside, it displayed the behind the maindialog, if i set the maindialog as normal then it can display, however when i want to run my maindialog, i want it as topmost. how to display the other dialog outside the maindialog when i set maindialog as topmost. thanks a lot
|
|
|
|
|
Make it (the other form top most through code):
Form2 f = new Form2();
f.TopMost = true;
f.ShowDialog();
I bug
|
|
|
|
|
if you mean double-clicking a form in the solution pane leads to an exception, that must be because some of your code (including the default constructor) gets executed by Visual Designer and a fault of yours results in an Exception. You could always right-click the form, choose "View Code" and go look for the problem.
|
|
|
|
|