Compare commits

..

2 Commits

Author SHA1 Message Date
copilot-swe-agent[bot]
94ec17d62a Fix startup crash by adding safe wrappers for assembly location access
Co-authored-by: emako <24737061+emako@users.noreply.github.com>
2025-08-12 02:01:11 +00:00
Copilot
a5241251d4 Initial plan 2025-08-12 01:49:28 +00:00
13 changed files with 86 additions and 38 deletions

View File

@@ -61,8 +61,8 @@ public class AppImageReader
public AppImageReader(string path) public AppImageReader(string path)
{ {
using var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete); using FileStream fs = File.OpenRead(path);
Open(fileStream); Open(fs);
} }
private void Open(Stream stream) private void Open(Stream stream)

View File

@@ -29,7 +29,7 @@ internal static class WgtParser
{ {
public static WgtInfo Parse(string path) public static WgtInfo Parse(string path)
{ {
using var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete); using var fileStream = File.OpenRead(path);
using var zipArchive = new ZipArchive(fileStream, ZipArchiveMode.Read); using var zipArchive = new ZipArchive(fileStream, ZipArchiveMode.Read);
var manifestEntry = zipArchive.GetEntry("manifest.json"); var manifestEntry = zipArchive.GetEntry("manifest.json");

View File

@@ -134,14 +134,14 @@ public partial class ArchiveInfoPanel : UserControl, IDisposable, INotifyPropert
private void LoadItemsFromArchive(string path) private void LoadItemsFromArchive(string path)
{ {
using var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete); using var stream = File.OpenRead(path);
// ReaderFactory is slow... so limit its usage // ReaderFactory is slow... so limit its usage
string[] useReader = [".tar.gz", ".tgz", ".tar.bz2", ".tar.lz", ".tar.xz"]; string[] useReader = [".tar.gz", ".tgz", ".tar.bz2", ".tar.lz", ".tar.xz"];
if (useReader.Any(path.ToLower().EndsWith)) if (useReader.Any(path.ToLower().EndsWith))
{ {
var reader = ReaderFactory.Open(fileStream, new ChardetReaderOptions()); var reader = ReaderFactory.Open(stream, new ChardetReaderOptions());
_type = reader.ArchiveType.ToString(); _type = reader.ArchiveType.ToString();
@@ -149,13 +149,13 @@ public partial class ArchiveInfoPanel : UserControl, IDisposable, INotifyPropert
{ {
if (_disposed) if (_disposed)
return; return;
LoadPercent = 100d * fileStream.Position / fileStream.Length; LoadPercent = 100d * stream.Position / stream.Length;
ProcessByLevel(reader.Entry); ProcessByLevel(reader.Entry);
} }
} }
else else
{ {
var archive = ArchiveFactory.Open(fileStream, new ChardetReaderOptions()); var archive = ArchiveFactory.Open(stream, new ChardetReaderOptions());
_type = archive.Type.ToString(); _type = archive.Type.ToString();
@@ -163,7 +163,7 @@ public partial class ArchiveInfoPanel : UserControl, IDisposable, INotifyPropert
{ {
if (_disposed) if (_disposed)
return; return;
LoadPercent = 100d * fileStream.Position / fileStream.Length; LoadPercent = 100d * stream.Position / stream.Length;
ProcessByLevel(entry); ProcessByLevel(entry);
} }
} }

View File

@@ -40,19 +40,12 @@ internal unsafe static class FreeTypeApi
error = FT_New_Face(lib, (byte*)Marshal.StringToHGlobalAnsi(path), IntPtr.Zero, &face); error = FT_New_Face(lib, (byte*)Marshal.StringToHGlobalAnsi(path), IntPtr.Zero, &face);
try if (error == FT_Error.FT_Err_Ok)
{ {
if (error == FT_Error.FT_Err_Ok) var familyName = Marshal.PtrToStringAnsi((nint)face->family_name);
{ return familyName;
var familyName = Marshal.PtrToStringAnsi((nint)face->family_name);
return familyName;
}
}
finally
{
FT_Done_Face(face);
FT_Done_FreeType(lib);
} }
return null; return null;
} }
} }

View File

@@ -149,11 +149,11 @@ public class WebfontPanel : WebpagePanel
} }
else else
{ {
var localPath = _fallbackPath + Uri.UnescapeDataString(requestedUri.AbsolutePath).Replace('/', '\\'); var localPath = _fallbackPath + requestedUri.AbsolutePath.Replace('/', '\\');
if (File.Exists(localPath)) if (File.Exists(localPath))
{ {
var fileStream = new FileStream(localPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete); var fileStream = File.OpenRead(localPath);
var response = _webView.CoreWebView2.Environment.CreateWebResourceResponse( var response = _webView.CoreWebView2.Environment.CreateWebResourceResponse(
fileStream, 200, "OK", MimeTypes.GetContentType()); fileStream, 200, "OK", MimeTypes.GetContentType());
args.Response = response; args.Response = response;

View File

@@ -210,7 +210,7 @@ public class WebpagePanel : UserControl
if (File.Exists(fallbackFilePath)) if (File.Exists(fallbackFilePath))
{ {
// Serve the file from the fallback directory // Serve the file from the fallback directory
var fileStream = new FileStream(fallbackFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete); var fileStream = File.OpenRead(fallbackFilePath);
var response = _webView.CoreWebView2.Environment.CreateWebResourceResponse( var response = _webView.CoreWebView2.Environment.CreateWebResourceResponse(
fileStream, 200, "OK", "Content-Type: application/octet-stream"); fileStream, 200, "OK", "Content-Type: application/octet-stream");
args.Response = response; args.Response = response;

View File

@@ -27,7 +27,7 @@ internal static class LottieExtractor
{ {
public static string GetJsonContent(string path) public static string GetJsonContent(string path)
{ {
using var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete); using var fileStream = File.OpenRead(path);
using var zipArchive = new ZipArchive(fileStream, ZipArchiveMode.Read); using var zipArchive = new ZipArchive(fileStream, ZipArchiveMode.Read);
var manifestEntry = zipArchive.GetEntry("manifest.json"); var manifestEntry = zipArchive.GetEntry("manifest.json");

View File

@@ -130,11 +130,11 @@ public class SvgImagePanel : WebpagePanel, IWebImagePanel
} }
else else
{ {
var localPath = _fallbackPath + Uri.UnescapeDataString(requestedUri.AbsolutePath).Replace('/', '\\'); var localPath = _fallbackPath + requestedUri.AbsolutePath.Replace('/', '\\');
if (File.Exists(localPath)) if (File.Exists(localPath))
{ {
var fileStream = new FileStream(localPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete); var fileStream = File.OpenRead(localPath);
var response = _webView.CoreWebView2.Environment.CreateWebResourceResponse( var response = _webView.CoreWebView2.Environment.CreateWebResourceResponse(
fileStream, 200, "OK", MimeTypes.GetContentTypeHeader()); fileStream, 200, "OK", MimeTypes.GetContentTypeHeader());
args.Response = response; args.Response = response;
@@ -149,7 +149,7 @@ public class SvgImagePanel : WebpagePanel, IWebImagePanel
{ {
if (File.Exists(localPath)) if (File.Exists(localPath))
{ {
var fileStream = new FileStream(localPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete); var fileStream = File.OpenRead(localPath);
var response = _webView.CoreWebView2.Environment.CreateWebResourceResponse( var response = _webView.CoreWebView2.Environment.CreateWebResourceResponse(
fileStream, 200, "OK", fileStream, 200, "OK",
$""" $"""

View File

@@ -124,11 +124,11 @@ public class MarkdownPanel : WebpagePanel
} }
else else
{ {
var localPath = _fallbackPath + Uri.UnescapeDataString(requestedUri.AbsolutePath).Replace('/', '\\'); var localPath = _fallbackPath + requestedUri.AbsolutePath.Replace('/', '\\');
if (File.Exists(localPath)) if (File.Exists(localPath))
{ {
var fileStream = new FileStream(localPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete); var fileStream = File.OpenRead(localPath);
var response = _webView.CoreWebView2.Environment.CreateWebResourceResponse( var response = _webView.CoreWebView2.Environment.CreateWebResourceResponse(
fileStream, 200, "OK", MimeTypes.GetContentType()); fileStream, 200, "OK", MimeTypes.GetContentType());
args.Response = response; args.Response = response;

View File

@@ -34,7 +34,6 @@ public class Plugin : IViewer
".xls", ".xlsx", ".xlsm", ".xlsb", ".ods", ".xls", ".xlsx", ".xlsm", ".xlsb", ".ods",
".ppt", ".pptx", ".odp", ".ppt", ".pptx", ".odp",
".vsd", ".vsdx", ".vsd", ".vsdx",
".ofd",
]; ];
private PreviewPanel _panel; private PreviewPanel _panel;

View File

@@ -69,9 +69,9 @@ public class Plugin : IViewer
if (path.EndsWith(".rtf", StringComparison.OrdinalIgnoreCase)) if (path.EndsWith(".rtf", StringComparison.OrdinalIgnoreCase))
{ {
var rtfBox = new RichTextBox(); var rtfBox = new RichTextBox();
using var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete); using FileStream fs = File.OpenRead(path);
rtfBox.Background = new SolidColorBrush(Colors.Transparent); rtfBox.Background = new SolidColorBrush(Colors.Transparent);
rtfBox.Selection.Load(fileStream, DataFormats.Rtf); rtfBox.Selection.Load(fs, DataFormats.Rtf);
rtfBox.IsReadOnly = true; rtfBox.IsReadOnly = true;
rtfBox.VerticalScrollBarVisibility = ScrollBarVisibility.Auto; rtfBox.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
rtfBox.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto; rtfBox.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;

View File

@@ -187,8 +187,8 @@ public class HighlightingThemeManager
{ {
Debug.WriteLine(file); Debug.WriteLine(file);
var ext = Path.GetFileNameWithoutExtension(file); var ext = Path.GetFileNameWithoutExtension(file);
using var fileStream = new FileStream(Path.GetFullPath(file), FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete); using Stream s = File.OpenRead(Path.GetFullPath(file));
using var reader = new XmlTextReader(fileStream); using var reader = new XmlTextReader(s);
var xshd = HighlightingLoader.LoadXshd(reader); var xshd = HighlightingLoader.LoadXshd(reader);
var highlightingDefinition = HighlightingLoader.Load(xshd, hlm); var highlightingDefinition = HighlightingLoader.Load(xshd, hlm);
if (xshd.Extensions.Count > 0) if (xshd.Extensions.Count > 0)

View File

@@ -37,16 +37,72 @@ namespace QuickLook;
public partial class App : Application public partial class App : Application
{ {
public static readonly string LocalDataPath = SettingHelper.LocalDataPath; public static readonly string LocalDataPath = GetSafeLocalDataPath();
public static readonly string UserPluginPath = Path.Combine(SettingHelper.LocalDataPath, @"QuickLook.Plugin\"); public static readonly string UserPluginPath = Path.Combine(LocalDataPath, @"QuickLook.Plugin\");
public static readonly string AppFullPath = Assembly.GetExecutingAssembly().Location; public static readonly string AppFullPath = Assembly.GetExecutingAssembly().Location ?? string.Empty;
public static readonly string AppPath = Path.GetDirectoryName(AppFullPath); public static readonly string AppPath = GetSafeAppPath();
public static readonly bool Is64Bit = Environment.Is64BitProcess; public static readonly bool Is64Bit = Environment.Is64BitProcess;
public static readonly bool IsUWP = ProcessHelper.IsRunningAsUWP(); public static readonly bool IsUWP = ProcessHelper.IsRunningAsUWP();
public static readonly bool IsWin11 = Environment.OSVersion.Version >= new Version(10, 0, 21996); public static readonly bool IsWin11 = Environment.OSVersion.Version >= new Version(10, 0, 21996);
public static readonly bool IsWin10 = !IsWin11 && Environment.OSVersion.Version >= new Version(10, 0); public static readonly bool IsWin10 = !IsWin11 && Environment.OSVersion.Version >= new Version(10, 0);
public static readonly bool IsGPUInBlacklist = SystemHelper.IsGPUInBlacklist(); public static readonly bool IsGPUInBlacklist = SystemHelper.IsGPUInBlacklist();
public static readonly bool IsPortable = SettingHelper.IsPortableVersion(); public static readonly bool IsPortable = SafeIsPortableVersion();
private static string GetSafeLocalDataPath()
{
try
{
return SettingHelper.LocalDataPath;
}
catch (ArgumentException)
{
// Fallback: determine data path based on portable mode detection
var isPortable = SafeIsPortableVersion();
if (isPortable)
{
var assemblyLocation = Assembly.GetExecutingAssembly().Location;
var assemblyDir = !string.IsNullOrEmpty(assemblyLocation)
? Path.GetDirectoryName(assemblyLocation)
: AppDomain.CurrentDomain.BaseDirectory;
return Path.Combine(assemblyDir ?? string.Empty, @"UserData\");
}
else
{
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
@"pooi.moe\QuickLook\");
}
}
}
private static bool SafeIsPortableVersion()
{
try
{
return SettingHelper.IsPortableVersion();
}
catch (ArgumentException)
{
// Fallback: check for portable.lock file in current directory or base directory
var assemblyLocation = Assembly.GetExecutingAssembly().Location;
var assemblyDir = !string.IsNullOrEmpty(assemblyLocation)
? Path.GetDirectoryName(assemblyLocation)
: AppDomain.CurrentDomain.BaseDirectory;
var lck = Path.Combine(assemblyDir ?? string.Empty, "portable.lock");
return File.Exists(lck);
}
}
private static string GetSafeAppPath()
{
var assemblyLocation = Assembly.GetExecutingAssembly().Location;
if (!string.IsNullOrEmpty(assemblyLocation))
{
return Path.GetDirectoryName(assemblyLocation) ?? string.Empty;
}
return AppDomain.CurrentDomain.BaseDirectory;
}
private bool _cleanExit = true; private bool _cleanExit = true;
private Mutex _isRunning; private Mutex _isRunning;