 |
|
|
 |
|
 |
This looks very interesting and potentially very useful. I haven't come across application domains before and haven't tested the code, but it looks to me that the shadow copies are put into a sub folder of the executable, therefore normally in a program files sub folder. I have two questions:
- What would happen if the program is run by a user that is not allowed to install software? In Vista, would it make the UAC confirmation dialog appear?
- If an assembly or other file is replaced, would that have an affect on uninstallation? Would the updated files still be uninstalled when the software is uninstalled, or would it leave leftover files in the file system?
|
|
|
|
 |
|
 |
Thanks for your reply!
First of all you can determine the path of the shadow copies. Therefore it isn't necessary to have the shadow copies in the program files folder (or a subfolder of that). You could choose a directory in the user settings.
I haven't used Vista so far - I can't say what would happen. If this is a problem choose an appropriate folder for the shadow copies.
Regarding your question about uninstalling:
As far I know the uninstallers handle the files by their name and so this shouldn't be an issue - so long the names remain the same.
Cheers
Günther
|
|
|
|
 |
|
 |
Günther M. FOIDL wrote: You could choose a directory in the user settings.
Wouldn't it be more appropriate in temp? Or perhaps when creating the directory when installing assign permissions so that the program can copy stuff there.
Günther M. FOIDL wrote: As far I know the uninstallers handle the files by their name and so this shouldn't be an issue - so long the names remain the same.
Usually by their relative paths but basically you'd have to force it to do a recursive delete. If don't do anything they won't either.
|
|
|
|
 |
|
 |
Ed.Poore wrote: Wouldn't it be more appropriate in temp?
Concerning the path you have complete freedom where to copy the files. In my article just an example path is used.
Thanks for comments!
Cheers
Günther
|
|
|
|
 |
|
 |
I realise that, I was just helping clear up some points.
|
|
|
|
 |
|
 |
The assembly directory should be loaded using:
startupPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
|
|
|
|
 |
|
 |
It isn't wrong at all...
On startup the 3 possibilities to get the assembly's path return the same result.
using System;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string path1, path2, path3;
path1 = Environment.CurrentDirectory;
path2 = Application.StartupPath;
path3 = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
Console.WriteLine(path1);
Console.WriteLine(path2);
Console.WriteLine(path3);
Console.ReadKey();
}
}
}
It can be an issue when you change the current directory for instance via a SaveFileDialog.
Cheers
Günther
|
|
|
|
 |
|
 |
If it's starting from a link the Environment.CurrentDirectory can be different. You also say that the SaveFileDialog can change it. If works 99% of the times, it's still wrong 1% of the times.
On the other hand, reflection works 100% of the times.
I didn't meant to be rude, just to suggest a small improvement to a nice snippet.
Kind Regards
D.
|
|
|
|
 |
|
 |
I've tested starting from a link on the results are the same.
Do you know from what link-type the directories differ?
The SaveFileDialog-thing doesn't matter on the the first lines of code. Saying it more precisely: It can be an issue in the later application code.
Nevertheless, thanks for your comment and suggestion.
Cheers
Günther
|
|
|
|
 |
|
 |
Suppose you're running the app from a batch file, from a scheduled task or, better, from another process through Process.Start().
You were forced to CD to app directory before launching it; you can't be sure that current directory is app directory.
Being in "C:\Program Files" you could run the app with "appFolder\bin\app.exe"; in this case CurrentDirectory is "C:\Program Files" and not "C:\Program Files\appFolder\bin".
Things get worst if your app path is in PATH environment variable: your user could run app.exe from everywhere...
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)
will always be the app path, wherever you are.
|
|
|
|
 |
|
 |
Thanks, you're right. I'm going to alter the code.
System.Windows.Forms.Application.StartupPath returns also the correct path.
Cheers Günther
Edit: marked as answer
|
|
|
|
 |
|
 |
Günther M. FOIDL wrote: System.Windows.Forms.Application.StartupPath returns also the correct path.
Yeah, but works only in WinForms applications and not - for example - in console apps or services;
unless you add System.Windows.Forms.dll to references...
|
|
|
|
 |
|
 |
But this shouldn't be an issue when the assembly that gets loaded by this program also references System.Windows.dll - and that will happen in most cases.
I've updated the code so the directory is obtained via reflection. Waiting for it to be posted...
@nicorac: Thanks very much for your explanation (I've voted 5)
modified on Tuesday, October 14, 2008 2:48 PM
|
|
|
|
 |
|
 |
My 2 cents worth...
If you Pin an application to the Start Menu (I mean the EXE itself, and not a link to the EXE) then the CurrentDirectory will also be wrong (on XP at least, I haven't tried Vista). I would have to agree and say that the Reflection is the best method.
|
|
|
|
 |
|
 |
Thanks for your reply. You're right.
But doing so you don't meet the prerequisite commented in the code:
Both assemblies (Loader and MyApplication) reside in the same directory.
Nevertheless the best and most secure way is by using reflection.
Cheers
Günther
|
|
|
|
 |
|
 |
I'm not sure about the line:
Directory.Delete(cachePath, true);
I, for example, start two instances of the program.
I'm not sure it's OK to delete whole folder when first instance exits.
OTOH, if I just delete this line, will cachePath be overwritten each time that program starts?
LP,
Dejan
|
|
|
|
 |
|
 |
Hi,
this isn't an issue. The CLR takes care about this and creates "subfolders" for each running instance. Just have a look in the explorer how the folder-tree lookes like.
So you can see the cache-path isn't a static directory - it's just the top direcotry of shadow copying.
So deleting this line isn't necessary. I putted the deleting into the loader for cleaning up reasons.
Greetings
Günther
|
|
|
|
 |
|
 |
Thanks for clarification.
LP,
Dejan
|
|
|
|
 |
|
 |
There is, however, another problem that could arise when multiple instances are concerned: If a running instance of the application updates file A and file B to new versions, and another instance of the application is started between the file updates so that file A is new and file B is old, the new instance might not work correctly as the new A and the old B is not intended to be used together. I suppose locking to a named mutex during shadow copying and file updating should prevent this situation from arising.
|
|
|
|
 |
|
 |
Thanks for pointing to possible problems. The named mutex is a good way preventing this.
But this doesn't concern shadow copying itself - it's an updating problem.
Cheers
Günther
|
|
|
|
 |
|
 |
Hi, I've never had contact with this method of shadow copying. It's actually helpful. I have a question though...
I as understand, you could update the assemblies at runtime physically, but do they really change its behaviour at runtime? or do you have to reboot the app for the changes to take effect?
Regards
Intelligence is almost useless for those who have nothing else!
Email: caiokf@gmail.com
|
|
|
|
 |
|
 |
The assemblies are executed from the cache (the shadow copy path) and the update replaces the files in the "original place", so the code isn't updated at runtime.
On the next start of the application those updated file are used for shadow copying and then the new code gets executed.
Hope I could answer your question - other I'll try to explain better.
Regards Günther
|
|
|
|
 |
|
 |
Thanks!
Intelligence is almost useless for those who have nothing else!
Email: caiokf@gmail.com
|
|
|
|
 |