Only open FilStream in read-only mode; Release propertyStore handle after getting the file properties

This commit is contained in:
Yawen Hou 2023-05-10 13:24:26 -04:00
parent c6182a43bb
commit 3b1481da2c
6 changed files with 51 additions and 20 deletions

View File

@ -21,9 +21,8 @@ namespace Peek.Common.Extensions
{ {
Size? size = null; Size? size = null;
var propertyStore = item.PropertyStore; var width = item.Width;
var width = propertyStore.TryGetUInt(PropertyKey.ImageHorizontalSize); var height = item.Height;
var height = propertyStore.TryGetUInt(PropertyKey.ImageVerticalSize);
if (width != null && height != null) if (width != null && height != null)
{ {
@ -36,8 +35,7 @@ namespace Peek.Common.Extensions
public static Size? GetSvgSize(this IFileSystemItem item) public static Size? GetSvgSize(this IFileSystemItem item)
{ {
Size? size = null; Size? size = null;
using (FileStream stream = new FileStream(item.Path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete))
using (FileStream stream = System.IO.File.OpenRead(item.Path))
{ {
XmlReaderSettings settings = new XmlReaderSettings(); XmlReaderSettings settings = new XmlReaderSettings();
settings.Async = true; settings.Async = true;
@ -95,8 +93,7 @@ namespace Peek.Common.Extensions
sizeInBytes = (ulong)folder.Size; sizeInBytes = (ulong)folder.Size;
break; break;
case FileItem _: case FileItem _:
var propertyStore = item.PropertyStore; var propertyStore = item.FileSizeBytes;
sizeInBytes = propertyStore.TryGetULong(PropertyKey.FileSizeBytes) ?? 0;
break; break;
} }
@ -117,8 +114,7 @@ namespace Peek.Common.Extensions
contentType = storageFolder.DisplayType; contentType = storageFolder.DisplayType;
break; break;
default: default:
var propertyStore = item.PropertyStore; var propertyStore = item.FileType;
contentType = propertyStore.TryGetString(PropertyKey.FileType) ?? string.Empty;
break; break;
} }

View File

@ -3,7 +3,9 @@
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System; using System;
using System.Runtime.InteropServices;
using System.Threading.Tasks; using System.Threading.Tasks;
using Peek.Common.Extensions;
using Peek.Common.Helpers; using Peek.Common.Helpers;
using Windows.Storage; using Windows.Storage;
@ -15,17 +17,28 @@ namespace Peek.Common.Models
{ {
private StorageFile? storageFile; private StorageFile? storageFile;
private Lazy<IPropertyStore> _propertyStore;
public FileItem(string path) public FileItem(string path)
{ {
Path = path; Path = path;
_propertyStore = new(() => PropertyStoreHelper.GetPropertyStoreFromPath(Path)); var propertyStore = PropertyStoreHelper.GetPropertyStoreFromPath(Path);
Width = propertyStore.TryGetUInt(PropertyKey.ImageHorizontalSize) ?? 0;
Height = propertyStore.TryGetUInt(PropertyKey.ImageVerticalSize) ?? 0;
FileSizeBytes = propertyStore.TryGetULong(PropertyKey.FileSizeBytes) ?? 0;
FileType = propertyStore.TryGetString(PropertyKey.FileType) ?? string.Empty;
// Release property store so it no longer holds the file open
Marshal.FinalReleaseComObject(propertyStore);
} }
public string Path { get; init; } public string Path { get; init; }
public IPropertyStore PropertyStore => _propertyStore.Value; public uint? Width { get; init; }
public uint? Height { get; init; }
public ulong FileSizeBytes { get; init; }
public string FileType { get; init; }
public async Task<IStorageItem?> GetStorageItemAsync() public async Task<IStorageItem?> GetStorageItemAsync()
{ {

View File

@ -3,7 +3,9 @@
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System; using System;
using System.Runtime.InteropServices;
using System.Threading.Tasks; using System.Threading.Tasks;
using Peek.Common.Extensions;
using Peek.Common.Helpers; using Peek.Common.Helpers;
using Windows.Storage; using Windows.Storage;
@ -15,17 +17,26 @@ namespace Peek.Common.Models
{ {
private StorageFolder? storageFolder; private StorageFolder? storageFolder;
private Lazy<IPropertyStore> _propertyStore;
public FolderItem(string path) public FolderItem(string path)
{ {
Path = path; Path = path;
_propertyStore = new(() => PropertyStoreHelper.GetPropertyStoreFromPath(Path)); var propertyStore = PropertyStoreHelper.GetPropertyStoreFromPath(Path);
FileSizeBytes = propertyStore.TryGetULong(PropertyKey.FileSizeBytes) ?? 0;
FileType = propertyStore.TryGetString(PropertyKey.FileType) ?? string.Empty;
// Release property store so it no longer holds the file open
Marshal.FinalReleaseComObject(propertyStore);
} }
public string Path { get; init; } public string Path { get; init; }
public IPropertyStore PropertyStore => _propertyStore.Value; public uint? Width { get; init; }
public uint? Height { get; init; }
public ulong FileSizeBytes { get; init; }
public string FileType { get; init; }
public async Task<IStorageItem?> GetStorageItemAsync() public async Task<IStorageItem?> GetStorageItemAsync()
{ {

View File

@ -22,7 +22,13 @@ namespace Peek.Common.Models
public string Path { get; init; } public string Path { get; init; }
public IPropertyStore PropertyStore { get; } public uint? Width { get; init; }
public uint? Height { get; init; }
public ulong FileSizeBytes { get; init; }
public string FileType { get; init; }
public Task<IStorageItem?> GetStorageItemAsync(); public Task<IStorageItem?> GetStorageItemAsync();
} }

View File

@ -210,7 +210,7 @@ namespace Peek.FilePreviewer.Previewers
{ {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
using FileStream stream = File.OpenRead(Item.Path); using FileStream stream = ReadHelper.OpenReadOnly(Item.Path);
await Dispatcher.RunOnUiThread(async () => await Dispatcher.RunOnUiThread(async () =>
{ {

View File

@ -12,11 +12,16 @@ namespace Peek.FilePreviewer.Previewers
{ {
public static async Task<string> Read(string path) public static async Task<string> Read(string path)
{ {
using var fs = new FileStream(path, FileMode.Open, FileAccess.Read); using var fs = OpenReadOnly(path);
using var sr = new StreamReader(fs, Encoding.UTF8); using var sr = new StreamReader(fs, Encoding.UTF8);
string content = await sr.ReadToEndAsync(); string content = await sr.ReadToEndAsync();
return content; return content;
} }
public static FileStream OpenReadOnly(string path)
{
return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
}
} }
} }