Reputation: 9455
An elegant / performant way to "Touch" a file in (update ModifiedTime) WinRT?
I have some code which needs to delete files that are older than 30 days. This works well, but in some cases, I need to update the time on the file to reset the 30 day window, and prevent deletion. On the basicProperties list, the ModifiedTime is read-only, so I need to find another way to update it...
Method 1: Rename twice
// Ugly, and may have side-effects depending on what's using the file
// Sometimes gives access denied...
public static async Task TouchFileAsync(this StorageFile file)
{
var name = file.Name;
await file.RenameAsync("~" + name).AsTask().ContinueWith(
async (task) => { await file.RenameAsync(name); }
);
}
Method 2: Modify a file property
// Sometimes works, but currently throwing an ArgumentException for
// me, and I have no idea why. Also tried many other properties:
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb760658(v=vs.85).aspx
public static async Task TouchFileAsync(this StorageFile file)
{
var prop = new KeyValuePair<string, object>("System.Comment", DateTime.Now.Ticks.ToString());
await file.Properties.SavePropertiesAsync(new[] { prop });
}
Method 3: Use a Win32 API via P/Invoke?
Anyone got any other ideas? I'm a bit stuck :-)
Many thanks, Jon
Upvotes: 4
Views: 1357
Reputation: 387
I just had a need for this and here is my solution.
usage
await storageFileToTouch.TouchAsync();
code
public static class StorageFileExtensions
{
/// <summary>
/// Touches a file to update the DateModified property.
/// </summary>
public static async Task TouchAsync(this StorageFile file)
{
using (var touch = await file.OpenTransactedWriteAsync())
{
await touch.CommitAsync();
}
}
}
Upvotes: 2
Reputation: 674
Assuming you're planning on combing a list of files that exist locally on an RT machine, and not somewhere in that cloud (otherwise we woudln't have to worry about the WinRT doc mod process), You could easily use the Application Data Container provided to each app to store very thin data (key value pairs fit very well).
In this way you would store a future delete date for each file that needed to be persisted, so that the next time it was raised for deletion, before the deletion process occurs, the app checks the App Storage Data. Then you wont need to worry about the permissions of the files you're iterating over, when you're only trying to make sure they don't get deleted from your process.
Windows.Storage.ApplicationDataContainer localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
// Create a setting in a container
Windows.Storage.ApplicationDataContainer container =
localSettings.CreateContainer("FilesToPersist", Windows.Storage.ApplicationDataCreateDisposition.Always);
StorageFile file = fileYouWantToPersist;
if (localSettings.Containers.ContainsKey("FilesToPersist"))
{
localSettings.Containers["FilesToPersist"].Values[file.FolderRelativeId] = DateTime.Now.AddDays(30);
}
// Read data from a setting in a container
bool hasContainer = localSettings.Containers.ContainsKey("FilesToPersist");
bool hasSetting = false;
if (hasContainer)
{
hasSetting = localSettings.Containers["FilesToPersist"].Values.ContainsKey(file.FolderRelativeId);
if(hasSettings)
{
string dt = localSettings.Containers["FilesToPersist"].Values[file.FolderRelativeId];
if(Convert.ToDateTime(dt) < DateTime.Now)
{
//Delete the file
}
}
}
Resources:
http://msdn.microsoft.com/en-us/library/windows/apps/windows.storage.applicationdata.aspx
http://lunarfrog.com/blog/2011/10/10/winrt-storage-accesscache/
Upvotes: 1