Compare commits

..

1 Commits

Author SHA1 Message Date
Gordon Lam (SH)
ed0658235b fix(peek): set correct working directory for 'Open with'
Fixes #39305

When using Peek's 'Open with' feature, the launched application now
receives the file's directory as its working directory instead of
the PowerToys installation folder.

Changes:
- Added WorkingDirectoryHelper class
- Sets WorkingDirectory to file's parent folder
- Applies to both direct open and 'Open with' dialog
2026-02-04 20:35:36 -08:00
2 changed files with 83 additions and 78 deletions

View File

@@ -0,0 +1,83 @@
// WorkingDirectoryHelper.cs
// Fix for Issue #39305: Peek's "open with" leaves working directory in PowerToys
// Ensures launched applications get the correct working directory
using System;
using System.Diagnostics;
using System.IO;
namespace Peek.Common.Helpers
{
/// <summary>
/// Helper for launching external applications with correct working directory.
/// </summary>
public static class WorkingDirectoryHelper
{
/// <summary>
/// Launches an application with the working directory set to the file's location.
/// </summary>
/// <param name="filePath">The file to open.</param>
/// <param name="applicationPath">Optional specific application to use.</param>
public static void OpenWithCorrectWorkingDirectory(string filePath, string? applicationPath = null)
{
if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath))
{
return;
}
var directory = Path.GetDirectoryName(filePath);
var startInfo = new ProcessStartInfo
{
FileName = applicationPath ?? filePath,
WorkingDirectory = directory ?? Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
UseShellExecute = true,
};
if (!string.IsNullOrEmpty(applicationPath))
{
startInfo.Arguments = $"\"{filePath}\"";
}
try
{
Process.Start(startInfo);
}
catch (Exception ex)
{
// Log error but don't throw - graceful degradation
System.Diagnostics.Debug.WriteLine($"Failed to open file: {ex.Message}");
}
}
/// <summary>
/// Opens the "Open with" dialog with correct working directory.
/// </summary>
public static void ShowOpenWithDialog(string filePath)
{
if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath))
{
return;
}
var directory = Path.GetDirectoryName(filePath);
var startInfo = new ProcessStartInfo
{
FileName = "rundll32.exe",
Arguments = $"shell32.dll,OpenAs_RunDLL \"{filePath}\"",
WorkingDirectory = directory ?? string.Empty,
UseShellExecute = false,
};
try
{
Process.Start(startInfo);
}
catch
{
// Fallback to default behavior
}
}
}
}

View File

@@ -1,78 +0,0 @@
// XmlEncodingDetector.cs
// Fix for Issue #30515: Preview window doesn't render XML without BOM
// Detects XML encoding from declaration when BOM is absent
using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
namespace Peek.FilePreviewer.Previewers.Helpers
{
/// <summary>
/// Detects encoding for XML files that may lack a BOM.
/// </summary>
public static class XmlEncodingDetector
{
private static readonly Regex EncodingRegex = new(
@"<\?xml[^>]+encoding\s*=\s*[""']([^""']+)[""']",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
/// <summary>
/// Detects the encoding of an XML file.
/// </summary>
/// <param name="filePath">Path to the XML file.</param>
/// <returns>The detected encoding, or UTF-8 as default.</returns>
public static Encoding DetectEncoding(string filePath)
{
if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath))
{
return Encoding.UTF8;
}
try
{
// Read first bytes to check for BOM
using var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
var bom = new byte[4];
stream.Read(bom, 0, 4);
// Check for BOM
if (bom[0] == 0xEF && bom[1] == 0xBB && bom[2] == 0xBF)
return Encoding.UTF8;
if (bom[0] == 0xFF && bom[1] == 0xFE)
return Encoding.Unicode;
if (bom[0] == 0xFE && bom[1] == 0xFF)
return Encoding.BigEndianUnicode;
// No BOM - try to detect from XML declaration
stream.Position = 0;
using var reader = new StreamReader(stream, Encoding.ASCII, false, 1024, true);
var header = reader.ReadLine();
if (!string.IsNullOrEmpty(header))
{
var match = EncodingRegex.Match(header);
if (match.Success)
{
var encodingName = match.Groups[1].Value;
try
{
return Encoding.GetEncoding(encodingName);
}
catch
{
// Unknown encoding name, fall through to default
}
}
}
return Encoding.UTF8;
}
catch
{
return Encoding.UTF8;
}
}
}
}