diff --git a/src/EverythingToJpeg.App/App.xaml.cs b/src/EverythingToJpeg.App/App.xaml.cs
index 4796741..e005df4 100644
--- a/src/EverythingToJpeg.App/App.xaml.cs
+++ b/src/EverythingToJpeg.App/App.xaml.cs
@@ -13,6 +13,8 @@ public partial class App : Application
{
base.OnStartup(e);
+ WireGlobalExceptionLogging();
+
var parsed = CliRouter.Parse(e.Args);
switch (parsed.Mode)
@@ -116,4 +118,38 @@ public partial class App : Application
try { File.WriteAllText(logPath, log.ToString()); } catch { }
}
}
+
+ private static void WireGlobalExceptionLogging()
+ {
+ var path = Path.Combine(Path.GetTempPath(), "EverythingToJpeg_unhandled.log");
+
+ void Append(string source, Exception? ex)
+ {
+ try
+ {
+ File.AppendAllText(path,
+ $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] {source}\n{ex}\n\n");
+ }
+ catch { }
+ }
+
+ AppDomain.CurrentDomain.UnhandledException += (_, e) =>
+ Append("AppDomain.UnhandledException", e.ExceptionObject as Exception);
+
+ Current.DispatcherUnhandledException += (_, e) =>
+ {
+ Append("Application.DispatcherUnhandledException", e.Exception);
+ MessageBox.Show(
+ "예기치 못한 오류:\n\n" + e.Exception.Message + "\n\n로그: " + path,
+ "EverythingToJpeg",
+ MessageBoxButton.OK, MessageBoxImage.Error);
+ e.Handled = true;
+ };
+
+ System.Threading.Tasks.TaskScheduler.UnobservedTaskException += (_, e) =>
+ {
+ Append("TaskScheduler.UnobservedTaskException", e.Exception);
+ e.SetObserved();
+ };
+ }
}
diff --git a/src/EverythingToJpeg.App/Views/ConvertWindow.xaml b/src/EverythingToJpeg.App/Views/ConvertWindow.xaml
index c97a5f9..f896c18 100644
--- a/src/EverythingToJpeg.App/Views/ConvertWindow.xaml
+++ b/src/EverythingToJpeg.App/Views/ConvertWindow.xaml
@@ -147,7 +147,51 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/EverythingToJpeg.App/Views/ConvertWindow.xaml.cs b/src/EverythingToJpeg.App/Views/ConvertWindow.xaml.cs
index ad409fd..e3ede57 100644
--- a/src/EverythingToJpeg.App/Views/ConvertWindow.xaml.cs
+++ b/src/EverythingToJpeg.App/Views/ConvertWindow.xaml.cs
@@ -22,7 +22,6 @@ public partial class ConvertWindow : FluentWindow
InitializeComponent();
FilesList.ItemsSource = _entries;
- FilesList.ItemTemplate = (DataTemplate)CreateFileEntryTemplate();
AddFiles(initialFiles);
@@ -113,19 +112,51 @@ public partial class ConvertWindow : FluentWindow
}
}
+ private static readonly string DialogLogPath =
+ Path.Combine(Path.GetTempPath(), "EverythingToJpeg_dialog.log");
+
+ private static void DiagLog(string line)
+ {
+ try
+ {
+ File.AppendAllText(DialogLogPath,
+ $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] {line}{Environment.NewLine}");
+ }
+ catch { }
+ }
+
private async void OnConvertClick(object sender, RoutedEventArgs e)
{
+ DiagLog($"OnConvertClick: entries={_entries.Count}");
+
if (_entries.Count == 0)
{
+ DiagLog(" → no entries, showing info");
ShowInfo("변환할 파일이 없습니다.");
return;
}
ConvertButton.IsEnabled = false;
CancelButton.Content = "취소";
+ ProgressStatusText.Text = "준비 중…";
_cts = new CancellationTokenSource();
- var options = BuildOptions();
+ ConvertOptions options;
+ try
+ {
+ options = BuildOptions();
+ DiagLog($" options: Quality={options.Quality} OutputLocation={options.OutputLocation} Custom={options.CustomOutputDirectory} Collision={options.OnCollision} MaxLong={options.MaxLongEdgePixels} PdfDpi={options.PdfDpi}");
+ }
+ catch (Exception ex)
+ {
+ DiagLog(" BuildOptions threw: " + ex);
+ ProgressStatusText.Text = "옵션 처리 오류: " + ex.Message;
+ ConvertButton.IsEnabled = true;
+ CancelButton.Content = "닫기";
+ _cts = null;
+ return;
+ }
+
var reporter = new Progress(p =>
{
var overall = p.Total == 0 ? 0 : (p.Index + p.FileProgress) / p.Total;
@@ -137,17 +168,27 @@ public partial class ConvertWindow : FluentWindow
try
{
var sources = _entries.Select(en => en.Path).ToList();
+ DiagLog($" starting ConvertManyAsync, {sources.Count} files");
var results = await _engine.ConvertManyAsync(sources, options, reporter, _cts.Token);
+ DiagLog($" finished, {results.Count} results");
+ foreach (var r in results)
+ DiagLog($" [{r.Status}] {Path.GetFileName(r.SourcePath)} msg={r.Message}");
ApplyResults(results);
ProgressStatusText.Text = SummarizeResults(results);
}
catch (OperationCanceledException)
{
+ DiagLog(" canceled");
ProgressStatusText.Text = "변환이 취소되었습니다.";
}
catch (Exception ex)
{
+ DiagLog(" EXCEPTION: " + ex);
ProgressStatusText.Text = "오류: " + ex.Message;
+ MessageBox.Show(this,
+ "변환 중 오류가 발생했습니다:\n\n" + ex.Message + "\n\n로그: " + DialogLogPath,
+ "EverythingToJpeg",
+ MessageBoxButton.OK, MessageBoxImage.Error);
}
finally
{
@@ -234,54 +275,6 @@ public partial class ConvertWindow : FluentWindow
=> MessageBox.Show(this, message, "EverythingToJpeg",
MessageBoxButton.OK, MessageBoxImage.Information);
- private object CreateFileEntryTemplate()
- {
- const string xaml = """
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- """;
- return System.Windows.Markup.XamlReader.Parse(xaml);
- }
}
public sealed class FileEntry : System.ComponentModel.INotifyPropertyChanged