How to change the DateCreated on a StorageFile? - c#

Per http://msdn.microsoft.com/en-us/library/windows/apps/windows.storage.storagefile.datecreated.aspx , StorageFile.DateCreated is read-only.
On the desktop, I can do:
IStorageFile file = ...
DateTime date = ...
BasicProperties props = await file.GetBasicPropertiesAsync();
var changes = new List<KeyValuePair<string,object>>();
changes.Add(new KeyValuePair<string, object>("System.DateCreated", date));
await props.SavePropertiesAsync(changes);
but on WP8, BasicProperties.SavePropertiesAsync isn't implemented.
Is there some other way to do this?

One way would be to take the date created and use ApplicationData.LocalSettings to store the file path and the date created. The risk being that you have to make sure the value is updated everytime you create a file.
Otherwise you could use moveAndReplaceAsync to move the file and reset the date created.
You could also store the values in your own secondary file or database, but that would require extra IO on every file read. (You have to open two files to get at the file contents and the 'date created').

Related

How to track, if the file has changed in the UWP App?

Is there any way to track, if the file I picked using the fileopenpicker changed? I have an UWP APP, which takes data from excel and does sth. with it, but every time I want to take data from the excel file, I have to use file picker again, which makes it useless. Do you know how to automate such task?
You can use FutureAccessList or MostRecnetUsedList to access the file without using the file picker every time.
StorageFile file = await savePicker.PickSaveFileAsync();
if (file != null)
{
// Add to MRU with metadata (For example, a string that represents the date)
string mruToken = Windows.Storage.AccessCache.StorageApplicationPermissions.MostRecentlyUsedList.Add(file, "20120716");
// Add to FA without metadata
string faToken = Windows.Storage.AccessCache.StorageApplicationPermissions.FutureAccessList.Add(file);
}
else
{
// The file picker was dismissed with no file selected to save
}
For more info, see this link.

Reading/Writing RichEditBox (.rtf) files without using picker (C# - Visual Studio - UWP)

I am struggling to create my first UWP program in C#. I have run into a problem with reading/writing .rtf files and have not been able to work out a solution nor find one in the forums.
My program is an application for reading and writing a daily journal. The daily journal entries are displayed and edited in a RichEditBox. Next to the RichEditBox is a CalendarDatePicker.
When the CalendarDatePicker value changes, the program creates a file name based on the CalendarDatePicker date. For example, if the CalendarDatePicker's value was 7/22/2018, my program would turn that into the following file name: "2018_7_22.rtf" and then assign that to a string named fileName.
All of the above is working as desired. Here is the problem I am having:
When the value of the CalendarDatePicker changes, the program is supposed to immediately load the .rtf file (if it exists) from storage into the RichEditBox. And, when I press the SAVE button, the program is
supposed to save the RichEditBox contents to storage. Both reading and writing the file is supposed to
use the name derived from the CalendarDatePicker value rather than opening up a picker for either
opening or saving the file.
I have not been able to find any documentation about how to read and write a .rtf file for the RichEditBox without using a picker. I do not want to use a picker because I want that the given journal entry can only be read or written according to the file name that is based on the current value of the CalendarDatePicker.
Here is what I am trying to do:
String filePath = Windows.Storage.ApplicationData.Current.LocalFolder.toString;
// this returns error: "cannot convert method group 'ToString' to non-delegate type string"
String fileName = "2018_22_7.rtf"
// this is an example of a string my program would create according to the CalendarDatePicker's value.
At the end of my question is the code from the RichEditBox documentation. I want do away with the portion that uses the picker and replace the following line:
Windows.Storage.StorageFile file = await savePicker.PickSaveFileAsync();
with:
Windows.Storage.StorageFile file = filePath + fileName;
Is it possible to do this or am I forced to use a picker with the RichEditBox?
I will deeply appreciate any help I can get in solving this problem. I am
melting from frustration! Thank you!
Here is the code from the RichEditBox documentation:
private async void SaveButton_Click(object sender, RoutedEventArgs e)
{
Windows.Storage.Pickers.FileSavePicker savePicker = new Windows.Storage.Pickers.FileSavePicker();
savePicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.DocumentsLibrary;
// Dropdown of file types the user can save the file as
savePicker.FileTypeChoices.Add("Rich Text", new List<string>() { ".rtf" });
// Default file name if the user does not type one in or select a file to replace
savePicker.SuggestedFileName = "New Document";
Windows.Storage.StorageFile file = await savePicker.PickSaveFileAsync();
if (file != null)
{
// Prevent updates to the remote version of the file until we
// finish making changes and call CompleteUpdatesAsync.
Windows.Storage.CachedFileManager.DeferUpdates(file);
// write to file
Windows.Storage.Streams.IRandomAccessStream randAccStream =
await file.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite);
editor.Document.SaveToStream(Windows.UI.Text.TextGetOptions.FormatRtf, randAccStream);
// Let Windows know that we're finished changing the file so the
// other app can update the remote version of the file.
Windows.Storage.Provider.FileUpdateStatus status = await Windows.Storage.CachedFileManager.CompleteUpdatesAsync(file);
if (status != Windows.Storage.Provider.FileUpdateStatus.Complete)
{
Windows.UI.Popups.MessageDialog errorBox =
new Windows.UI.Popups.MessageDialog("File " + file.Name + " couldn't be saved.");
await errorBox.ShowAsync();
}
}
}
Universal Windows Apps (apps) can access certain file system locations by default.
Before window version 17134, if you don't want use a picker to access the file, your UWP app only can access the files in the Application install directory, Application data locations, Removable devices and some Locations that UWP apps can access with specific Capability such as the Music and Pictures Libraries. But you can not write into the Application install directory. In this case, you can try to save the file in above location except the Application install directory. Such as the Application data locations then you can create and get the file using the following code. Please see the File access permissions for more details.
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
//Createa file
StorageFile fileToSave = await localFolder.CreateFileAsync("YourFileName");
//Get file
StorageFile file = await localFolder.GetFileAsync("YourFileName");
If your app target on version 17134 and later, you can access all files that the user has access to using the broadFileSystemAccess Capability, this capability works for APIs in the Windows.Storage namespace, you can get the file using the path as following code, here is a sample.
StorageFolder folder = await StorageFolder.GetFolderFromPathAsync(path);

UWP . Copy file from FileOpenPicker to localstorage

FileOpenPicker picker = new FileOpenPicker();
picker.ViewMode = PickerViewMode.Thumbnail;
picker.SuggestedStartLocation = PickerLocationId.ComputerFolder;
picker.FileTypeFilter.Add(".txt");
A user chooses a file to open. How can I store/copy/save that file to localstorage for future use, so every time the app opens, it picks automatically that file?
After the user opens the file using the FileOpenPicker you can "cache" access to it using StorageApplicationPermissions API.
Once you have the StorageFile you want to open automatically, you can "cache" your access to it using the following code:
string token = StorageApplicationPermissions.FutureAccessList.Add( file );
What you get back is a string token, which you can save for example in the app settings. Next time the app is opened, you can retrieve the file again using the following code:
StorageFile file =
await StorageApplicationPermissions.FutureAccessList.GetFileAsync(token);
Note that this API has limitation of at most 1000 items stored, so if you expect that more could be added, you will have to ensure the older files are removed otherwise you would not be able to add new files.
There is also alternative - StorageApplicationPermissions.MostRecentlyUsedList which you can use the same way as the FutureAccessList, but it has the advantage of automatically managing the list. It can store up to 25 items, but it is able to automatically remove the oldest ones when not needed anymore.
Also note, that this APIs can cache access not only to files but also to folders (StorageFolder).
Copying the file to AppData folder
If you just want to create a local copy of the picked file, you can copy it to the local folder of the app.
var file = await picker.PickSingleFileAsync();
if ( file != null )
{
await file.CopyAsync( ApplicationData.Current.LocalFolder );
}
StorageFile file = await openPicker.PickSingleFileAsync();
if (file != null)
{
var yourPath = file.Path;
}
but It won't work as you expect. But remember you can't open file from location you (your app) don't have access to.
edit: yeah, I see in comments that I have missed some part of the qestion ;)
the easiest way to store the information for future re-use would be propably to use LocalSettings
https://msdn.microsoft.com/library/windows/apps/windows.storage.applicationdata.localsettings.aspx
(sorry for the link, but there is no use in copying info from there)
You could:
1) Store the file name in your project settings;
YourNameSpace.Properties.Settings.fileToLoad;
2) write the file name in a local file (look at TextWriter namespace);
3) store the file name in your database if your application is data-driven
... and others.
I am presuming here that you're using WinForms or Console app. If you are using a webForm, you would need to store the file name in a cookie so you could attach the right file to the right user before they log in or give you credenstials. For Webforms, then, look into the use of cookies.
Just to add to the above suggestions, following example from Official Microsoft document shows how to Store file for future access:
var openPicker = new FileOpenPicker();
StorageFile file = await openPicker.PickSingleFileAsync();
// Process picked file
if (file != null)
{
// Store file for future access
Windows.Storage.AccessCache.StorageApplicationPermissions.FutureAccessList.Add(file);
}
else
{
// The user didn't pick a file
}

Read files based on their modified time in C#

I have a situation here. I want to read files based on their creation of last modified time. Initially i used FileSystemWatcher so that i was notified when a new file was coming, but later i realized that if the system on which my software is running goes down or restarts the location where files were being dropped will still continue.
To make it easier for understanding i will give an example:
System A - File Server (Files are created every 2 min in a directory on this server)
System B - My Software will run and Monitor files from the Path of System A
If System B goes restarts and is up again after 10 min the FileSystemWatcher will skip all these files which were generated in those 10 min.
How Can I ensure that those files generated in those 10 min of time are also captured?
Let me know if my question is still not understandable.
If you don't want to split it up in two systems, you have to persist a little bit of information.
You could store the current timestamp in a file, every time a new event was fired on the filesystem watcher. Every time your service starts, you can read all files from the filesystem that are newer than the last timestamp. This way you shouldn't miss a file.
I would split this application into two parts and running a filesystemwatcher-wcf service that buffers the files created in this 10 minutes and will send it to system b when it is restarted. I can't see a other way, sorry.
I think the FileSystemWatcher must write info about file system into DB (or other type of storage). When System B starts, watcher compares current file system with this info and will raise events about changes.
Copy the entire files from the Source Machine and paste into the destination based on condition..
string dirPath = #"C:\A";
string DestinPath = #"C:\B";
if (Directory.Exists(dirPath) && Directory.Exists(DestinPath))
{
DirectoryInfo di = new DirectoryInfo(dirPath);
foreach (var file in di.GetFiles())
{
string destinFile = DestinPath + "\\" + file.Name;
if (File.Exists(destinFile))
{
continue;
}
else
file.CopyTo(destinFile);
}
}
Not sure if I understood your question correctly, but based on what I get and assuming both systems are in sync in terms of time, if for example you want to get files that have been modified within ten minutes ago:
DateTime tenMinutesAgo = DateTime.Now.AddMinutes(-10);
string[] systemAFiles = System.IO.Directory.GetFiles(systemAPath);
foreach (string files in systemAFiles)
{
DateTime lastWriteTime = System.IO.File.GetLastWriteTime(files);
if (lastWriteTime > tenMinutesAgo) //produced after ten minutes ago
{
//read file
}
}
I understood that these files are "generated" so they have been created or modified. If they have simply been moved from one folder to another this will not work. In that case the best way is to write a snapshot of the files in that list (and writing it to some sort of a save file) and compare it when it is running again.

Detect if a file has been overwritten (Move and Replace) using C#

I am currently writing some background processes for a website that are to be run nightly on a webserver.
My main issue is that I need to detect whether an image file has changed in the last 24 hours. I thought that this would be easily achievable using the following code:
DateTime lastWrite = System.IO.File.GetLastWriteTimeUtc(HttpContext.Current.Server.MapPath(image.FileName));
if (lastWrite > DateTime.UtcNow.AddHours(-24) && lastWrite < DateTime.UtcNow)
{
var a = "This item has been modified";
}
else
{
var b = "This item has not been modified";
}
however, it seems that this will only give me the DateTime when the file was last modified. This is great for if the image has been edited using something like paint but it does not tell me whether the image has been overwritten using a cut and paste on an existing image as the modified and create date remain the same as the original image that was in place.
My question therefore is how do I detect whether a file (mainly images) have truly been modified (edited, copied over, removed then replaced) within a 24 hour period?
Any help would be greatly appreciated.
For this long-running-page application you'll need to keep a database containing information about the old files. One way of doing this would be to store the MD5 of each file and then compare and copy things that have changed.
using (var md5 = MD5.Create())
using (var stream = File.OpenRead(filename)) {
return Convert.ToBase64String(md5.ComputeHash(stream));
}
This has the added benefit of allowing you to sync even if some problem means that your "housekeeping" doesn't get run overnight, which will inevitably happen!
If you have no other software using the archive file attribute, that will work as you need it to - once you've copied the file to another location, unset the archive attribute. Overwriting the file from another directory will reset it!
// Check for flag
FileAttributes attributes = File.GetAttributes(path);
bool isArchiveSet = (attributes & File.Archive) == File.Archive
// Remove archive flag
FileAttributes attributes = File.GetAttributes(path);
attributes = attributes & ~FileAttributes.Archive;
File.SetAttributes(path, attributes);
(Untested code, if you have a problem let me know I'll look at it - but I have tested the behaviour of the archive bit and it does what you want it to).

Categories

Resources