Save text to file periodically - c#

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.

Related

C#, can I save a file from a stream or other to my single exe?

I would like to take a serialized file and save it to my recourses folder in project.
My reason for doing this (maybe there's a better way) is I have a published exe (single executable file) for the program that runs and when it creates a serialized file I don't want it to save it to desktop. I need to somehow save it to my exe without going outside of it.
Any advice on how I could do this?
It's very ugly.....but you could use an "alternative data stream" on NTFS system.
http://ntfs.com/ntfs-multiple.htm
https://learn.microsoft.com/en-us/sysinternals/downloads/streams
How to read and modify NTFS Alternate Data Streams using .NET
https://blogs.msmvps.com/bsonnino/2016/11/24/alternate-data-streams-in-c/
https://oddvar.moe/2018/04/11/putting-data-in-alternate-data-streams-and-how-to-execute-it-part-2/
https://blog.foldersecurityviewer.com/ntfs-alternate-data-streams-the-good-and-the-bad/
https://www.irongeek.com/i.php?page=security/altds
You'll probably have security scanners stopping you from doing it.
In addition if you copy the from an NTFS volume to say FAT, then alternative data streams are lost.
Also some backup software may not backup ADS properly.
https://wiki.sep.de/wiki/index.php/Support_for_NTFS_alternate_data_streams_(ADS)_for_Windows
https://www.2brightsparks.com/resources/articles/ntfs-alternate-data-stream-ads.html
https://community.osr.com/discussion/89308/alternate-data-streams-and-backups
https://social.technet.microsoft.com/Forums/Azure/en-US/007d5442-1cd8-4293-b717-b8fa72606189/ntfs-data-streams-broken-by-design-on-file-copy?forum=winserverfiles

How to detect a file is in use?

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 ..

Open file from byte array

I am storing attachments in my applications.
These gets stored in SQL as varbinary types.
I then read them into byte[] object.
I now need to open these files but dont want to first write the files to disk and then open using Process.Start().
I would like to open using inmemory streams. Is there a way to to this in .net. Please note these files can be of any type
You can write all bytes to file without using Streams:
System.IO.File.WriteAllBytes(path, bytes);
And then just use
Process.Start(path);
Trying to open file from memory isn't worth the result. Really, you don't want to do it.
MemoryStream has a constructor that takes a Byte array.
So:
var bytes = GetBytesFromDatabase(); // assuming you can do that yourself
var stream = new MemoryStream(bytes);
// use the stream just like a FileStream
That should pretty much do the trick.
Edit: Aw, crap, I totally missed the Process.Start part. I'm rewriting...
Edit 2:
You cannot do what you want to do. You must execute a process from a file. You'll have to write to disk; alternatively, the answer to this question has a very complex suggestion that might work, but would probably not be worth the effort.
MemoryMappedFile?
http://msdn.microsoft.com/en-us/library/system.io.memorymappedfiles.memorymappedfile.aspx
My only issue with this was that I will have to make sure the user has write access to the path where I will place the file...
You should be able to guarantee that the return of Path.GetTempFileName is something to which your user has access.
...and also am not sure how I will detect that the user has closed the file so I can delete the file from disk.
If you start the process with Process.Start(...), shouldn't you be able to monitor for when the process terminates?
If you absolutely don't want to write to disk yourself you can implement local HTTP server and serve attachemnts over HTTP (like http://localhost:3456/myrecord123/attachment1234.pdf).
Also I'm not sure if you get enough benefits doing such non-trivial work. You'll open files from local security zone that is slightly better then opening from disk... and no need to write to disk yourself. And you'll likely get somewhat reasonable warning if you have .exe file as attachment.
On tracking "process done with the attachment" you more or less out of luck: only in some cases the process that started openeing the file is the one that is actually using it. I.e. Office applications are usually one-instance applications, and as result document will be open in first instance of the application, not the one you've started.

Determine if a file is open

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.

Write to file that is open in Excel

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.

Categories