Visual C# .NET을 사용하여 Office COM 추가 기능을 빌드하는 방법

요약

Microsoft Office XP, Microsoft Office 2003 및 Microsoft Office 2007은 Office 응용 프로그램을 향상시키고 제어하기 위한 애플리케이션 추가 기능을 빌드하기 위한 균일한 디자인 아키텍처를 지원합니다. 이러한 추가 기능을 COM(Microsoft Component Object Model) 추가 기능이라고 합니다. 이 단계별 문서에서는 Office COM 추가 기능에 대해 설명하고 Microsoft Visual C# .NET을 사용하여 Office COM 추가 기능을 빌드하는 방법을 설명합니다.

IDTExensibility2 인터페이스

COM 추가 기능은 Microsoft Msaddndr.dll(추가 기능 디자이너 형식 라이브러리)에 설명된 대로 IDTExensibility2 인터페이스를 구현하는 In-Process COM 서버 또는 ActiveX DLL(동적 링크 라이브러리)입니다. 모든 COM 추가 기능은 이 인터페이스에서 상속되며 5가지 메서드를 각각 구현해야 합니다.

Onconnection

COM 추가 기능이 연결되면 OnConnection 이벤트가 발생합니다. 추가 기능은 시작 시, 최종 사용자 또는 Automation을 통해 연결될 수 있습니다. OnConnection 이벤트가 성공적으로 반환되면 추가 기능이 로드되었다고 합니다. 오류 메시지가 반환되면 호스트 애플리케이션이 추가 기능에 대한 참조를 즉시 해제하고 개체가 제거됩니다.

OnConnection 이벤트는 다음 네 가지 매개 변수를 사용합니다.

  • 애플리케이션: 호스트 애플리케이션 개체에 대한 참조입니다.

  • ConnectMode: 추가 기능이 연결되는 방법을 지정하는 상수입니다. 추가 기능은 다음과 같은 방법으로 연결할 수 있습니다.

    • ext_cm_AfterStartup: COM 추가 기능 대화 상자에서 최종 사용자가 추가 기능을 시작합니다.
    • ext_cm_CommandLine: 추가 기능이 명령줄에서 연결됩니다. Office 애플리케이션용 COM 추가 기능 빌드에는 적용되지 않습니다.
    • ext_cm_External: 추가 기능은 Automation을 통해 외부 애플리케이션에 의해 연결됩니다. Office 애플리케이션용 COM 추가 기능 빌드에는 적용되지 않습니다.
    • ext_cm_Startup: 추가 기능은 애플리케이션 시작 시 호스트에 의해 시작됩니다. 이 동작은 레지스트리의 설정에 의해 제어됩니다.
  • AddInInst: 호스트 애플리케이션에 대한 COMAddIns 컬렉션에서 이 추가 기능을 참조하는 COMAddIn 개체에 대한 참조입니다.

  • 사용자 지정: 사용자 정의 데이터를 저장할 수 있는 Variant 형식 값의 배열입니다.

OnDisconnection

COM 추가 기능의 연결이 끊어지고 메모리에서 언로드되기 직전에 OnDisconnection 이벤트가 발생합니다. 추가 기능은 이 이벤트에서 리소스를 정리하고 호스트 애플리케이션에 대한 변경 내용을 복원해야 합니다.

OnDisconnection 이벤트는 다음 두 매개 변수를 사용합니다.

  • RemoveMode: 추가 기능의 연결이 끊어진 방법을 지정하는 상수입니다. 다음과 같은 방법으로 추가 기능의 연결을 끊을 수 있습니다.

    • ext_dm_HostShutdown: 호스트 애플리케이션이 닫히면 추가 기능의 연결이 끊어집니다.
    • ext_dm_UserClosed: 추가 기능은 최종 사용자 또는 Automation 컨트롤러에 의해 연결이 끊어집니다.
  • 사용자 지정: 사용자 정의 데이터를 저장할 수 있는 Variant 형식 값의 배열입니다.

OnAddInsUpdate

등록된 COM 추가 기능 집합이 변경되면 OnAddInsUpdate 이벤트가 발생합니다. 즉, COM 추가 기능이 설치되거나 호스트 애플리케이션에서 제거될 때마다 이 이벤트가 발생합니다.

OnStartupComplete 및 OnBeginShutdown

OnStartupComplete 메서드와 OnBeginShutdown 메서드는 호스트 애플리케이션이 떠났거나 애플리케이션이 메모리에서 자신을 로드하거나 언로드하는 데 사용 중이기 때문에 사용자 상호 작용을 피해야 하는 상태를 입력할 때 호출됩니다. OnStartupComplete 메서드는 시작 중에 추가 기능이 연결된 경우에만 호출되며, OnBeginShutdown 메서드는 호스트가 종료 중에 추가 기능의 연결을 끊는 경우에만 호출됩니다.

이러한 이벤트가 발생할 때 호스트 애플리케이션에 대한 사용자 인터페이스가 완전히 활성화되므로 OnConnection 이벤트 및 OnDisconnection 이벤트에서 사용할 수 없는 특정 작업을 수행하는 유일한 방법일 수 있습니다.

COM 추가 기능 등록

일반적인 COM 등록 외에도 COM 추가 기능은 실행되는 각 Office 애플리케이션에 등록해야 합니다. 특정 애플리케이션에 자신을 등록하려면 추가 기능에서 다음 위치에서 해당 ProgID를 키 이름으로 사용하여 하위 키를 만들어야 합니다.

HKEY_CURRENT_USER\Software\Microsoft\Office\OfficeApp\Addins\ProgID

추가 기능은 이 키 위치에 친숙한 표시 이름과 전체 설명 모두에 대한 값을 제공할 수 있습니다. 또한 추가 기능은 LoadBehavior라는 DWORD 값을 사용하여 원하는 부하 동작을 지정해야 합니다. 이 값은 호스트 애플리케이션에서 추가 기능을 로드하는 방법을 결정하며 다음 값의 조합으로 구성됩니다.

  • 0 = 연결 끊기 - 로드되지 않습니다.
  • 1 = 연결됨 - 로드됩니다.
  • 2 = Bootload - 애플리케이션 시작 시 로드.
  • 8 = DemandLoad - 사용자가 요청한 경우에만 로드합니다.
  • 16 = ConnectFirstTime - 다음 시작 시 한 번만 로드합니다.

지정된 일반적인 값은 0x03(연결된 | 부팅 로드).

IDTExtensibility2를 구현하는 추가 기능은 사용자 인터페이스를 지원하지 않는 작업에 추가 기능이 안전한지 여부를 나타내기 위해 CommandLineSafe 라는 DWORD 값을 지정해야 합니다. 0x00 값은 False를 나타내고 0x01 값은 True를 나타냅니다.

Visual C# .NET을 사용하여 COM 추가 기능을 빌드하는 방법

앞에서 설명한 것처럼 Office COM 추가 기능은 COM 런타임 계층을 통해 Office 애플리케이션에서 정품 인증하는 In-Process COM 서버입니다. 따라서 .NET에서 COM 추가 기능을 개발하려면 추가 기능 구성 요소를 .NET에서 구현한 다음 COM interop 계층을 통해 COM 클라이언트(즉, Office 애플리케이션)에 노출해야 합니다.

Visual C# .NET에서 COM 추가 기능을 만들려면 다음 단계를 수행합니다.

  1. Visual C# .NET에서 클래스 라이브러리 프로젝트를 만듭니다.
  2. IDTExtensibility2를 구현하는 형식 라이브러리에 대한 참조를 추가합니다. 이에 대한 기본 interop 어셈블리는 확장성이라는 이름으로 이미 사용할 수 있습니다.
  3. Microsoft Office 개체 라이브러리에 대한 참조를 추가합니다. 이에 대한 기본 interop 어셈블리는 Office라는 이름으로 이미 사용할 수 있습니다.
  4. IDTExtensibility2를 구현하는 클래스 라이브러리에 공용 클래스를 만듭니다.
  5. 클래스 라이브러리가 빌드된 후 COM interop용 라이브러리를 등록합니다. 이렇게 하려면 이 클래스 라이브러리에 대해 강력한 명명된 어셈블리를 생성한 다음 COM interop에 등록합니다. Regasm.exe 사용하여 COM interop용 .NET 구성 요소를 등록할 수 있습니다.
  6. Office 응용 프로그램에서 추가 기능을 인식하고 로드할 수 있도록 레지스트리 항목을 만듭니다.

이러한 단계를 모두 완료하도록 선택하거나 공유 추가 기능 형식의 .NET 프로젝트를 만들 수 있습니다. 그러면 .NET에서 COM 추가 기능을 만드는 데 도움이 되는 확장성 마법사가 시작됩니다.

확장성 마법사는 IDTExtensibility2 인터페이스를 구현하는 Connect 클래스와 함께 Visual C# .NET 클래스 라이브러리 프로젝트를 만듭니다. IDTExtensibility의 빈 멤버를 구현하는 기본 코드도 생성됩니다. 이 프로젝트에는 확장성 및 Office 어셈블리에 대한 참조가 있습니다. 프로젝트의 빌드 설정에 COM Interop에 대한 등록이 선택되어 있습니다. 어셈블리 키(.snk) 파일이 생성되고 Assemblyinfo.vb의 AssemblyKeyfile 특성에서 참조됩니다.

클래스 라이브러리 프로젝트와 함께 마법사는 다른 컴퓨터에 COM 추가 기능을 배포하는 데 사용할 수 있는 설치 프로젝트를 생성합니다. 원하는 경우 이 프로젝트를 제거할 수 있습니다.

단계별 예제

  1. Microsoft Visual Studio .NET의 파일 메뉴에서 새로 만들기를 클릭한 다음 프로젝트를 클릭합니다.

  2. 새 프로젝트 대화 상자에서 프로젝트 형식에서 다른 프로젝트를 확장하고 확장성 프로젝트를 선택한 다음 공유 추가 기능 템플릿을 선택합니다.

  3. 추가 기능의 이름으로 MyCOMAddin을 입력한 다음 확인을 클릭합니다.

  4. 확장성 마법사가 나타나면 다음 단계를 수행합니다.

    1. 1페이지에서 Visual C#을 사용하여 추가 기능 만들기를 선택하고 다음을 클릭합니다.

    2. 2페이지에서 다음 호스트 애플리케이션을 선택하고 다음을 클릭합니다.

      • Microsoft Word
      • Microsoft PowerPoint
      • Microsoft Outlook
      • Microsoft Excel
      • Microsoft Access
    3. 3페이지에서 추가 기능에 대한 이름과 설명을 입력하고 다음을 클릭합니다.

      참고 추가 기능의 이름과 설명은 Office 응용 프로그램의 COM 추가 기능 대화 상자에 표시됩니다.

    4. 4페이지에서 사용 가능한 모든 옵션을 선택하고 다음을 클릭합니다.

    5. 마침을 클릭합니다.

  5. 프로젝트 메뉴에서 참조 추가를 클릭합니다. 구성 요소 목록에서 System.Windows.Forms.DLL 클릭하고 선택을 클릭한 다음 확인을 클릭합니다.

  6. Connect 클래스의 네임스페이스 목록에 다음을 추가합니다.

    using System.Reflection;
    
  7. Connect 클래스에 다음 멤버를 추가합니다.

    private CommandBarButton MyButton;
    
  8. 다음과 같이 Connect 클래스에서 IDTExtensibility2의 멤버에 대한 코드를 구현합니다.

    public void OnConnection(object application, Extensibility.ext_ConnectMode connectMode, object addInInst, ref System.Array custom) {
       applicationObject = application;
       addInInstance = addInInst;
    
    if(connectMode != Extensibility.ext_ConnectMode.ext_cm_Startup)
       {
          OnStartupComplete(ref custom);
       }
    
    }
    
    public void OnDisconnection(Extensibility.ext_DisconnectMode disconnectMode, ref System.Array custom) {
       if(disconnectMode != Extensibility.ext_DisconnectMode.ext_dm_HostShutdown)
       {
          OnBeginShutdown(ref custom);
       }
       applicationObject = null;
    }
    
    public void OnAddInsUpdate(ref System.Array custom)
    {
    }
    
    public void OnStartupComplete(ref System.Array custom)
    {
       CommandBars oCommandBars;
       CommandBar oStandardBar;
    
    try
       {
       oCommandBars = (CommandBars)applicationObject.GetType().InvokeMember("CommandBars", BindingFlags.GetProperty , null, applicationObject ,null);
       }
       catch(Exception)
       {
       // Outlook has the CommandBars collection on the Explorer object.
       object oActiveExplorer;
       oActiveExplorer= applicationObject.GetType().InvokeMember("ActiveExplorer",BindingFlags.GetProperty,null,applicationObject,null);
       oCommandBars= (CommandBars)oActiveExplorer.GetType().InvokeMember("CommandBars",BindingFlags.GetProperty,null,oActiveExplorer,null);
       }
    
    // Set up a custom button on the "Standard" commandbar.
       try
       {
       oStandardBar = oCommandBars["Standard"];        
       }
       catch(Exception)
       {
       // Access names its main toolbar Database.
       oStandardBar = oCommandBars["Database"];      
       }
    
    // In case the button was not deleted, use the exiting one.
       try
       {
       MyButton = (CommandBarButton)oStandardBar.Controls["My Custom Button"];
       }
       catch(Exception)
       {
          object omissing = System.Reflection.Missing.Value ;
          MyButton = (CommandBarButton) oStandardBar.Controls.Add(1, omissing , omissing , omissing , omissing);
          MyButton.Caption = "My Custom Button";
          MyButton.Style = MsoButtonStyle.msoButtonCaption;
       }
    
    // The following items are optional, but recommended. 
       //The Tag property lets you quickly find the control 
       //and helps MSO keep track of it when more than
       //one application window is visible. The property is required
       //by some Office applications and should be provided.
       MyButton.Tag = "My Custom Button";
    
    // The OnAction property is optional but recommended. 
       //It should be set to the ProgID of the add-in, so that if
       //the add-in is not loaded when a user presses the button,
       //MSO loads the add-in automatically and then raises
       //the Click event for the add-in to handle. 
       MyButton.OnAction = "!<MyCOMAddin.Connect>";
    
    MyButton.Visible = true;
       MyButton.Click += new Microsoft.Office.Core._CommandBarButtonEvents_ClickEventHandler(this.MyButton_Click);
    
    object oName = applicationObject.GetType().InvokeMember("Name",BindingFlags.GetProperty,null,applicationObject,null);
    
    // Display a simple message to show which application you started in.
       System.Windows.Forms.MessageBox.Show("This Addin is loaded by " + oName.ToString()   , "MyCOMAddin");
       oStandardBar = null;
       oCommandBars = null;
    }
    
    public void OnBeginShutdown(ref System.Array custom)
    {
       object omissing = System.Reflection.Missing.Value ;
       System.Windows.Forms.MessageBox.Show("MyCOMAddin Add-in is unloading.");
       MyButton.Delete(omissing);
       MyButton = null;
    }
    
    private void MyButton_Click(CommandBarButton cmdBarbutton,ref bool cancel) {
       System.Windows.Forms.MessageBox.Show("MyButton was Clicked","MyCOMAddin"); }
    
  9. COM 추가 기능을 빌드하고 테스트합니다. 이렇게 하려면 다음과 같이 하십시오.

    1. 빌드 메뉴에서 솔루션 빌드를 클릭합니다. COM 추가 기능을 빌드하면 .NET 클래스가 COM interop에 등록됩니다.
    2. 추가 기능(예: Microsoft Word 또는 Microsoft Excel)에 대한 호스트 응용 프로그램으로 선택한 Office 응용 프로그램 중 하나를 시작합니다.
    3. 추가 기능이 시작되면 추가 기능의 OnStartupComplete 이벤트가 발생하며 메시지가 표시됩니다. 메시지 상자를 해제합니다. 추가 기능은 표준 도구 모음에 "내 사용자 지정 단추"라는 캡션이 있는 새 사용자 지정 단추를 추가했습니다.
    4. 내 사용자 지정 단추를 클릭합니다. 단추의 Click 이벤트는 추가 기능에서 처리되며 메시지 상자가 표시됩니다. 메시지 상자를 해제합니다.
    5. Office 응용 프로그램을 종료합니다.
    6. 애플리케이션을 종료하면 OnBeginShutDown 이벤트가 실행되고 메시지가 표시됩니다. 메시지 상자를 해제하여 데모를 종료합니다.