Erro: Parâmetro ' Cancelar ' para eventos do Office é ignorado no Visual Studio .NET 2003

Traduções de Artigos Traduções de Artigos
Artigo: 830519 - Ver produtos para os quais este artigo se aplica.
Este artigo foi arquivado. Este artigo é oferecido "tal como está" e deixará de ser actualizado.
Expandir tudo | Reduzir tudo

Nesta página

Sumário

Quando trabalha com o Microsoft Visual Studio .NET 2003, poderá detectar problemas quando utiliza o parâmetro Cancelar num evento COM que é aumentado pelo Microsoft Word, Microsoft Excel ou pelo Microsoft Outlook. Embora o código recebe eventos COM e o código pode definir o parâmetro da mesma forma, COM o evento não está cancelado. Este problema ocorre quando utiliza a interoperabilidade de um cliente gerido (tal como Microsoft Visual C# ou Microsoft Visual Basic. NET) e também utilizar a versão 1.1 do Microsoft .NET Framework.

Causa

O .NET Framework 1.1 tenha introduzido alterações de segurança para melhorar a segurança de tipo ao interagir com um componente do COM. O .NET Framework 1.1 melhora a segurança de tipo utilizando as informações de empacotamento de referências na biblioteca de tipos do componente. Quando automatizar o Word, Excel ou o Outlook a partir de um cliente gerido, a assemblagem de interoperabilidade COM (IA) ou a PIA (Primary Interop Assembly) do Microsoft Office XP utiliza as informações tipo armazenados na bibliotecas de tipos do Microsoft Office para processar eventos. As versões existentes do Word escreva bibliotecas, bibliotecas de Excel e a marca de bibliotecas de tipo de Outlook o parâmetro ' Cancelar ' como um parâmetro [in] . O parâmetro ' Cancelar ' está marcado como um parâmetro [no] para que o common language runtime impõe esta restrição e impede que quaisquer alterações efectuadas pelo código gerido de serem devolvidos ao autor da chamada. Por conseguinte, o evento não pode ser cancelado uma IA código gerido (ou PIA).

Resolução

Este erro foi corrigido no Microsoft Office 2003.

Como contornar

Se utilizar uma versão anterior do Word, uma versão anterior do Excel ou uma versão anterior do Outlook, tem de estabelecer o seus próprios receptor de ponto de ligação no código gerido. Rotina de tratamento personalizada pode evitar a dependência de biblioteca de tipos e a protecção de tipo de imposto que normalmente se aplicam. Por conseguinte, o argumento pode ser transferido para o autor da chamada.

A Microsoft fornece exemplos de programação apenas, para fins sem garantia expressa ou implícita. Isto inclui, mas não está limitado a, as garantias implícitas de comercialização ou adequação a um fim específico. Este artigo pressupõe que está familiarizado com a linguagem de programação apresentada e as ferramentas que são utilizadas para criar e depurar procedimentos. Os técnicos de suporte da Microsoft podem ajudar a explicar a funcionalidade de um determinado procedimento, mas não modificarão estes exemplos para proporcionarem funcionalidades adicionais nem criarão procedimentos adaptados às necessidades específicas do utilizador.

Gerar uma classe de programa auxiliar

Directamente receber eventos a partir do Visual C#, terá de criar sua própria definição dispinterface e também tem de criar uma classe de programa auxiliar a implementar o código de evento. A definição dispinterface tem de corresponder o identificador exclusivo global (GUID) e os identificadores de distribuição (DISPID) para o receptor de eventos que se espera pelo objecto Office que pretende receber eventos para. Para saber quais são estes valores, pode utilizar um dos seguintes métodos:
  • Pode utilizar o Visualizador de objectos OLE/COM que está incluída no Visual Studio .NET 2003 Professional Edition
  • Pode utilizar o Platform SDK. Para obter informações adicionais sobre o Platform SDK, visite o seguinte Web site da Microsoft:

    http://www.microsoft.com/msdownload/platformsdk/sdkupdate
Depois de saber o GUID e o DISPID, é possível criar a própria definição da definição dispinterface no Visual Basic .NET ou no Visual C#.

Este artigo fornece dois exemplos que mostram como utilizar a ligação personalizada aponta para contornar este problema. O primeiro exemplo demonstra como receber eventos de objecto de aplicação para o Word 2000 e, em seguida, cancelar o evento DocumentBeforeClose para que o utilizador não é possível fechar o documento. O segundo exemplo PIAs o evento ItemSend para o Outlook 2002, isso pode cancelar a operação de envio na aplicação.

Exemplo 1: Cancelar DocumentBeforeClose evento

  1. Inicie o Visual Studio .NET 2003. Inicie um novo projecto. Selecção Visual C# como tipo de projecto. Seleccione Windows Application como o modelo. Nome do projecto MyWordEventTest e, em seguida, clique em OK .

    Por predefinição, é criado o Form1.
  2. No menu projecto , clique em Adicionar referência . Na caixa de diálogo, seleccione Microsoft Word 9.0 Object Library no separador ' COM. clique em Seleccionar para adicionar uma referência e clique em OK para fechar a caixa de diálogo.

    Uma IA personalizada é gerada automaticamente para si.
  3. No menu projecto , clique em Adicionar uma classe . Seleccione Ficheiro de código e atribua o nome da classe Word9EventHelper.cs . Clique em OK para gerar o ficheiro.
  4. Adicione o seguinte código para a janela código 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 ao Form1 e, em seguida, adicione um botão de comando. Faça duplo clique o botão de comando para tornar a janela código Form1.cs aparecem. Ou, no menu Ver , clique em código para tornar a janela código Form1.cs aparecem. Adicione o seguinte código ao processador 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 processador de botão:
    Word.Application m_oApp;
    WordAppEvents9.WordAppEventHelper m_oAppEvents;
    
  7. No menu criar , clique em criar soluções para tornar o projecto. Clique em Debug e clique em Iniciar para executar a aplicação.

    Quando a aplicação é iniciada, pode clicar no botão de comando e, em seguida, o Word é apresentado. Não é possível fechar a janela do Word até fechar a aplicação.

    Pode utilizar código semelhante para processar eventos do Excel.

Exemplo 2: Cancelar ItemSend evento

  1. Inicie o Visual Studio .NET 2003. Inicie um novo projecto. Selecção Visual C# como tipo de projecto. Seleccione Windows Application como o modelo. Nome do projecto MyOutlookEventTest e, em seguida, clique em OK .

    Por predefinição, é criado o Form1.
  2. No menu projecto , clique em Adicionar referência . Na caixa de diálogo, seleccione Microsoft Outlook 10.0 Object Library no separador ' COM. clique em Seleccionar para adicionar uma referência e clique em OK para fechar a caixa de diálogo.

    Uma IA personalizada é gerada automaticamente para si.
  3. No menu projecto , clique em Adicionar uma classe . Seleccione Ficheiro de código e atribua o nome da classe Outlook10EventHelper.cs . Clique em OK para gerar o ficheiro.
  4. Adicione o seguinte código à 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 ao Form1 e, em seguida, adicione um botão de comando. Faça duplo clique o botão de comando para tornar a janela código Form1.cs aparecem. Ou, no menu Ver , clique em código para tornar a janela código Form1.cs aparecem. Adicione o seguinte código ao processador de botão para o item de 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 processador de botão:
    Outlook.Application m_oApp;
    OutlookAppEvents10.OutlookAppEventHelper m_oAppEvents;
    
  7. No menu criar , clique em criar soluções para tornar o projecto. Clique em Debug e clique em Iniciar para executar a aplicação.

    Quando a aplicação é iniciada, pode clicar no botão de comando e, em seguida, o Outlook é apresentada. É criado automaticamente um rascunho de mensagem de correio electrónico nova. Um destinatário na linha para entrada e clique em Enviar . Obterá um pop caixa de diálogo perguntando-lhe se deseja cancelar o evento ItemSend. Clique em Sim para cancelá-la.

    Pode utilizar código semelhante para processar eventos do Excel.

Ponto Da Situação

A Microsoft confirmou que este é um problema nos produtos da Microsoft listados na secçã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 de artigo que se segue para visualizar o artigo na base de dados de conhecimento da Microsoft:
311452Desenvolvimento do Microsoft Office soluções com o Visual Studio .NET
317109Aplicação do Office não é terminado após a automatização do Visual Studio .NET cliente

Propriedades

Artigo: 830519 - Última revisão: 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 revisto ou traduzido por humanos. A Microsoft tem artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais. O objectivo é simples: oferecer em Português a totalidade dos artigos existentes na base de dados do suporte. Sabemos no entanto que a tradução automática não é sempre perfeita. Esta pode conter erros de vocabulário, sintaxe ou gramática? erros semelhantes aos que um estrangeiro realiza ao falar em Português. A Microsoft não é responsável por incoerências, erros ou estragos realizados na sequência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza actualizações frequentes 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