I had searched a lot of examples, but none work perfect for me. I am using C#.
My application need to remove the files in folder, only when the file is closed.
The try-catch File.Open(...) method only works for certain filetype like doc, xls, ppt, pdf, mp3 etc, but not work for txt, zip, html etc...
The behavior your are seeing doesn't have anything to do with the file's extension or contents. It has to do with the way the associated applications treat those files. For example, Notepad, Internet Explorer, etc will not hold a lock on an opened file once the contents are read. That's why .txt and .html files are able to be opened.
Microsoft Office, virtually all media players, etc will hold a lock on the file. In the case of Office, it's doing so to make sure other programs don't delete/move the file out from under it. In the case of a media player, the files are usually too big to be read into memory completely. That's why those file types are locked when in use.
In other words, those files that appear to not be in use aren't actually in use. The program read the data from the file and close it and now it's done with it. There's really no easy way to determine whether or not another program has a particular file open if it no longer has an open handle to the file.
Open the file in the binary mode File.Open(...) will work for all files.
Try opening the file in write mode, I think there is something to specify that the lock is exculsive..but for some reason if your thread dies..dunno if that lock will be released automatically...
all you need is to delete the file that is not in use ... rigth ... Simply ignore the exception thrown by File.Delete. Since it will not delete the file that is in use ..
try
{
File.Delete(path);
}
catch(Exception e)
{
// ignore ... or whatever action
}
you can also catch specific exceptions to take specific action ... like IOException for file in use, UnauthorizedAccessException for read only files and permission issues etc ...
Checking file for opening and then trying to delete may still through exception as file may have been opened by some process between checking and deleting operations ..
Related
In my datalogging application I write to a temporary file of the form ... AppData\Local\Temp\euaxgd5z.csv
This opens by default in Excel.
Process.Start(TempFileLocationBox.Text.ToString());
The next time the timer tries to write more data to this file, an exception is thrown. However if I open it with TextPad
Process.Start("textpad.exe", TempFileLocationBox.Text.ToString());
it can write to the file quite happily and TextPad will ask if I want to reload it. How can I get Excel to behave as nicely as TextPad?
Personally, I wouldn't even try to 'communicate' to excel the fact that you want the file reloaded. I would just write a new file and open a new copy of excel, after closing the old copy if possible.
That way you won't need to worry if the user is using open office instead, for example.
I want to save some plain text periodically to a text file, and it will be really better if I can minimize the chance of corrupting the file in case the app gets terminated or the system restarts. What are the way to ensure that the plain text file is always good.
Edit
I will run the program from USB drive, so want to make sure the file is still perfect if I eject the drive without closing the App.
You could take a look at using transactions on the NTFS file system, assuming that the USB stick is formatted NTFS and your OS is Vista or better.
Do not use option FileMode.Create, which overwrites existing files. Instead, use option FileMode.Append when creating the file stream, so that any text will be appended to the file without modifying last data.
However, try not to keep the files opened for long period, just open them and read or write and then Dispose them.
Use File.AppendAllText to open, append and close in one go.
Is there any way to determine if a file is open by anything include applications that do not lock the file (like notepad).
I need to detect when a given file myfile.txt is no longer open in any application including notepad - so i cannot use File.Open(...) with exclusive access to test since the file has no lock on it.
No. When Notepad has opened a file, it has read the entire file in and then closed it. So there is no trace in the OS that links Notepad's private memory with the file on disk.
Opening the file exclusively will not work, because Notepad does not have the file open. Searching Notepad's handle table will not work, because Notepad does not have the file open.
The only way to detect this is to write an unmanaged DLL that is injected into every process to scan their virtual memory, searching for the exact file contents. Not recommended.
You must call File.Open(...) specifying your desired access flags and check the returning value to determine if the file is opened or if the access is denied. This is the recommended and safe way to access a file.
I have a portable executable that saves data to a file in the same folder as the executable. Is there any way that I can save data into the executable itself when I close the app?
This maybe weird, but taking the data with me and only have one file for the exe and data would be great.
Would prefer if this was made with C#, but is not a requisite.
You cannot modify your own EXE to contain stored data in anything approaching an elegant or compact way. First off, the OS obtains a lock on the EXE file while the application contained within is being run. Second, an EXE comes pre-compiled (into MSIL at least), and modification of the file's source data usually requires recompilation to reset various pointers to code handles, or else a SERIOUS knowledge on a very esoteric level about what you're doing to the file.
The generally-accepted methods are the application config file, a resource file, or some custom file you create/read/modify at runtime, like you're doing now. Two files for an application should not be cause for concern
You can, by reserving space through the means of using a string resource and pad it out. You need to do a bit of detective work to find out exactly where in the offset to the executable you wish to dump the data into, but be careful, the file will be "in use", so proceed cautiously with that.
So right now you're using an app.config (and Settings.settings) file?
I believe this is the most compact way to save data close to the .exe.
I would highly doubt you can alter the manifest of the .exe, or any other part of it.
Edit: Apparently, there might be some ways after all: http://www.codeproject.com/KB/msil/reflexil.aspx
There is one way using multiple streams, but only works in NTFS filesystems.
NTFS allows you to define alternative "named" streams in one file. The usual content is in the main = unnamed stream. It has something to do with the extra info you can see when you right click a file and check properties.
Unfortunatly C# has no support for multiple streams, but there are open source pojects that can help you.
See this link for a nice wrapper to read and write multiple streams to one single file in C#
Alternate data streams might work. By using the ::stream syntax you can create a data stream within your exe and read/write data.
Edit:
to create/access an alternate data stream, you will use a different filename. Something like:
applicAtion.exe:settings:$data
this will access a data stream named "settings" within application.exe. To do this you need to add the :settings:$data to the filename when reading or writing to the file. This functionality is provided by ntfs so it shold work in c# and should work when the application is running.
Additional information is available at: http://msdn.microsoft.com/en-us/library/aa364404(VS.85).aspx
If you want to take the data with you and only have one file for the exe and data, .zip them into a self-extracting .exe.
you can add data to end of executable file :
var executableName = Process.GetCurrentProcess().MainModule.FileName;
// rename executable file
var newExecutableName = fullPath.Replace(".exe", "_.exe");
FileInfo fi = new FileInfo(executableName);
fi.MoveTo(newExecutableName);
// make copy of executable file to original name
File.Copy(newExecutableName, executableName);
// write data end of new file
var bytes = Encoding.ASCII.GetBytes("new data...");
using (FileStream file = File.OpenWrite(executableName))
{
file.Seek(0, SeekOrigin.End);
file.Write(bytes, 0, bytes.Length);
}
// we can delete old file when exited
Suppose I have a program running that periodically adds information to a .CSV file. Is there a way to write to the file while it is already open in Excel? Obviously the changes wouldn't be noticed until the file was re-opened in Excel, but as it stands right now, I'm catching IOException and just starting a new .csv file if the current one is already open.
Excel seems to open the file in exclusive mode, so the only way I can think of would be to write your changes to a temporary file, and then use FileSystemWatcher to see when the file is closed, and overwrite the file.
Not a very good idea, as you could lose data. The whole reason excel locks the file is so that you don't accidentally overwrite changes made in excel.
It sounds like the file is locked. I doubt you will be able to write to that file if it is open in another process.
As a former (and sort of current) VB Programmer, I can tell you Jared is correct - there is no way to do this directly. You can try to copy the file first, make your edits, then attempt to save the file back to its original location until the locked file becomes free. You should be able to copy that file, even while locked.
What about using Excel's object model and automating the addition of the data into the open spreadsheet? You'd probably need to prompt the user somehow to let them know what was happening.