Jon Rea
Jon Rea

Reputation: 9455

An elegant / performant way to "Touch" a file in (update ModifiedTime) in WinRT?

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

Answers (2)

Thanos
Thanos

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

Zack Weiner
Zack Weiner

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

Related Questions