#c# #.net #interop
#c# #.net #взаимодействие
Вопрос:
Я использую приведенный ниже код для получения запущенного экземпляра MS Word.
Теперь у меня проблема с компиляцией с использованием неназначенной локальной переменной «oWord»‘
вот мой код:
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;
но, на мой взгляд, oWord назначен, я предполагаю, что компилятор просматривает мой блок Try ..Catch и говорит, что у меня неназначенный oWord
Итак, как правильно назначить это?
Комментарии:
1.
Microsoft.Office.Interop.Word._Application oWord = null
2. Какое значение
oWord
имеет значениеif
false?
Ответ №1:
Возможно, она никогда не будет назначена, если Marshal.GetActiveObject
вызов завершится неудачно, но код ошибки — это нечто иное, чем unchecked((int)0x800401E3)
.
Вам нужно установить oWord
что-то при первом объявлении:
Microsoft.Office.Interop.Word._Application oWord = null;
или
Microsoft.Office.Interop.Word._Application oWord = new Microsoft.Office.Interop.Word.Application();
Я бы, вероятно, сделал последнее. Это также устраняет необходимость в проверке null дальше по строке, что прямо сейчас вам действительно нужно, поскольку вы не выполняете полный прерывание, если в этом блоке try / catch обнаружено исключение.
(Сказав это, если это действительно приведет к запуску Word, если он еще не запущен, выберите первый вариант, а затем убедитесь oWord
, что после try / catch значение по-прежнему не равно null.)
Комментарии:
1. Проблема здесь в том, что вы не обрабатываете ошибки COM, кроме
MK_E_UNAVAILABLE
. Вам нужно что-то с ними сделать. Ваш ответ ведет кnull
проверкам, но это просто беспорядочно. Особенно когда есть очень простой способ решить проблему.2. @DavidHeffernan согласился. Ваш ответ — лучший подход.
Ответ №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;
Давайте попробуем понять, почему компилятор сообщает вам, что oWord
она не может быть назначена после выполнения этого кода.
- Если код внутри
try
выполняется без исключения, тоoWord
он должен быть назначен. - Или, если этот код выдает исключение, он может быть необработанным, и в этом случае он распространяется за пределы кода выше.
- Или, если код в try выдает
COMException
, он будет перехвачен. Если код ошибки0x800401E31
затемoWord
присваивается. - Или, если код ошибки отличается от
0x800401E3
, тоoWord
никогда не присваивается.
Мы можем аннотировать ваш код, чтобы продемонстрировать это более наглядно:
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;
На мой взгляд, самый простой способ справиться с этим — повторно создать исключение.
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;
Это позволяет избежать необходимости инициализировать переменную null
и позже проверять, все ли она еще существует null
.
Более того, он явно обрабатывает условие ошибки, которое ваш код не может обработать. А именно ошибка COM, отличная от MK_E_UNAVAILABLE
.
Комментарии:
1. @DavidHefferman: Спасибо за такой полностью информативный и полезный ответ… Я только что кое-что узнал!
Ответ №3:
Просто присвоите ей null
значение по умолчанию:
Microsoft.Office.Interop.Word._Application oWord = null;
Это необходимо, потому что в настоящее время код присваивает ей значение в if statement
блоке catch {} , поэтому возможно, что oWord
никогда не получит значение без начального / значения по умолчанию.
Комментарии:
1. Я не думаю, что области здесь уместны. Проблема просто в том, что локальная переменная не может быть назначена.
2. я меняю свой ответ, чтобы обозначить
if
оператор.3. На мой взгляд, вам, как и @Anna, не хватает какой-либо обработки ошибок COM, кроме
MK_E_UNAVAILABLE
. Инициализацияnull
просто выдает ошибку времени компиляции за ошибку времени выполнения.4. Я не согласен. В этом суть вопроса. Именно поэтому переменная не инициализируется из-за того, что это условие не обрабатывается.
5. Нет. Вы вообще не понимаете. Переменная может по-прежнему иметь значение null после завершения catch, а затем вы обменяли ошибку времени компиляции на ошибку времени выполнения. Вам нужно устранить основную причину, по которой компилятор правильно жаловался.