|
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.
|
|
|
|
|
when eriting source code, how we can have Persistence block in C# text editor?
|
|
|
|
|
Do you mean reusing the same code again and again?
You could write your own code snippet[^].
The funniest thing about this particular signature is that by the time you realise it doesn't say anything it's too late to stop reading it.
My latest tip/trick
Visit the Hindi forum here.
|
|
|
|
|
when we create a block inside text editor, by pressing any key, that block disappears,
while existing block, if suddenly u press DEL key, content of that block get detroyed.
i dont want this, i want to have a block remain persist. pay attention i am talking only
about text editor not data manippulate or SQL server or....... just inside of text editor.
|
|
|
|
|
Write a Data Access Layer.
|
|
|
|
|
i'm trying to crate an AVI file using some screen shots as frames.but when starting the process it gives the the exception saying
"Attempted to read or write protected memory. This is often an indication that other memory is corrupt."
the application that i use to create the avi file is loaded to my application using reflection.what i do is just pass the frames to this loaded application.
any idea why this occurs.
thanx n advance..
|
|
|
|
|
because you took a wrong turn somewhere.
Member 4257632 wrote: using reflection
why?
|
|
|
|
|
This is my code
Note newNote = new Note();
Search newSearch = new Search();
SRLS newSRLS = new SRLS();
Alarm newAlarm = new Alarm();
QuickLaunch newQuickLaunch = new QuickLaunch();
Calender newCalender = new Calender();
Time newformtime = new Time();
private void Form1_Load(object sender, EventArgs e)
{
notifyIcon1.Visible = true;
if (timeToolStripMenuItem.Checked == true)
{
newformtime.Show();
}
if (alarmToolStripMenuItem.Checked == true)
{
newAlarm.Show();
}
if (calenderToolStripMenuItem.Checked == true)
{
newCalender.Show();
}
if (sRLSToolStripMenuItem.Checked == true)
{
newSRLS.Show();
}
if (searchToolStripMenuItem.Checked == true)
{
newSearch.Show();
}
if (noteToolStripMenuItem.Checked == true)
{
newNote.Show();
}
if (quickLaunchToolStripMenuItem.Checked == true)
{
newQuickLaunch.Show();
}
timeToolStripMenuItem.Checked = Settings.Default.timecheck;
alarmToolStripMenuItem.Checked = Settings.Default.calendercheck;
calenderToolStripMenuItem.Checked = Settings.Default.alarmcheck;
sRLSToolStripMenuItem.Checked = Settings.Default.srlscheck;
searchToolStripMenuItem.Checked = Settings.Default.searchcheck;
noteToolStripMenuItem.Checked = Settings.Default.notecheck;
quickLaunchToolStripMenuItem.Checked = Settings.Default.quickLaunchcheck;
}
So id some one checks the box then closes the program and then reopens it the other form should be visible can anyone see the problem in my code? coz I can't
|
|
|
|