BUG: "Отмена" для событий Office игнорируется в Visual Studio .NET 2003

Переводы статьи Переводы статьи
Код статьи: 830519 - Vizualiza?i produsele pentru care se aplic? acest articol.
Эта статья помещена в архив. Она предлагается "как есть" и обновляться не будет.
Развернуть все | Свернуть все

В этой статье

Аннотация

При работе с Microsoft Visual Studio .NET 2003, могут возникнуть проблемы при использованииОтмена:параметр события COM, которое возникает в Microsoft Word, Microsoft Excel или Microsoft Outlook. Несмотря на то, что код получает события модели COM и код таким образом, можно задать параметр COM не отменить событие. Данная проблема возникает, когда использовать взаимодействие COM из управляемого клиента (например, Microsoft Visual C# или Microsoft Visual Basic .NET), а также использовать Microsoft .NET Framework версии 1.1.

Причина

.NET Framework 1.1 представила изменения системы безопасности для повышения безопасности типа, когда взаимодействие с COM-компонента. .NET Framework 1.1 повышает строгую типизацию, используя сведения о маршалинге в библиотеку типов компонента. При автоматизации Word, Excel или Microsoft Outlook из управляемого клиента, сборки взаимодействия COM (IA) или основной сборки взаимодействия (PIA) Microsoft Office XP использует сведения о типе, хранящиеся в библиотеках типов Microsoft Office для обработки событий. Существующие версии Word введите знак библиотеки типов Microsoft Outlook, библиотеки и библиотеки типов Microsoft ExcelОтмена:параметр[в]Parameter:. надписьюОтмена:параметр помечен как[в]параметр таким образом, чтобы общеязыковая среда выполнения применяет это ограничение и предотвращает любые изменения, внесенные с управляемым кодом, возвращаемых в вызывающий объект. Таким образом оно не может быть отменено из управляемого кода IA (PIA).

Решение

Данная ошибка была исправлена в Microsoft Office 2003.

Временное решение

При использовании более ранней версии Word, Excel более ранней версии или более ранняя версия Outlook, необходимо установить собственный приемник точки подключения в управляемом коде. Пользовательский обработчик может избежать зависимостей библиотеки типов и защиты применяется тип, который обычно применяется. Таким образом аргумент может быть передан обратно в вызывающий объект.

Корпорация Майкрософт предлагает примеры программного кода только для иллюстрации, без каких-либо явных или подразумеваемых гарантий.. Включая, но не ограничивая, подразумеваемые гарантии товарности или пригодности для использования в определенных целях.. В данной статье предполагается, что вы знакомы с языком программирования предложенном в примере, а также с средствами, которые используются для создания и отладки.. Сотрудники службы поддержки Майкрософт могут объяснить возможности конкретной процедуры, но не выполнять модификации примеров для обеспечения функциональных возможностей или создания процедур соответствующих определенным требованиям..

Создание класса модуля поддержки

Чтобы непосредственно приемника событий в Visual C#, необходимо создать свое собственное определение диспетчерский интерфейс и необходимо также создать вспомогательный класс для реализации кода события. Диспетчерский интерфейс определение должно соответствовать глобальный уникальный идентификатор (GUID) и идентификаторов диспетчеризации (DISPID) для приемника событий, который ожидает события для объекта Microsoft Office. Чтобы узнать, каковы эти значения, можно использовать любой из следующих способов:
  • Можно использовать средство просмотра объектов OLE/COM, который входит в состав Visual Studio .NET 2003 Professional Edition
  • Можно использовать Platform SDK. Для получения дополнительных сведений о пакете Platform SDK посетите следующий веб-узел корпорации Майкрософт:

    http://www.Microsoft.com/msdownload/platformsdk/sdkupdate
После известен идентификатор GUID и идентификаторов DispId, можно создать свое собственное определение определения диспетчерский интерфейс в Visual Basic .NET или Visual C#.

This article provides you two examples that show you how to use custom connection point to work around this problem. The first example demonstrates how to sink theПриложениеobject events for Word 2000 and then cancel theDocumentBeforeCloseevent so that the user cannot close the document. The second example sinks theItemSendevent for Outlook 2002, so that you can cancel the Send operation in your application.

Example 1: CancelDocumentBeforeCloseСобытие:

  1. Start Visual Studio .NET 2003. Start a new project. SelectВ Visual C#as the project type. SelectWindows Applicationas the template. Имя проектаMyWordEventTestи выберите командуOk..

    По умолчанию будет создана форма Form1..
  2. в менюProjectвыберите пунктДобавить ссылку. In the dialog box, selectMicrosoft Word 9.0 Object Libraryon the COM tab. ClickSelectto add a reference, and then clickOk.Чтобы закрыть диалоговое окно.

    A custom IA is generated for you automatically.
  3. в менюProjectвыберите пунктAdd a Class. SelectCode File, and then name the classWord9EventHelper.cs. затем –Ok.to generate the file.
  4. Add the following code to the code window for Word9EventHelper.cs:
    using System;
    using System.Runtime.InteropServices;
    using Word; // The default name for a custom Word IA.
    // If you use Office XP and you have the PIAs
    // referenced in your project, you must change the previous line to read:
    // using Word = Microsoft.Office.Interop.Word;
    
    namespace WordAppEvents9
    {
    	[InterfaceType(ComInterfaceType.InterfaceIsIDispatch),
    	GuidAttribute("000209FE-0000-0000-C000-000000000046")]
    	public interface DWordApplicationEvents9
    	{
    		[DispId(0x00000001)] void Startup();
    		[DispId(0x00000002)] void Quit();
    		[DispId(0x00000003)] void DocumentChange();
    		[DispId(0x00000004)] void DocumentOpen(Word.Document doc);
    		[DispId(0x00000006)] void DocumentBeforeClose(Word.Document doc, ref bool Cancel);	
    		[DispId(0x00000007)] void DocumentBeforePrint(Word.Document doc, ref bool Cancel);
    		[DispId(0x00000008)] void DocumentBeforeSave(Word.Document doc, ref bool SaveAsUI, ref bool Cancel);
    		[DispId(0x00000009)] void NewDocument(Word.Document doc);
    		[DispId(0x0000000a)] void WindowActivate(Word.Document doc, Word.Window wn);
    		[DispId(0x0000000b)] void WindowDeactivate(Word.Document doc, Word.Window wn);
    		[DispId(0x0000000c)] void WindowSelectionChange(Word.Selection sel);
    		[DispId(0x0000000d)] void WindowBeforeRightClick(Word.Selection sel, ref bool Cancel);
    		[DispId(0x0000000e)] void WindowBeforeDoubleClick(Word.Selection sel, ref bool Cancel);
    	}
    
    
    	public class WordAppEventHelper : DWordApplicationEvents9, IDisposable
    	{
    		public WordAppEventHelper()
    		{
    			m_oConnectionPoint = null;
    			m_Cookie = 0;
    		}
    
    		public void Startup()
    		{System.Diagnostics.Debug.WriteLine("Startup");}
    
    		public void Quit()
    		{System.Diagnostics.Debug.WriteLine("Quit");}
    
    		public void DocumentChange()
    		{System.Diagnostics.Debug.WriteLine("DocumentChange");}
    
    		public void DocumentOpen(Word.Document doc)
    		{System.Diagnostics.Debug.WriteLine("DocumentOpen");}
    
    		public void DocumentBeforeClose(Word.Document doc, ref bool Cancel)
    		{
    			System.Diagnostics.Debug.WriteLine("DocumentBeforeClose");
    			Cancel = true; // Cancel the close!
    		}
    
    		public void DocumentBeforePrint(Word.Document doc, ref bool Cancel)
    		{System.Diagnostics.Debug.WriteLine("DocumentBeforePrint");}
    
    		public void DocumentBeforeSave(Word.Document doc, ref bool SaveAsUI, ref bool Cancel)
    		{System.Diagnostics.Debug.WriteLine("DocumentBeforeSave");}
    
    		public void NewDocument(Word.Document doc)
    		{System.Diagnostics.Debug.WriteLine("NewDocument");}
    
    		public void WindowActivate(Word.Document doc, Word.Window wn)
    		{System.Diagnostics.Debug.WriteLine("WindowActivate");}
    
    		public void WindowDeactivate(Word.Document doc, Word.Window wn)
    		{System.Diagnostics.Debug.WriteLine("WindowDeactivate");}
    
    		public void WindowSelectionChange(Word.Selection sel)
    		{System.Diagnostics.Debug.WriteLine("WindowSelectionChange");}
    
    		public void WindowBeforeRightClick(Word.Selection sel, ref bool Cancel)
    		{System.Diagnostics.Debug.WriteLine("WindowBeforeRightClick");}
    
    		public void WindowBeforeDoubleClick(Word.Selection sel, ref bool Cancel)
    		{System.Diagnostics.Debug.WriteLine("WindowBeforeDoubleClick");}
    
    		private UCOMIConnectionPoint m_oConnectionPoint;
    		private int m_Cookie;
    
    		public void SetupConnection(Word.Application app)
    		{
    			if (m_Cookie != 0) return;
    
    			// GUID of the DIID_ApplicationEvents dispinterface.
    			Guid guid = new Guid("{000209FE-0000-0000-C000-000000000046}");
    
    			// QI for IConnectionPointContainer.
    			UCOMIConnectionPointContainer oConnPointContainer = (UCOMIConnectionPointContainer)app;
    
    			// Find the connection point and then advise.
    			oConnPointContainer.FindConnectionPoint(ref guid, out m_oConnectionPoint);
    			m_oConnectionPoint.Advise(this, out m_Cookie);
    		}
    
    		public void RemoveConnection()
    		{
    			if (m_Cookie != 0)
    			{
    				m_oConnectionPoint.Unadvise(m_Cookie);
    				m_oConnectionPoint = null;
    				m_Cookie = 0;
    			}
    		}
    
    		public void Dispose(){RemoveConnection();}
    	}
    }
  5. Switch back to Form1, and then add a command button. Double-click the command button to make the code window for Form1.cs appear. Or, on theПредставление:выберите пунктКодto make the code window for Form1.cs appear. Add the following code to the button handler for theзатем –Событие::
    Word.Document doc;
    Object missing = System.Reflection.Missing.Value;
    
    // Create a new instance of Word and then set up the event handler.
    m_oApp = new Word.ApplicationClass();
    m_oAppEvents = new WordAppEvents9.WordAppEventHelper();
    m_oAppEvents.SetupConnection(m_oApp);
    
    // Make Word visible and then display a new document to test close.
    m_oApp.Visible = true;
    doc = m_oApp.Documents.Add(ref missing, ref missing, ref missing, ref missing);
    doc.UserControl = true;
    doc.Content.Text = "Try to close the document";
    
    // You only have to do this one time in this sample.
    button1.Enabled = false;
    
  6. Добавьте следующий код вФормы Form1class before the button handler:
    Word.Application m_oApp;
    WordAppEvents9.WordAppEventHelper m_oAppEvents;
    
  7. в менюПостроениевыберите пунктПостроение решенийto make the project. затем –Отладкаи выберите командуSTART ::для запуска приложения.

    When the application starts, you can click the command button and then Word appears. You cannot close the Word window until you close your application.

    You can use similar code to handle events for Excel.

Example 2: CancelItemSendСобытие:

  1. Start Visual Studio .NET 2003. Start a new project. SelectВ Visual C#as the project type. SelectWindows Applicationas the template. Имя проектаMyOutlookEventTestи выберите командуOk..

    По умолчанию будет создана форма Form1..
  2. в менюProjectвыберите пунктДобавить ссылку. In the dialog box, selectMicrosoft Outlook 10.0 библиотека объектовon the COM tab. ClickSelectto add a reference, and then clickOk.Чтобы закрыть диалоговое окно.

    A custom IA is generated for you automatically.
  3. в менюProjectвыберите пунктAdd a Class. SelectCode File, and then name the classOutlook10EventHelper.cs. затем –Ok.to generate the file.
  4. Add the following code to the code window for Outlook10EventHelper.cs:
    using System;
    using System.Runtime.InteropServices;
    //using Outlook; // The default name for a custom Word IA.
    // If you use Office XP and you have the PIAs
    // referenced in your project, you must change the previous line to read:
    using Outlook = Microsoft.Office.Interop.Outlook;
    using System.Windows.Forms;
    
    namespace OutlookAppEvents10
    {
    	[InterfaceType(ComInterfaceType.InterfaceIsIDispatch),
    	GuidAttribute("0006300E-0000-0000-C000-000000000046")]
    	public interface DOutlookApplicationEvents_10
    	{
    		void ItemSend(object Item, ref bool Cancel);
    		void NewMail();
    		void Reminder(object Item);
    		void OptionsPagesAdd(Outlook.PropertyPages Pages);
    		void Startup();
    		void Quit();
    		void AdvancedSearchComplete(Outlook.Search SearchObject);
    		void AdvancedSearchStopped(Outlook.Search SearchObject);
    		void MAPILogonComplete();
    	}
    
    	public class OutlookAppEventHelper : IDisposable
    	{
    		public OutlookAppEventHelper()
    		{
    			m_oConnectionPoint = null;
    			m_Cookie = 0;
    		}
    
    		private UCOMIConnectionPoint m_oConnectionPoint;
    		private int m_Cookie;
    
    		public void SetupConnection(Outlook.Application app)
    		{
    			if (m_Cookie != 0) return;
    			// GUID of the DIID_ApplicationEvents dispinterface.
    			Guid guid = new Guid("{0006300E-0000-0000-C000-000000000046}");
    
    			// QI for IConnectionPointContainer.
    			UCOMIConnectionPointContainer oConnectionPointContainer = (UCOMIConnectionPointContainer)app;
    
    			// Find the connection point and then advise.
    			oConnectionPointContainer.FindConnectionPoint(ref guid, out m_oConnectionPoint);
    			m_oConnectionPoint.Advise(this, out m_Cookie);
    		}
    
    		public void RemoveConnection()
    		{
    			if (m_Cookie != 0)
    			{
    				m_oConnectionPoint.Unadvise(m_Cookie);
    				m_oConnectionPoint = null;
    				m_Cookie = 0;
    			}
    		}
    
    		#region IDisposable Members
    
    		public void Dispose()
    		{
    			RemoveConnection();
    		}
    
    		#endregion
    
    		//#region DOutlookApplicationEvents_10 Members
    
    		[DispId(0x0000F002)]
    		public void ItemSend(object Item, ref bool Cancel)
    		{
    			DialogResult result;
    			result = MessageBox.Show("Do you want to cancel the ItemSend event?","",MessageBoxButtons.YesNo);
    			if(result == DialogResult.Yes)
    			{
    				System.Diagnostics.Debug.WriteLine("Cancelling Message");
    				Cancel = true;	
    			}
    			else
    			{
    				System.Diagnostics.Debug.WriteLine("Passing Message");
    				Cancel = false;
    			}
    		}
    
    		[DispId(0x0000F003)]
    		public void NewMail()
    		{
    			MessageBox.Show("NewMail");
    		}
    
    		[DispId(0x0000F004)]
    		public void Reminder(object Item)
    		{
    			MessageBox.Show("Reminder");
    		}
    
    		[DispId(0x0000F005)]
    		public void OptionsPagesAdd(Microsoft.Office.Interop.Outlook.PropertyPages Pages)
    		{
    			MessageBox.Show("OptionsPagesAdd");
    		}
    
    		[DispId(0x0000F006)]
    		public void Startup()
    		{
    			MessageBox.Show("Startup");
    		}
    
    		[DispId(0x0000F007)]
    		public void Quit()
    		{
    			MessageBox.Show("Quit");
    		}
    
    		[DispId(0x0000FA6A)]
    		public void AdvancedSearchComplete(Microsoft.Office.Interop.Outlook.Search SearchObject)
    		{
    			MessageBox.Show("AdvancedSearchComplete");
    		}
    
    		[DispId(0x0000FA6B)]
    		public void AdvancedSearchStopped(Microsoft.Office.Interop.Outlook.Search SearchObject)
    		{
    			MessageBox.Show("AdvancedSearchStopped");
    		}
    
    		[DispId(0x0000FA90)]
    		public void MAPILogonComplete()
    		{
    			MessageBox.Show("MAPILogonComplete");
    		}
    		//#endregion
    	}
    }
    Примечание.You need to place the [DispId(#)] attribute on the methods. Otherwise, the event cannot be cancelled.
  5. Switch back to Form1, and then add a command button. Double-click the command button to make the code window for Form1.cs appear. Or, on theПредставление:выберите пунктКодto make the code window for Form1.cs appear. Add the following code to the button handler for theзатем –Событие::
    Outlook.MailItem item;
    
    if (m_oApp == null)
    {
    	// Create a new instance of Outlook and then set up the event handler.
    	m_oApp = new Outlook.ApplicationClass();
    	m_oAppEvents = new OutlookAppEvents10.OutlookAppEventHelper();
    	m_oAppEvents.SetupConnection(m_oApp);
    } 
    
    // Make Outlook visible and then display a new message to test send.
    item = (Outlook.MailItem)m_oApp.CreateItem(Outlook.OlItemType.olMailItem);
    item.Subject = "The Subject!";
    item.Body = "Try sending the message.";
    item.Display(m_oApp);
  6. Добавьте следующий код вФормы Form1class before the button handler:
    Outlook.Application m_oApp;
    OutlookAppEvents10.OutlookAppEventHelper m_oAppEvents;
    
  7. в менюПостроениевыберите пунктПостроение решенийto make the project. затем –Отладкаи выберите командуSTART ::для запуска приложения.

    When the application starts, you can click the command button and then Outlook appears. A new email draft is automatically created. Input a recipient in theКому:line, and then clickОтправить. You will get a pop up dialog asking you if you want to cancel the ItemSend event. затем –ДА.to cancel it.

    You can use similar code to handle events for Excel.

Статус

Данное поведение является подтвержденной ошибкой продуктов Майкрософт, перечисленных в разделе «Информация в данной статье применима к»..

Ссылки

Для получения дополнительных сведений об автоматизации Office из Visual Studio .NET, щелкните следующий номер статьи базы знаний Майкрософт:
311452Разработка решений для Microsoft Office с помощью Visual Studio .NET
317109Приложения Office не завершить работу после автоматизации Visual Studio .NET клиента

Свойства

Код статьи: 830519 - Последний отзыв: 21 февраля 2014 г. - Revision: 2.0
Информация в данной статье относится к следующим продуктам.
  • Microsoft Excel 2002 Standard Edition
  • Microsoft Word 2002 Standard Edition
  • Microsoft Outlook 2002 Standard Edition
  • Microsoft Excel 2000 Standard Edition
  • Microsoft Word 2000 Standard Edition
  • Microsoft Outlook 2000 Standard Edition
  • Microsoft .NET Framework 1.1
  • Microsoft Visual Studio .NET 2003 Professional Edition
  • Microsoft Visual Studio .NET 2003 Enterprise Architect
  • Microsoft Visual Studio .NET 2003 Academic Edition
Ключевые слова: 
kbnosurvey kbarchive kbnofix kbbug kbmt KB830519 KbMtru
Переведено с помощью машинного перевода
ВНИМАНИЕ! Перевод данной статьи был выполнен не человеком, а с помощью программы машинного перевода, разработанной корпорацией Майкрософт. Корпорация Майкрософт предлагает вам статьи, переведенные как людьми, так и средствами машинного перевода, чтобы у вас была возможность ознакомиться со статьями базы знаний KB на родном языке. Однако машинный перевод не всегда идеален. Он может содержать смысловые, синтаксические и грамматические ошибки, подобно тому как иностранец делает ошибки, пытаясь говорить на вашем языке. Корпорация Майкрософт не несет ответственности за неточности, ошибки и возможный ущерб, причиненный в результате неправильного перевода или его использования. Корпорация Майкрософт также часто обновляет средства машинного перевода.
Эта статья на английском языке:830519

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com