I have an automatic update system that replaces my existing program files on reboot. (Suffice to say, it's a very complicated program with many drivers, services, and user level modules. There really is no other way. Trust me.)
The function MoveFileEx is used with MOVEFILE_DELAY_UNTIL_REBOOT to setup this file replacement. I'm finding that it works just fine, normally. However, if the source and target files are on different drives, the target is deleted but the source is not moved. The result is that when the user installs the software on a drive different from the system partition, an update deletes the product file rather than update them.
Now, I see in the documentation for MoveFileEx that MOVEFILE_COPY_ALLOWED should be used when moving a file from one volume to another. But it also says that flag cannot be used with MOVEFILE_DELAY_UNTIL_REBOOT.
Q: How can I move a file on reboot, overwriting an existing file, when the source and the target are not on the same volume?
Why don't you just copy the files to the drive where the user installed your program?
As far as I see there is no direct way to do what you want relying only on this function.
Finding writable location on the same drive might be a problem on Vista, but you mention you have services - if they run with LocalSystem privilleges have them write the new files.
One other simple update mechanism that I have used ( not working for drivers though) is to have dedicated update program - kill/end everything, let the update program do its work and start everything up again.
Related
Our application collects data from an external device. This data primarily resides in memory, but is spooled to disk in temporary files until the user explicitly saves the data. This is to provide some recovery chance if the application crashes for some reason. Generally speaking, it works just fine.
Lately we've discovered, thanks to Windows becoming more forceful about automatic updates, that these files get deleted automatically during a reboot. So if Windows kills our application to automatically apply updates, the temporary files that would have allowed recovery are gone after the reboot.
I've tested the issue by killing the application on purpose and rebooting; indeed, the temporary files have vanished after the reboot.
The files are created using the Win32 API call GetTempFileName, along with GetTempPath. Everything I've read on the subject says these files are not automatically deleted ever, but they clearly are being deleted.
What can I do to stop this? Or should I just change where our safety data is stored?
What you are seeing is a new "Storage Sense" feature added in Windows 10.
How to Clear Temporary Files Automatically in Windows 10.
Windows 10 got the ability to clear temporary files automatically in a recent build. Starting with build 15014, a new option appeared in Settings.
When enabled, it can be set to clear items like temporary files, Recycle Bin, etc. You can turn them off individually.
Alternatively, another option would be to change your app to save its temporary files in a non-system temp folder that you control, rather than using GetTempPath(). And maybe also use something other than GetTempFileName() to create your temporary file names (like using date/times or guids instead), so Windows can't possibly track the temporary files you create. Then perhaps your files won't be deleted automatically by Storage Sense anymore.
The best solution IMO is not using the temporary folder which contains (as the name suggests) temporary files that can be deleted without any consequences.
Instead you should store them somewhere in the LocalAppdata folder.
Use SHGetFolderPath function to retrieve the actual location of the LocalAppData folder.
In LocalAppData create a folder whose name is that of your company and/or product name or some combination of both and store all your pseudo temporary files there.
I am looking for a bit of advice on how Windows file system differentiates between files that are copied(copy and pasted from another location) and files that are created (a new file created in a a folder).
A bit of background to this so it makes more sense: I have an application that is used to move files. The application will monitor a directory and when a file is placed in the directory it will move it elsewhere. However, I am having issues where the application will not pick up a file that is created within the monitored directory but will pick up files that have been created else where and are copied into the monitored directory.
Any advice on how Windows differentiates, or if it does at all, would be greatly appreciated.
This is running on Microsoft Windows Server 2008 R2 Standard. I can't dig into the code and see what is going on under the hood unfortunately, so need to get an idea of the difference if any there would be.
The filesystems don't know the operation of "copying" the file. Any copying is a sequence of file open/read/write/close operations. The same applies to moving to the different filesystem. Moving within the same filesystem, though, is an operation native to the filesystems and it can be done with one command to the filesystem.
Now about your problem. Most likely you catch the creation of the file (before the data is written), and when your application reacts, the file is still opened for writing. So you need to wait until the file is closed.
Depending on how you do monitoring, such waiting is done in different ways. In filesystem filters you wait for file close operation. With .NET FileSystemWatcher there's no way to track file close operation, but I saw a couple of tricks here on StackOverflow (don't have a link though, sorry).
A file existing in D: drive, from creation
The same file which was copied to E: drive
As you can see, the file which was copied to E: drive, has a creation time as the latest, when it was copied to and the modification time as the last modification time for that file in previous location.
So I guess this illustrates, how windows differentiates between copied files and created files.
Hi I am trying to find out what is the best location to save a cache file.
I have an Windows form application that updates user's data from the server using a custom tool.
I want to write the timestamp of the latest updates done on user's machine in the cache file.
Where is the best location for keeping this file:
1. in application directory (c:\program files..)
2. in a temp location e.g. Users profile folder or c:\windows\temp
3. in any location (e.g. c:\dataupdates) where user has full access to read/write to.
Not in the application directory. That much is clear. :) The application directory shouldn't even be writable by the program (or actually by the user account that runs the program). Although some applications still use this location, it has actually been deprecated since Windows 95, I believe, and it has become a real pain since the more rigid UAC applied in Windows Vista and 7.
So the most obvious options are:
The temp folder, which is for temporary files. Note however, that you will need to clean those files up. Temp folder is not automatically cleared by default, so adding new files all the time will consume increasingly much space on the hard drive. On the other hand, some users do clear their temp folders, or may have scripts installed that do that for them, so you cannot trust such files to remain. Also, this is not always C:\Temp of whatever. You'll have to ask Windows what the location is.
You can pick 'any' location. Note that you cannot write anywhere. You cannot even expect the C drive to exist. If you choose this, then you have to make it a configurable setting.
The %app data% directory, my personal favorite, which is a special directory for applications to store their data in. The advantage is, that you can ask Windows for this location, and you can make up a relative path based on that directory, so you don't really have to make it an application setting. For more info on how to get it, see also this question: C# getting the path of %AppData%
I would definitely choose the App Data path for this purpose.
I'm having issues with a few .ocx files in vb6. I have 2 components registered but when I attempted to add both into my project it says that I need to register them. I have tried copying new files into the sysWOW64 folders and still it does not work.
This occasionally happens when there is some corruption and conflict in the registry. One way to fix this is to place the two items in a folder within the project and add them by manually going to the reference and selecting that local copy, it will automatically register it as a new object and often (although not always) will fix the corruption by tagging the new path and it often resolves the issue you are facing. The only problem is that in the future projects, you may need to repeat the process or have access to the items.
The cleaner approach is to find all instances of the files on the system by doing an advanced search and finding ALL COPIES of them on the system, often they are all over the place. Once you have those paths, you need to regsvr32 /u <filepath.filename> each one to clean remove them from the registry and then place them in a common area and then register them from ONE location using regsvr32 <filepath.filename> and now things should work fairly cleanly.
Easiest way to find all instances on your machine (at least for me) is to simple go to your command prompt (if using more recent than XP, then as administrator) and then simply type:
C:
cd\
dir /s <filename.ext> > c:\files.txt
and wait until its done, at that point you open that file and it should give you all the paths to the files you need and you can easily turn the text file into a batch file by adding the commands you need to unreg and run it, voila, quick and fairly painless. If at anytime you unreg and it whines about it not being registered or can't do it, don't worry, just acknowledge and move on. Some OCX and DLL don't have registration entry points. If you register and it complains saying it can't do it, then you pretty much have no choice but to it the way I mentioned at the very beginning, by direct linking in your reference and having it drop into your project.
Final note, unless they are 64 bit compatible, you don't need and often shouldn't put them in the WOW system folder but rather system and system32 folders depending on version control and binary control of the original OCX.
I have a Windows service application on Vista SP1 and I've found that users are renaming its executable file (while it's running) and then rebooting, thus causing it to fail to start on next bootup because the service manager can no longer find the exe file since it's been renamed.
I seem to recall that with older versions of Windows you couldn't do this because the OS placed a lock on the file. Even with Vista SP1 I still cannot copy over the existing file when it's running - Windows reports that the file is in use - makes sense. So why should I be allowed to rename it? What happens if Windows needs to page in a new code page from the exe but the file has been renamed since it was started? I ran Process Monitor while renaming the exe file, etc, but Process Mon didn't report anything strange and just logged changing the filename like any other file.
Does anyone know what's going on here behind the scenes? It's seem counter intuitive that Windows would allow a running process' filename (or its dependent DLLs) to be changed. What am I missing here?
your concept is wrong ... the filename is not the center of the file-io universe ... the handle to the open file is. the file is not moved to a different section of disk when you rename it, it's still in the same place and the part of the disk the internal data structure for the open file is still pointing to the same place. bottom line is that your observations are correct. you can rename a running program without causing problems. you can create a new file with the same name as the running program once you've renamed it. this is actually useful behavior if you want to update software while the software is running.
As long as the file is still there, Windows can still read from it - it's the underlying file that matters, not its name.
I can happily rename running executables on my XP machine.
The OS keeps an open handle to the .exe file,. Renaming the file simply changes some filesystem metadata about the file, without invalidating open handles. So when the OS goes to page in more code, it just uses the file handle it already has open.
Replacing the file (writing over its contents) is another matter entirely, and I'm guessing the OS opens with the FILE_SHARE_WRITE flag unset, so no other processes can write to the .exe file.
Might be a stupid question but, why do users have access to rename the file if they are not suppose to rename the file? But yeah, it's allowed because, as the good answers point out, the open handle to the file isn't lost until the application exits. And there are some uses for it as well, even though I'm not convinced updating an application by renaming its file is a good practice.
You might consider having your service listen to changes to the directory that your service is installed in. If it detects a rename, then it could rename itself back to what it's supposed to be.
There are two aspects to the notion of file here:
The data on the disk - that's the actual file.
The file-name (could be several or none) which you can give that data - called directory entries.
What you are renaming is the directory entry, which still references the same data. Windows doesn't care about your doing so, as it still can access the data when it needs to. The running process is mapped to the data, not the name.