Author SHA1 Message Date
redlineoandClaude Sonnet 5 e40d971de0 Fix crash opening bulk sender window (rows null during InitializeComponent)
Real stack trace from the operator's machine pinned it down: WinForms
fires DataGridView.CellValueChanged as a side effect of
DataGridViewColumn.HeaderText assignments inside InitializeComponent(),
i.e. before PreviewForm's constructor has had a chance to run RunScan()
and populate the `rows` field. UpdateSummaryLabel() then hit
rows.Count(...) on a null source. Nothing to do with Outlook/COM at
all - a pure WinForms initialization-order gotcha.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-24 10:26:29 +03:00
redlineoandClaude Sonnet 5 f50624023a Show full exception detail in error dialogs instead of just Message
An operator hit "Значение не может быть неопределенным. Имя параметра:
source" (ArgumentNullException, ParamName=source) opening the bulk
sender window on a real Outlook install. A full read-through of every
LINQ call reachable from that path found nothing that could receive a
null source, and this dev machine has no Outlook to reproduce against
- so the next occurrence needs a real stack trace to diagnose instead
of guessing from ex.Message alone.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-24 10:19:09 +03:00
3 changed files with 15 additions and 4 deletions

No files matched your search

@@ -60,7 +60,7 @@ namespace BulkArchiveMailer.AddIn
catch (Exception ex) catch (Exception ex)
{ {
MessageBox.Show( MessageBox.Show(
"Не удалось открыть окно массовой рассылки: " + ex.Message, "Не удалось открыть окно массовой рассылки: " + ex.ToString(),
"BulkArchiveMailer", "BulkArchiveMailer",
MessageBoxButtons.OK, MessageBoxButtons.OK,
MessageBoxIcon.Error); MessageBoxIcon.Error);
@@ -39,7 +39,7 @@ namespace BulkArchiveMailer.AddIn.UI
} }
catch (Exception ex) catch (Exception ex)
{ {
MessageBox.Show(this, "Не удалось прочитать настройки: " + ex.Message, "BulkArchiveMailer", MessageBoxButtons.OK, MessageBoxIcon.Error); MessageBox.Show(this, "Не удалось прочитать настройки: " + ex.ToString(), "BulkArchiveMailer", MessageBoxButtons.OK, MessageBoxIcon.Error);
Close(); Close();
return; return;
} }
@@ -128,6 +128,17 @@ namespace BulkArchiveMailer.AddIn.UI
private void UpdateSummaryLabel() private void UpdateSummaryLabel()
{ {
if (rows == null)
{
// Can be invoked before RunScan() ever ran - most notably,
// WinForms fires DataGridView.CellValueChanged as a side
// effect of DataGridViewColumn.HeaderText assignments in
// InitializeComponent(), i.e. before the constructor (and
// therefore RunScan()) has had a chance to populate `rows`.
// Nothing to summarize yet in that case.
return;
}
var ready = rows.Count(r => r.Job.Status == SendStatus.Ready); var ready = rows.Count(r => r.Job.Status == SendStatus.Ready);
var already = rows.Count(r => r.Job.Status == SendStatus.AlreadySent); var already = rows.Count(r => r.Job.Status == SendStatus.AlreadySent);
var errors = rows.Count(r => r.Job.Status == SendStatus.Error); var errors = rows.Count(r => r.Job.Status == SendStatus.Error);
@@ -31,7 +31,7 @@ namespace BulkArchiveMailer.AddIn.UI
catch (Exception ex) catch (Exception ex)
{ {
MessageBox.Show( MessageBox.Show(
"Не удалось прочитать config.json (" + AppSettings.ConfigFilePath + "):\n" + ex.Message + "Не удалось прочитать config.json (" + AppSettings.ConfigFilePath + "):\n" + ex.ToString() +
"\n\nБудут показаны пустые настройки — сохранение перезапишет файл заново.", "\n\nБудут показаны пустые настройки — сохранение перезапишет файл заново.",
"BulkArchiveMailer", "BulkArchiveMailer",
MessageBoxButtons.OK, MessageBoxButtons.OK,
@@ -231,7 +231,7 @@ namespace BulkArchiveMailer.AddIn.UI
} }
catch (Exception ex) catch (Exception ex)
{ {
MessageBox.Show(this, "Не удалось сохранить настройки: " + ex.Message, "BulkArchiveMailer", MessageBoxButtons.OK, MessageBoxIcon.Error); MessageBox.Show(this, "Не удалось сохранить настройки: " + ex.ToString(), "BulkArchiveMailer", MessageBoxButtons.OK, MessageBoxIcon.Error);
return; return;
} }