MessageBox.Show is called without a MessageBoxOptions argument
ID |
vbnet.portability.specify_message_box_options |
Severity |
low |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Globalization |
Language |
VB.NET |
Description
Reports a call to MessageBox.Show, written either unqualified or through a qualified type
name such as System.Windows.Forms.MessageBox, that passes no MessageBoxOptions value. Any
overload is reported when no MessageBoxOptions member appears among the arguments, including
the owner-window overloads. A call that supplies options - a single member or several combined
with Or - is not reported. The member has to be named at the call site for that: options
passed through a variable or a field, as in MessageBox.Show(text, caption, buttons, icon,
defaultButton, opts), are not recognised and the call is still reported, because the type of
the argument is not available to this analysis.
Rationale
The overload without options accepts the machine’s defaults for two decisions that the
defaults get wrong in exactly the environments that are hardest to test. The first is reading
order. A message box laid out left-to-right inside a right-to-left application does not merely
look inconsistent: the buttons appear in the mirror of the order the user expects, so the
button under the pointer is not the one that was under it in every other dialog in the
application, and "Yes" and "No" swap places on a confirmation prompt. Windows does not infer
this from the thread’s culture, so a fully localised application still shows unmirrored
message boxes until RtlReading and RightAlign are passed explicitly. The second is the
desktop the box appears on. Code that also runs without an interactive desktop - a Windows
service, a scheduled task, an IIS worker - displays the box on a desktop nobody is looking at,
and because Show is modal the calling thread blocks on a dialog that can never be dismissed.
The symptom is a hung service rather than an error, which is why this is usually diagnosed from
a process dump long after deployment.
The following code illustrates the pattern detected by this rule:
Public Sub ReportSaved()
' FLAGGED: MessageBox.Show is called without a MessageBoxOptions argument
MessageBox.Show("The invoice was saved.")
End Sub
Remediation
Pass a MessageBoxOptions value on every Show call. For a localised UI, derive it from the
current culture or the form’s RightToLeft setting and pass
MessageBoxOptions.RtlReading Or MessageBoxOptions.RightAlign when reading order is
right-to-left. For code that may run without an interactive desktop, pass
MessageBoxOptions.ServiceNotification, or better, do not raise a dialog at all from a service
- write to the log or the event log and let the caller decide how to present the failure.
' Before: unmirrored in a right-to-left UI, invisible and blocking in a service
MessageBox.Show("The invoice was saved.", "Billing")
' After
Dim options As MessageBoxOptions = If(RightToLeft = RightToLeft.Yes,
MessageBoxOptions.RtlReading Or MessageBoxOptions.RightAlign,
CType(0, MessageBoxOptions))
MessageBox.Show("The invoice was saved.", "Billing", MessageBoxButtons.OK,
MessageBoxIcon.Information, MessageBoxDefaultButton.Button1, options)