Error: El parámetro Cancel para eventos de Office se omite en Visual Studio .NET 2003

Seleccione idioma Seleccione idioma
Id. de artículo: 830519 - Ver los productos a los que se aplica este artículo
Este artículo se ha archivado. Se ofrece "tal cual" y no se volverá a actualizar.
Expandir todo | Contraer todo

En esta página

Resumen

Cuando se trabaja con Visual Studio .NET 2003, puede experimentar problemas cuando utiliza el parámetro Cancel en un evento COM que se provoca por Microsoft Word, Microsoft Excel o Microsoft Outlook. Aunque el código recibe el evento de COM y el código puede establecer el parámetro en consecuencia, el COM no se cancela el evento. Este problema se produce cuando utiliza la interoperabilidad COM desde un cliente administrado (como Microsoft Visual C# o Microsoft Visual Basic. NET) y también utiliza la versión 1.1 de Microsoft .NET Framework.

Causa

Presenta los cambios de seguridad para mejorar la seguridad de tipos cuando se interactúa con un componente COM en .NET Framework 1.1. .NET Framework 1.1 mejora la seguridad de tipos al utilizando la información de cálculo de referencias de la biblioteca de tipo del componente. Cuando automatiza Word, Excel o Outlook desde un cliente administrado, el ensamblado de interoperabilidad de COM (IA) o el ensamblado de interoperabilidad primario (PIA) para Microsoft Office XP utiliza la información de tipo se almacena en las bibliotecas de tipo Microsoft Office para controlar los eventos. Las versiones existentes de la palabra escriba bibliotecas, las bibliotecas de tipos Excel y la marca de bibliotecas de tipo Outlook el parámetro Cancel como un parámetro [in] . El parámetro Cancel está marcado como un parámetro [in] para que common language runtime impone esta restricción y se impide que los cambios realizados por el código administrado desde que se devuelve al llamador. Por lo tanto, el evento no puede cancelarse de IA código administrado (o PIA).

Solución

Este error se corrigió en Microsoft Office 2003.

Solución

Si utiliza una versión anterior de Word, una versión anterior de Excel o una versión anterior de Outlook, debe establecer su propio receptor de punto de conexión en el código administrado. Un controlador personalizado puede evitar el tipo-dependencia de biblioteca y la protección de tipo exige que se aplican normalmente. Por lo tanto, se puede pasar el argumento al llamador.

Microsoft proporciona ejemplos de programación con fines ilustrativos únicamente, sin ninguna garantía tanto expresa como implícita. Esto incluye, entre otras, las garantías implícitas de comerciabilidad e idoneidad para un fin determinado. Este artículo se supone que está familiarizado con el lenguaje de programación que se muestra y con las herramientas que se utilizan para crear y depurar procedimientos. Los ingenieros de soporte técnico de Microsoft pueden explicarle la funcionalidad de un determinado procedimiento, pero no modificarán estos ejemplos para ofrecer mayor funcionalidad ni crearán procedimientos que cumplan sus requisitos específicos.

Generar una clase auxiliar

Para directamente de receptores de eventos de Visual C#, debe crear su propia definición de interfaz dispinterface y también debe crear una clase auxiliar para implementar el código de evento. La definición de interfaz dispinterface debe coincidir con el identificador único global (GUID) y los identificadores de envío (DISPID) para el receptor de eventos que se espera el objeto de Office que desea recibir eventos para. Para averiguar cuáles son estos valores, puede utilizar cualquiera de los métodos siguientes:
  • Puede utilizar el Visor de objetos OLE y COM que se incluye con Visual Studio .NET 2003 Professional
  • Puede utilizar el SDK. Para información adicional acerca de Platform SDK, visite el siguiente sitio Web de Microsoft:

    http://www.microsoft.com/msdownload/platformsdk/sdkupdate
Una vez conozca el GUID y los DISPID, puede crear su propia definición de la definición de interfaz dispinterface en Visual Basic .NET o Visual C#.

En este artículo se proporcionan dos ejemplos que muestran cómo utilizar conexión personalizada apunta a evitar este problema. El primer ejemplo muestra cómo recibir los eventos del objeto Application de Word 2000 y, a continuación, cancelar el evento DocumentBeforeClose para que el usuario no puede cerrar el documento. El segundo ejemplo receptores el evento ItemSend para Outlook 2002, por lo que puede cancelar la operación de envío en la aplicación.

Ejemplo 1: cancelar DocumentBeforeClose evento

  1. Inicie Visual Studio .NET 2003. Inicie un nuevo proyecto. SELECT C# como el tipo de proyecto. Seleccione Windows Application como la plantilla. Proyecto el nombre MyWordEventTest y, a continuación, haga clic en Aceptar .

    De forma predeterminada, se crea Form1.
  2. En el menú proyecto , haga clic en Agregar referencia . En el cuadro de diálogo, seleccione Biblioteca de objetos de Microsoft Word 9.0 en la ficha COM haga clic en Seleccionar para agregar una referencia y, a continuación, haga clic en Aceptar para cerrar el cuadro de diálogo.

    Un IA personalizado se genera automáticamente.
  3. En el menú proyecto , haga clic en Agregar una clase . Seleccione Archivo de código y, a continuación, nombrar la clase Word9EventHelper.cs . Haga clic en Aceptar para generar el archivo.
  4. Agregue el código siguiente a la ventana de código 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. Volver a Form1 y, a continuación, agregue un botón de comando. Haga doble clic en el botón de comando para que aparezca la ventana de código de Form1.cs. O bien, en el menú Ver , haga clic en código para que aparezca la ventana de código de Form1.cs. Agregar el código siguiente al controlador del botón para el documento de event:
    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. Agregue el código siguiente a la clase Form1 antes el controlador del botón:
    Word.Application m_oApp;
    WordAppEvents9.WordAppEventHelper m_oAppEvents;
    
  7. En el menú Generar , haga clic en Generar soluciones para hacer que el proyecto. Haga clic en Depurar y, a continuación, haga clic en Inicio para ejecutar la aplicación.

    Cuando se inicia la aplicación, hacer clic en el botón de comando y, a continuación, aparece Word. No puede cerrar la ventana de Word hasta que cierre la aplicación.

    Puede utilizar código similar para controlar eventos de Excel.

Ejemplo 2: Evento cancelar ItemSend

  1. Inicie Visual Studio .NET 2003. Inicie un nuevo proyecto. SELECT C# como el tipo de proyecto. Seleccione Windows Application como la plantilla. Proyecto el nombre MyOutlookEventTest y, a continuación, haga clic en Aceptar .

    De forma predeterminada, se crea Form1.
  2. En el menú proyecto , haga clic en Agregar referencia . En el cuadro de diálogo, seleccione Biblioteca de objetos de Microsoft Outlook 10.0 en la ficha COM haga clic en Seleccionar para agregar una referencia y, a continuación, haga clic en Aceptar para cerrar el cuadro de diálogo.

    Un IA personalizado se genera automáticamente.
  3. En el menú proyecto , haga clic en Agregar una clase . Seleccione Archivo de código y, a continuación, nombrar la clase Outlook10EventHelper.cs . Haga clic en Aceptar para generar el archivo.
  4. Agregue el código siguiente en la ventana de código para 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
    	}
    }
    Note You need to place the [DispId(#)] attribute on the methods. En caso contrario, el evento no puede cancelarse.
  5. Volver a Form1 y, a continuación, agregue un botón de comando. Haga doble clic en el botón de comando para que aparezca la ventana de código de Form1.cs. O bien, en el menú Ver , haga clic en código para que aparezca la ventana de código de Form1.cs. Agregue el código siguiente al controlador del botón para el artículo event:
    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. Agregue el código siguiente a la clase Form1 antes el controlador del botón:
    Outlook.Application m_oApp;
    OutlookAppEvents10.OutlookAppEventHelper m_oAppEvents;
    
  7. En el menú Generar , haga clic en Generar soluciones para hacer que el proyecto. Haga clic en Depurar y, a continuación, haga clic en Inicio para ejecutar la aplicación.

    Cuando se inicia la aplicación, hacer clic en el botón de comando y, a continuación, aparece Outlook. Se crea automáticamente un borrador de correo electrónico nuevo. Entrada de un destinatario en la línea para y, a continuación, haga clic en Enviar . Obtendrá un pop cuadro de diálogo preguntando si desea cancelar el evento ItemSend. Haga clic en para cancelarla.

    Puede utilizar código similar para controlar eventos de Excel.

Estado

Microsoft ha confirmado que se trata de un problema de los productos de Microsoft enumerados en la sección "La información de este artículo se refiere a".

Referencias

Para obtener información adicional acerca automatizar Office desde Visual Studio. NET, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:
311452Desarrollar Microsoft Office soluciones con Visual Studio .NET
317109Aplicación de Office no se cierra después de la automatización desde cliente de Visual Studio .NET

Propiedades

Id. de artículo: 830519 - Última revisión: jueves, 27 de febrero de 2014 - Versión: 3.5
La información de este artículo se refiere a:
  • Microsoft Excel 2002 Standard Edition
  • Microsoft Word 2002 Standard Edition
  • Microsoft Outlook 2002 Standard
  • Microsoft Excel 2000 Standard Edition
  • Microsoft Word 2000 Standard Edition
  • Microsoft Outlook 2000 Standard
  • Microsoft .NET Framework 1.1
  • Microsoft Visual Studio .NET 2003 Professional
  • Microsoft Visual Studio .NET 2003 Enterprise Architect
  • Microsoft Visual Studio .NET 2003 Academic Edition
Palabras clave: 
kbnosurvey kbarchive kbmt kbnofix kbbug KB830519 KbMtes
Traducción automática
IMPORTANTE: Este artículo ha sido traducido por un software de traducción automática de Microsoft (http://support.microsoft.com/gp/mtdetails) en lugar de un traductor humano. Microsoft le ofrece artículos traducidos por un traductor humano y artículos traducidos automáticamente para que tenga acceso en su propio idioma a todos los artículos de nuestra base de conocimientos (Knowledge Base). Sin embargo, los artículos traducidos automáticamente pueden contener errores en el vocabulario, la sintaxis o la gramática, como los que un extranjero podría cometer al hablar el idioma. Microsoft no se hace responsable de cualquier imprecisión, error o daño ocasionado por una mala traducción del contenido o como consecuencia de su utilización por nuestros clientes. Microsoft suele actualizar el software de traducción frecuentemente.
Haga clic aquí para ver el artículo original (en inglés): 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