Erro: O parâmetro Cancel para eventos do Office é ignorado no Visual Studio .NET 2003

Traduções deste artigo Traduções deste artigo
ID do artigo: 830519 - Exibir os produtos aos quais esse artigo se aplica.
Este artigo foi arquivado. É oferecido "como está" e não será mais atualizado.
Expandir tudo | Recolher tudo

Neste artigo

Sumário

Quando você trabalha com o Microsoft Visual Studio .NET 2003, você pode ter problemas quando você usa o parâmetro Cancelar em um evento de COM é gerado pelo Microsoft Word, pelo Microsoft Excel ou Microsoft Outlook. Embora o código recebe o evento COM e o código pode definir o parâmetro da mesma forma, COM o evento não for cancelado. Esse problema ocorre quando você usar interoperabilidade COM em um cliente gerenciado (como Microsoft Visual Basic .NET ou Microsoft Visual translation from VPE for Csharp) e também usar versão 1.1 do Microsoft .NET Framework.

Causa

O .NET Framework 1.1 introduziu alterações de segurança para aumentar a segurança de tipos ao interagir com um componente COM. O .NET Framework 1.1 aumenta a segurança de tipos, usando as informações empacotamento a biblioteca de tipos do componente. Ao automatizar o Word, Excel ou o Outlook de um cliente gerenciado, o assembly de interoperabilidade de COM (IA) ou o assembly de interoperabilidade primário (PIA) para o Microsoft Office XP usa as informações do tipo armazenados em bibliotecas de tipos as Microsoft Office para manipular eventos. Versões existentes do Word digite bibliotecas, bibliotecas de tipos Excel e a marca de bibliotecas de tipo de parâmetro Cancel Outlook como um parâmetro [in] . O parâmetro Cancel é marcado como um parâmetro [in] para que o common language runtime impõe essa restrição e impede que quaisquer alterações que são feitas pelo código gerenciado do que está sendo retornado ao chamador. Portanto, o evento não pode ser cancelado de um código gerenciado IA (ou PIA).

Resolução

Esse bug foi corrigido no Microsoft Office 2003.

Como Contornar

Se você usar uma versão anterior do Word, uma versão anterior do Excel ou uma versão anterior do Outlook, você deve estabelecer seu próprio coletor do ponto de conexão em seu código gerenciado. Um manipulador personalizado pode evitar a dependência de biblioteca de tipos e a proteção de tipo aplicada que normalmente se aplicam. Portanto, o argumento pode ser passado volta para o chamador.

Microsoft fornece exemplos de programação apenas para ilustração, sem garantia expressa ou implícita. Isso inclui, mas não está limitado a, garantias implícitas de comercialização ou adequação para uma finalidade específica. Este artigo presume que você está familiarizados com a linguagem de programação que está sendo demonstrada e com as ferramentas que são usadas para criar e depurar procedimentos. Engenheiros de suporte podem ajudar a explicar a funcionalidade de um determinado procedimento, mas eles não modificarão esses exemplos para fornecer funcionalidades adicionais ou construir procedimentos para atender às suas necessidades.

Gerar uma classe auxiliar

Para coletor diretamente eventos translation from VPE for Csharp Visual, você deve criar sua própria definição dispinterface e você também deve criar uma classe auxiliar para implementar seu código de evento. A definição de dispinterface deve coincidir com o identificador globalmente exclusivo (GUID) e os identificadores de expedição (DISPIDs) para o coletor de evento que é esperado pelo objeto Office que você deseja coletar eventos para. Para descobrir quais são esses valores, você pode usar um dos seguintes métodos:
  • Você pode usar o Visualizador do objeto OLE/COM que acompanha o Visual Studio .NET 2003 Professional Edition
  • Você pode usar o Platform SDK. Para obter informações adicionais sobre o Platform SDK, visite o seguinte site:

    http://www.microsoft.com/msdownload/platformsdk/sdkupdate
Depois de você souber o GUID e os DISPIDs, você pode criar sua própria definição de definição de dispinterface no Visual Basic .NET ou no Visual translation from VPE for Csharp.

Este artigo apresenta dois exemplos que mostram como usar conexão personalizada você aponta para solucionar esse problema. O primeiro exemplo demonstra como coletar os eventos do objeto Application para o Word 2000 e, em seguida, cancelar o evento DocumentBeforeClose para que o usuário não é possível fechar o documento. O segundo exemplo de Coletores de evento ItemSend para o Outlook 2002, para que você pode cancelar a operação de envio em seu aplicativo.

Exemplo 1: evento Cancelar DocumentBeforeClose

  1. Inicie o Visual Studio .NET 2003. Inicie um novo projeto. Selecione translation from VPE for Csharp Visual como o tipo de projeto. Selecione Windows Application como o modelo. Nomeie o projeto MyWordEventTest e em seguida, clique em OK .

    Por padrão, é criado o Form1.
  2. No menu Project , clique em Adicionar referência . Na caixa de diálogo, selecione Microsoft Word 9.0 Object Library na guia COM clique em Selecionar para adicionar uma referência e clique em OK para fechar a caixa de diálogo.

    Uma IA personalizada é gerada automaticamente para você.
  3. No menu Project , clique em Adicionar uma classe . Selecione Arquivo de código e, em seguida, nomeie a classe Word9EventHelper.cs . Clique em OK para gerar o arquivo.
  4. Adicione o seguinte código para a janela de código de sistema 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. Voltar para o Form1 e adicione um botão de comando. Clique duas vezes o botão de comando para fazer a janela de código para Form1.cs aparecer. Ou, no menu Exibir , clique em código para fazer a janela de código para Form1.cs aparecer. Adicione o seguinte código ao manipulador de botão para o 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. Adicione o seguinte código à classe Form1 antes do manipulador do botão:
    Word.Application m_oApp;
    WordAppEvents9.WordAppEventHelper m_oAppEvents;
    
  7. No menu Build , clique em Build Solution para tornar o projeto. Clique em Debug e, em seguida, clique em Iniciar para executar o aplicativo.

    Quando o aplicativo é iniciado, você pode clicar o botão de comando e o Word é exibido. Você não pode fechar a janela Word até você fechar o aplicativo.

    Você pode usar código semelhante para manipular eventos para o Excel.

Exemplo 2: Cancelar ItemSend evento

  1. Inicie o Visual Studio .NET 2003. Inicie um novo projeto. Selecione translation from VPE for Csharp Visual como o tipo de projeto. Selecione Windows Application como o modelo. Nomeie o projeto MyOutlookEventTest e em seguida, clique em OK .

    Por padrão, é criado o Form1.
  2. No menu Project , clique em Adicionar referência . Na caixa de diálogo, selecione a Biblioteca de objetos do Microsoft Outlook 10.0 no guia de COM, clique em Selecionar para adicionar uma referência e clique em OK para fechar a caixa de diálogo.

    Uma IA personalizada é gerada automaticamente para você.
  3. No menu Project , clique em Adicionar uma classe . Selecione Arquivo de código e, em seguida, nomeie a classe Outlook10EventHelper.cs . Clique em OK para gerar o arquivo.
  4. Adicionar o código a seguir à janela de código para o sistema 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. Caso contrário, o evento não pode ser cancelado.
  5. Voltar para o Form1 e adicione um botão de comando. Clique duas vezes o botão de comando para fazer a janela de código para Form1.cs aparecer. Ou, no menu Exibir , clique em código para fazer a janela de código para Form1.cs aparecer. Adicione o seguinte código ao manipulador de botão para o item 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. Adicione o seguinte código à classe Form1 antes do manipulador do botão:
    Outlook.Application m_oApp;
    OutlookAppEvents10.OutlookAppEventHelper m_oAppEvents;
    
  7. No menu Build , clique em Build Solution para tornar o projeto. Clique em Debug e, em seguida, clique em Iniciar para executar o aplicativo.

    Quando o aplicativo é iniciado, você pode clicar o botão de comando e o Outlook é exibido. Um rascunho de email novo é criado automaticamente. Entrada um destinatário na linha para e, em seguida, clique em Enviar . Você receberá uma pop-up diálogo perguntando se você deseja cancelar o evento ItemSend. Clique em Sim para cancelá-la.

    Você pode usar código semelhante para manipular eventos para o Excel.

Situação

A Microsoft confirmou que este é um problema nos produtos da Microsoft que estão listados na seção "Aplica-se a" deste artigo.

Referências

Para obter informações adicionais sobre como automatizar o Office do Visual Studio. NET, clique no número abaixo para ler o artigo na Base de dados de Conhecimento da Microsoft:
311452Microsoft Office de desenvolver soluções com o Visual Studio .NET
317109Aplicativo do Office não fecha após a automação de cliente do Visual Studio .NET

Propriedades

ID do artigo: 830519 - Última revisão: quinta-feira, 27 de fevereiro de 2014 - Revisão: 3.5
A informação contida neste artigo aplica-se a:
  • 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
  • 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
Palavras-chave: 
kbnosurvey kbarchive kbmt kbnofix kbbug KB830519 KbMtpt
Tradução automática
IMPORTANTE: Este artigo foi traduzido por um sistema de tradução automática (também designado por Machine Translation ou MT), não tendo sido portanto traduzido ou revisto por pessoas. A Microsoft possui artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais, com o objetivo de oferecer em português a totalidade dos artigos existentes na base de dados de suporte. No entanto, a tradução automática não é sempre perfeita, podendo conter erros de vocabulário, sintaxe ou gramática. A Microsoft não é responsável por incoerências, erros ou prejuízos ocorridos em decorrência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza atualizações freqüentes ao software de tradução automática (MT). Obrigado.
Clique aqui para ver a versão em Inglês deste artigo: 830519

Submeter comentários

 

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