c# use of unassigned local variable after Try..Catch

1

I am using the below code to get a running instance of MS Word.

I now have a compile problem with 'Use of unassigned local variable "oWord"'

here is my code:

Microsoft.Office.Interop.Word._Application oWord ; 

try
{
// Is Word running?
oWord = Marshal.GetActiveObject("Word.Application") as Microsoft.Office.Interop.Word.Application; // ApplicationClass;
}
catch (COMException ce)
{
if (ce.ErrorCode == unchecked((int)0x800401E3))
    // No, Word not in ROT, start a new instance
    oWord = new Microsoft.Office.Interop.Word.Application();
}
// Use instance referened by _WordApp 

oWord.ScreenUpdating = false; // < PROBLEM HERE

object objDefaultBehaviorWord8 = WdDefaultTableBehavior.wdWord8TableBehavior;
object objAutoFitFixed = WdAutoFitBehavior.wdAutoFitFixed;

//MAKING THE APPLICATION VISIBLE
oWord.Visible = Properties.Settings.Default.DebugMode;
oWord.DisplayAlerts = WdAlertLevel.wdAlertsNone;

but to my mind oWord is assigned, I'm guessing that the the compiler is looking at my Try..Catch block and saying I have unassigned oWord

So what's the correct way to assign this?

c#
.net
interop

3 Answers

6

It might never get assigned if the Marshal.GetActiveObject call fails, but the error code is something other than unchecked((int)0x800401E3).

You need to set oWord to something when you first declare it:

Microsoft.Office.Interop.Word._Application oWord = null;

or

Microsoft.Office.Interop.Word._Application oWord = new Microsoft.Office.Interop.Word.Application();

I'd probably do the latter. That also removes the need for null checks further down the line, which right now you really should have since you're not fully aborting if there's an exception caught in that try/catch block.

(Having said that, if doing that will actually start Word if it's not already running, go with the first option and then make sure oWord isn't still null after the try/catch.)

answered on Stack Overflow Jun 30, 2014 by Adam Lear • edited Jun 30, 2014 by Adam Lear
2

Just assign it a default null value:

Microsoft.Office.Interop.Word._Application oWord = null;

This is necessary because the code currently assigns it a value in the if statement of the catch {} block, so it's possible that oWord never gets a value without the initial/default value.

answered on Stack Overflow Jun 30, 2014 by T McKeown • edited Jun 30, 2014 by T McKeown
2
Microsoft.Office.Interop.Word._Application oWord; 
try
{
    oWord = Marshal.GetActiveObject("Word.Application") as
        Microsoft.Office.Interop.Word.Application;
}
catch (COMException ce)
{
    if (ce.ErrorCode == unchecked((int)0x800401E3))
        oWord = new Microsoft.Office.Interop.Word.Application();
}
oWord.ScreenUpdating = false;

Let's try to see why the compiler tells you that oWord may not be assigned after this code has executed.

  1. If the code inside the try executes without exception, then oWord must be assigned.
  2. Or, if that code throws an exception it may be unhandled, in which case it propagates beyond the code above.
  3. Or, if the code in the try throws COMException it will be caught. If the error code is 0x800401E31 then oWord is assigned.
  4. Or, if the error code is other than 0x800401E3, then oWord is never assigned.

We can annotate your code to demonstrate this more clearly:

Microsoft.Office.Interop.Word._Application oWord; 
try
{
    oWord = Marshal.GetActiveObject("Word.Application") as
        Microsoft.Office.Interop.Word.Application;
}
catch (COMException ce)
{
    // oWord still not initialized ....
    if (ce.ErrorCode == unchecked((int)0x800401E3))
        oWord = new Microsoft.Office.Interop.Word.Application();
    else
        ; // .... and still not initialized ....
}
oWord.ScreenUpdating = false;

The simplest way to deal with this, in my view, is to re-throw the exception.

Microsoft.Office.Interop.Word._Application oWord; 
try
{
    oWord = Marshal.GetActiveObject("Word.Application") as
        Microsoft.Office.Interop.Word.Application;
}
catch (COMException ce)
{
    if (ce.ErrorCode != unchecked((int)0x800401E3))
        throw;
    oWord = new Microsoft.Office.Interop.Word.Application();
}
oWord.ScreenUpdating = false;

This avoids the need to initialiaze the variable to null and later test for it still being null.

What's more it explicitly deals with the error condition that your code fails to handle. Namely a COM error other than MK_E_UNAVAILABLE.

answered on Stack Overflow Jun 30, 2014 by David Heffernan • edited Jun 30, 2014 by David Heffernan

User contributions licensed under CC BY-SA 3.0