Visual C를 사용하여 Microsoft Access를 자동화하는 방법 #

요약

이 문서에서는 Microsoft Visual C# 2005 또는 Microsoft Visual C# .NET을 사용하여 Microsoft Access를 자동화하는 방법을 보여 줍니다. 항목 및 샘플 코드에서는 다음을 수행하는 방법을 보여 줍니다.

  • Access에서 데이터베이스를 엽니다.
  • Access 보고서를 인쇄하거나 미리 봅니다.
  • Access 양식을 표시하고 편집합니다.
  • 암호로 보호된 데이터베이스를 열거나 사용자 수준 보안이 켜져 있는 경우 대화 상자를 사용하지 마세요.
  • 액세스 런타임을 자동화합니다.

Automation 및 ADO.NET

개발자는 두 가지 기술인 Automation 및 Microsoft ADO.NET 사용하여 Visual C# 2005 또는 Visual C# .NET의 Microsoft Access 데이터베이스를 사용할 수 있습니다.

access 데이터베이스의 테이블 및 쿼리와 같은 데이터 개체를 사용하려는 경우 ADO.NET 기본 설정 기술입니다. Access 보고서를 인쇄하거나 미리 보거나 Access 양식을 표시하거나 Access 매크로를 호출하는 기능과 같은 Microsoft Access 애플리케이션 관련 기능이 필요한 경우에만 Automation을 사용합니다.

이 문서에서는 Access를 자동화하는 방법을 설명합니다. 이 문서에서는 ADO.NET 대해 설명하지 않습니다. ADO.NET 대한 자세한 내용은 아래 문서 번호를 클릭하여 Microsoft 기술 자료에서 문서를 확인합니다.

  • 306636 ADO 2005 및 Visual C# 2005를 사용하거나 ADO.NET 및 Visual C# .NET을 사용하여 데이터베이스에 연결하고 명령을 실행하는 방법

  • 314145 Visual C# .NET을 사용하여 데이터베이스에서 DataSet 개체를 채우는 방법

  • 307587 Visual C# 2005 또는 Visual C# .NET을 사용하여 DataSet 개체에서 데이터베이스를 업데이트하는 방법

Automation은 COM(구성 요소 개체 모델) 기술입니다. 자동화를 사용하면 Visual C# .NET과 같은 언어로 작성된 애플리케이션이 프로그래밍 방식으로 다른 애플리케이션을 제어할 수 있습니다. Microsoft Office 애플리케이션을 자동화하는 경우 실제로 메모리에서 해당 애플리케이션의 인스턴스를 실행한 다음 애플리케이션의 개체 모델을 호출하여 해당 애플리케이션에서 다양한 작업을 수행합니다. Access 및 기타 Microsoft Office 응용 프로그램을 사용하면 사용자 인터페이스를 통해 수동으로 수행할 수 있는 거의 모든 작업을 Automation을 사용하여 프로그래밍 방식으로 수행할 수도 있습니다.

Access는 개체 모델을 통해 이 프로그래밍 기능을 노출합니다. 개체 모델은 Access의 논리적 구성 요소에 대응하는 클래스 및 메서드의 컬렉션입니다. Visual C# .NET에서 개체 모델에 액세스하려면 형식 라이브러리에 대한 프로젝트 참조를 설정할 수 있습니다.

일반적인 자동화 작업

Access에서 데이터베이스 열기

Microsoft Access를 자동화하는 경우 보고서 인쇄와 같은 유용한 작업을 수행하려면 먼저 데이터베이스를 열어야 합니다. 자동화하는 Access 인스턴스에서 데이터베이스를 열려면 Application 개체의 OpenCurrentDatabase 또는 OpenAccessProject 메서드를 사용합니다. Access에서 한 번에 하나의 데이터베이스만 열 수 있습니다. 다른 데이터베이스를 사용하려면 CloseCurrentDatabase 메서드를 사용하여 다른 데이터베이스를 열 수 있습니다.

System.Runtime.InteropServices.Marshal.BindToMoniker(<데이터베이스> 경로) 메서드를 사용하여 Access 인스턴스에서 데이터베이스를 열 수도 있습니다. 데이터베이스가 Access 인스턴스에서 이미 열려 있는 경우 BindToMoniker는 해당 인스턴스의 Application 개체를 반환합니다. 그렇지 않으면 BindToMoniker가 Access의 새 인스턴스를 시작하고 지정된 데이터베이스를 엽니다.

OpenCurrentDatabase는 자동화하는 Access 인스턴스를 지정하기 때문에 데이터베이스를 여는 데 선호되는 방법입니다. 데이터베이스를 여는 방법을 제어하는 인수를 제공할 수도 있습니다. 예를 들면 다음과 같습니다.

Access.Application oAccess = null;

// Start a new instance of Access for Automation:
oAccess = new Access.ApplicationClass();

// Open a database in exclusive mode:
oAccess.OpenCurrentDatabase(
   "c:\\mydb.mdb", //filepath
   true //Exclusive
   );

Access 보고서를 미리 보거나 인쇄하려면 DoCmd 개체의 OpenReport 메서드를 호출합니다. OpenReport를 호출할 때 전달하는 인수 중 하나는 보고서를 화면에서 미리 볼 수 있는지 또는 프린터로 전송되는지 여부를 결정합니다.

// Preview a report named Sales:
oAccess.DoCmd.OpenReport(
   "Sales", //ReportName
   Access.AcView.acViewPreview, //View
   System.Reflection.Missing.Value, //FilterName
   System.Reflection.Missing.Value //WhereCondition
   );

// Print a report named Sales:
oAccess.DoCmd.OpenReport(
   "Sales", //ReportName
   Access.AcView.acViewNormal, //View
   System.Reflection.Missing.Value, //FilterName
   System.Reflection.Missing.Value //WhereCondition
   );

View 인수는 보고서가 Access에 표시되는지 또는 프린터로 전송되는지 여부를 결정합니다. WHERE라는 단어가 없는 유효한 SQL WHERE 절을 사용하는 경우 WhereCondition 인수는 보고서의 레코드 집합을 제한할 수 있습니다. System.Reflection.Missing.Value를 사용하여 선택 사항인 개체 매개 변수를 건너뛸 수 있습니다.

보고서를 미리 보는 경우 Access가 화면에 표시되도록 Application 개체의 Visible 속성을 설정해야 합니다. 이러한 방식으로 사용자는 액세스 창에서 보고서를 볼 수 있습니다.

데이터베이스에서 보고서 또는 다른 개체를 인쇄하는 다른 방법이 있습니다. DoCmd 개체의 PrintOut 메서드를 사용합니다. 이 예제에서는 데이터베이스 창에서 Employees라는 보고서를 선택한 다음 PrintOut을 호출하여 선택한 개체를 인쇄합니다. PrintOut 메서드를 사용하면 Access의 인쇄 대화 상자에 해당하는 인수를 제공할 수 있습니다.

// Select the Employees report in the database window:
oAccess.DoCmd.SelectObject(
   Access.AcObjectType.acReport, //ObjectType
   "Employees", //ObjectName
   true //InDatabaseWindow
   );

// Print 2 copies of the selected object:
oAccess.DoCmd.PrintOut(
   Access.AcPrintRange.acPrintAll, //PrintRange
   System.Reflection.Missing.Value, //PageFrom
   System.Reflection.Missing.Value, //PageTo
   Access.AcPrintQuality.acHigh, //PrintQuality
   2, //Copies
   false //CollateCopies
   );

또는 경우에 따라 OpenReport 및 PrintOut 메서드를 모두 사용하여 보고서를 인쇄하는 것이 좋습니다. Employees 보고서의 복사본을 여러 장 인쇄하려고 하지만 특정 직원에 대해서만 인쇄하려는 경우를 가정해 보겠습니다. 이 예제에서는 먼저 OpenReport를 사용하여 WhereCondition 인수를 사용하여 레코드를 특정 직원으로 제한하는 미리 보기 모드에서 Employees 보고서를 엽니다. 그런 다음 PrintOut을 사용하여 활성 개체의 여러 복사본을 인쇄합니다.

// Open the report in preview mode using a WhereCondition:
oAccess.DoCmd.OpenReport(
   "Employees", //ReportName
   Access.AcView.acViewPreview, //View
   System.Reflection.Missing.Value, //FilterName
   "[EmployeeID]=1" //WhereCondition
   );

// Print 2 copies of the active object: 
oAccess.DoCmd.PrintOut(
   Access.AcPrintRange.acPrintAll, //PrintRange
   System.Reflection.Missing.Value, //PageFrom
   System.Reflection.Missing.Value, //PageTo
   Access.AcPrintQuality.acHigh, //PrintQuality
   2, //Copies
   false //CollateCopies
   );

// Close the report preview window: 
oAccess.DoCmd.Close(
   Access.AcObjectType.acReport, //ObjectType
   "Employees", //ObjectName
   Access.AcCloseSave.acSaveNo //Save
   );

Access 2002에는 Printer 개체가 도입되었습니다. 이 개체를 사용하여 이전 버전의 Access보다 Access 프린터 설정을 더 쉽게 사용자 지정할 수 있습니다. Access에서 Printer 개체를 사용하여 보고서를 인쇄하는 예제를 보려면 아래 문서 번호를 클릭하여 Microsoft 기술 자료의 문서를 봅니다.

284286 Application.Printer 개체의 변경 내용을 다시 설정하는 방법

액세스 양식 표시 및 편집

Visual C# .NET에는 매우 강력한 양식 기능이 있습니다. 그러나 사용자가 이전에 Access에서 개발한 양식을 보도록 하려는 경우가 있을 수 있습니다. 또는 Access 데이터베이스에 쿼리 또는 보고서에 대한 조건을 제공하는 양식이 있을 수 있으며 보고서를 미리 보거나 인쇄하려면 먼저 해당 양식을 열어야 합니다. Access 양식을 열고 표시하려면 DoCmd 개체의 OpenForm 메서드를 호출합니다.

// Show a form named Employees:
oAccess.DoCmd.OpenForm(
   "Employees", //FormName
   Access.AcFormView.acNormal, //View
   System.Reflection.Missing.Value, //FilterName
   System.Reflection.Missing.Value, //WhereCondition
   Access.AcFormOpenDataMode.acFormPropertySettings, //DataMode
   Access.AcWindowMode.acWindowNormal, //WindowMode
   System.Reflection.Missing.Value //OpenArgs
   );

이제 양식의 컨트롤을 편집할 수 있습니다.

액세스 보안 대화 상자

Access를 자동화할 때 데이터베이스를 열려고 할 때 사용자 이름이나 암호 또는 둘 다를 입력하라는 메시지가 표시될 수 있습니다. 사용자가 잘못된 정보를 입력하면 코드에서 오류가 발생합니다. 이러한 대화 상자를 피하고 자동화 코드가 중단 없이 실행되도록 프로그래밍 방식으로 사용자 이름과 암호를 제공하려는 경우가 있을 수 있습니다.

Microsoft Access에는 암호로 보호된 데이터베이스와 작업 그룹 파일(System.mdw)을 통한 사용자 수준 보안이라는 두 가지 보안 유형이 있습니다. 암호로 보호된 데이터베이스를 열려고 하면 데이터베이스 암호를 묻는 대화 상자가 표시됩니다. 사용자 수준 보안은 암호로 보호된 데이터베이스와 다릅니다. 사용자 수준 보안이 활성화되면 Access에서 사용자가 데이터베이스를 열기 전에 사용자 이름과 암호를 둘 다 묻는 로그온 대화 상자가 표시됩니다.

데이터베이스 암호 방지 대화 상자

암호로 보호된 데이터베이스를 여는 경우 OpenCurrentDatabase 메서드에 암호를 제공하여 대화 상자를 피할 수 있습니다.

// Open a password-protected database in shared mode:
// Note: The bstrPassword argument is case-sensitive
oAccess.OpenCurrentDatabase(
   "c:\\mydb.mdb", //filepath
   false, //Exclusive
   "MyPassword" //bstrPassword
   );

다음은 oAccess가 이전에 열려 있는 데이터베이스가 없는 Access 인스턴스로 설정된 예제입니다. 이 코드는 대화 상자를 방지하기 위해 데이터베이스에 암호를 제공합니다.

string sDBPassword = "MyPassword"; //database password
DAO._DBEngine oDBEngine = oAccess.DBEngine;
DAO.Database oDB = oDBEngine.OpenDatabase("c:\\mydb.mdb",
   false, false, ";PWD=" + sDBPassword);
oAccess.OpenCurrentDatabase("c:\\mydb.mdb", false);
oDB.Close();
System.Runtime.InteropServices.Marshal.ReleaseComObject(oDB);
oDB = null;
System.Runtime.InteropServices.Marshal.ReleaseComObject(oDBEngine);
oDBEngine = null;

oDB.Close는 실제로 Access에서 데이터베이스를 닫지 않습니다. DBEngine 개체를 통해 만들어진 데이터베이스에 대한 DAO 연결만 닫습니다. OpenCurrentDatabase 메서드를 사용한 후에는 DAO 연결이 더 이상 필요하지 않습니다. oDB 및 oDBEngine 개체를 해제하는 코드를 확인합니다. 코드가 완료된 후 Access가 올바르게 종료되도록 이러한 개체를 사용해야 합니다.

액세스 보안 로그온 방지 대화 상자

Access에서 사용자 수준 보안이 설정되어 있으면 사용자에게 로그온 대화 상자가 표시되어 사용자 이름과 암호를 모두 묻는 메시지가 표시됩니다. Access 개체 모델을 사용하여 사용자 이름 및 암호를 지정할 수 없습니다. 따라서 Access를 자동화할 때 로그온 대화 상자를 사용하지 않으려면 먼저 Msaccess.exe 파일을 시작하고 /user 및 /pwd 명령줄 스위치를 제공하여 사용자 이름과 암호를 지정해야 합니다. 그런 다음 GetActiveObject 또는 BindToMoniker를 사용하여 실행 중인 Access 인스턴스의 애플리케이션 개체를 검색하여 Automation을 진행할 수 있습니다.

액세스 런타임 자동화

Microsoft Office Developer Edition에는 MOD(Microsoft Office Developer Tools)가 포함되어 있습니다. MOD를 사용하여 Access 개발자는 Access의 소매 버전이 없는 사용자에게 Access 애플리케이션을 만들고 배포할 수 있습니다. 사용자가 소매 버전의 Access가 없는 컴퓨터에 Access 애플리케이션을 설치하면 런타임 버전의 Access가 설치됩니다. Access Runtime이 설치되고 소매 버전처럼 등록됩니다. 실행 파일을 Msaccess.exe 호출합니다. Access Runtime을 사용하면 클라이언트 컴퓨터에서 Access 애플리케이션을 실행할 수 있지만 Access 런타임에서는 사용자가 새 애플리케이션을 개발하거나 기존 애플리케이션의 디자인을 수정할 수 없습니다.

Access Runtime은 데이터베이스로 시작해야 합니다. 이 요구 사항 때문에 Access Runtime을 자동화하려면 Msaccess.exe 시작하고 열 데이터베이스를 지정해야 합니다. GetActiveObject 또는 BindToMoniker를 사용하여 애플리케이션 개체를 검색한 후 Access Runtime을 자동화할 수 있습니다. Access Runtime을 자동화하려고 할 때 이 방법을 사용하지 않으면 인스턴스를 인스턴스화하려고 할 때 다음과 같은 오류 메시지가 표시됩니다.

System.Runtime.InteropServices.COMException(0x80080005) 서버 실행이 실패했습니다.

전체 샘플 Visual C# 2005 또는 Visual C# .NET 프로젝트 만들기

다음 단계별 샘플을 사용하려면 Northwind 샘플 데이터베이스가 설치되어 있는지 확인합니다. 기본적으로 Microsoft Access 2000은 다음 경로에 샘플 데이터베이스를 설치합니다.

C:\Program Files\Microsoft Office\Office\Samples

Microsoft Access 2002는 다음 경로를 사용합니다.

C:\Program Files\Microsoft Office\Office10\Samples

Microsoft Office Access 2003에서는 다음 경로를 사용합니다.

C:\Program Files\Microsoft\Office\Office11\Samples

Northwind 샘플 데이터베이스가 Access 2002 또는 Access 2003에 설치되어 있는지 확인하려면 도움말 메뉴에서 샘플 데이터베이스를 클릭한 다음 Northwind 샘플 데이터베이스를 클릭합니다.

  1. 현재 실행 중인 Access 인스턴스를 모두 닫습니다.

  2. Microsoft Visual Studio .NET을 시작합니다.

  3. [파일] 메뉴에서 [새로 만들기]를 클릭한 다음 [프로젝트]를 클릭합니다. Visual C# 프로젝트 형식에서 Windows 애플리케이션을 선택합니다. 기본적으로 Form1이 만들어집니다.

    참고 Visual Studio 2005에서 코드를 변경해야 합니다. 기본적으로 Visual C#은 Windows Forms 프로젝트를 만들 때 프로젝트에 하나의 양식을 추가합니다. 폼의 이름은 Form1입니다. 폼을 나타내는 두 파일의 이름은 Form1.cs 및 Form1.designer.cs입니다. Form1.cs에서 코드를 작성합니다. Form1.designer.cs 파일은 Windows Forms 디자이너가 도구 상자에서 컨트롤을 끌어서 놓아 수행한 모든 작업을 구현하는 코드를 작성하는 위치입니다.

    Visual C# 2005의 Windows Forms Designer에 대한 자세한 내용은 다음 MSDN(Microsoft Developer Network) 웹 사이트를 참조하세요.https://msdn.microsoft.com/en-us/library/ms173077.aspx

  4. Microsoft Access 개체 라이브러리에 대한 참조를 추가합니다. 이렇게 하려면 다음과 같이 하십시오.

    1. 프로젝트 메뉴에서 참조 추가를 클릭합니다.
    2. COM 탭에서 Microsoft Access 개체 라이브러리를 찾은 다음 선택을 클릭합니다.

    참고 Visual Studio 2005에서. 선택을 클릭할 필요가 없습니다.

    참고 Microsoft Office 2003에는 IA(기본 Interop 어셈블리)가 포함되어 있습니다. Microsoft Office XP에는 PIA가 포함되지 않지만 다운로드할 수 있습니다.

  5. 참조 추가 대화 상자에서 [확인]을 클릭하여 선택 내용을 적용합니다.

    참고 Access 10.0 개체 라이브러리를 참조하는 경우 참조를 추가하려고 할 때 오류가 발생합니다.

  6. 보기 메뉴에서 도구 상자를 클릭하여 도구 상자를 표시합니다.

  7. 5개의 라디오 단추 컨트롤과 1개의 단추 컨트롤을 Form1에 추가합니다.

  8. 라디오 단추 컨트롤을 모두 선택한 다음 Size 속성을 150,24로 설정합니다.

  9. 폼 로드 이벤트 및 단추 컨트롤의 Click 이벤트에 대한 이벤트 처리기를 추가합니다.

    1. Form1.cs의 디자인 보기에서 Form1을 두 번 클릭합니다.

      Form의 Load 이벤트에 대한 처리기가 만들어지고 Form1.cs에 표시됩니다.

    2. 보기 메뉴에서 디자이너를 클릭하여 디자인 보기로 전환합니다.

    3. Button1을 두 번 클릭합니다.

      단추의 Click 이벤트에 대한 처리기가 만들어지고 Form1.cs에 표시됩니다.

  10. Form1.cs에서 다음 코드를 바꿉니다.

    private void Form1_Load(object sender, System.EventArgs e)
    {
    
    }
    
    private void button1_Click(object sender, System.EventArgs e)
    {
    
    } 
    

    with:

          private string msAction = null;
          // Commonly-used variable for optional arguments:
          private object moMissing = System.Reflection.Missing.Value;
    
    private void Form1_Load(object sender, System.EventArgs e)
          {
             radioButton1.Text = "Print report";
             radioButton2.Text = "Preview report";
             radioButton3.Text = "Show form";
             radioButton4.Text = "Print report (Security)";
             radioButton5.Text = "Preview report (Runtime)";
             button1.Text = "Go!";
             radioButton1.Click += new EventHandler(RadioButtons_Click);
             radioButton2.Click += new EventHandler(RadioButtons_Click);
             radioButton3.Click += new EventHandler(RadioButtons_Click);
             radioButton4.Click += new EventHandler(RadioButtons_Click);
             radioButton5.Click += new EventHandler(RadioButtons_Click);
          }
    
    private void RadioButtons_Click(object sender, System.EventArgs e)
          {
             RadioButton radioBtn = (RadioButton) sender;
             msAction = radioBtn.Text;
          }
    
    private void button1_Click(object sender, System.EventArgs e)
          {
             // Calls the associated procedure to automate Access, based
             // on the selected radio button on the form.
             switch(msAction)
             {
                case "Print report": Print_Report();
                   break;
                case "Preview report": Preview_Report();
                   break;
                case "Show form": Show_Form();
                   break;
                case "Print report (Security)": Print_Report_Security();
                   break;
                case "Preview report (Runtime)": Preview_Report_Runtime();
                   break;
             }
          }
    
    private void NAR(object o)
          {
             // Releases the Automation object.
             try // use try..catch in case o is not set
             {
                Marshal.ReleaseComObject(o);
             }
             catch{}
          }
    
    private Access.Application ShellGetDB(string sDBPath, string sCmdLine,
             ProcessWindowStyle enuWindowStyle, int iSleepTime)
          {
             //Launches a new instance of Access with a database (sDBPath)
             //using System.Diagnostics.Process.Start. Then, returns the
             //Application object via calling: BindToMoniker(sDBPath). Returns
             //the Application object of the new instance of Access, assuming that
             //sDBPath is not already opened in another instance of Access. To
             //ensure the Application object of the new instance is returned, make
             //sure sDBPath is not already opened in another instance of Access
             //before calling this function.
             // 
             //Example:
             //Access.Application oAccess = null;
             //oAccess = ShellGetDB("c:\\mydb.mdb", null,
             //  ProcessWindowStyle.Minimized, 1000);
    
    Access.Application oAccess = null;
             string sAccPath = null; //path to msaccess.exe
             Process p = null;
    
    // Enable exception handler:
             try
             {
                // Obtain the path to msaccess.exe:
                sAccPath = GetOfficeAppPath("Access.Application", "msaccess.exe");
                if (sAccPath == null)
    
    {
                   MessageBox.Show("Can't determine path to msaccess.exe");
                   return null;
                }
    
    // Make sure specified database (sDBPath) exists:
                if(!System.IO.File.Exists(sDBPath))
                {
                   MessageBox.Show("Can't find the file '" + sDBPath + "'");
                   return null;
                }
    
    // Start a new instance of Access passing sDBPath and sCmdLine:
                if(sCmdLine == null)
                   sCmdLine = @"""" + sDBPath + @"""";
                else
                   sCmdLine = @"""" + sDBPath + @"""" + " " + sCmdLine;
                ProcessStartInfo startInfo = new ProcessStartInfo();
                startInfo.FileName = sAccPath;
                startInfo.Arguments = sCmdLine;
                startInfo.WindowStyle = enuWindowStyle;
                p = Process.Start(startInfo);
                p.WaitForInputIdle(60000); //max 1 minute wait for idle input state
    
    // Move focus back to this form. This ensures that Access
                // registers itself in the ROT:
                this.Activate();
    
    // Pause before trying to get Application object:
                System.Threading.Thread.Sleep(iSleepTime);
    
    // Obtain Application object of the instance of Access
                // that has the database open:
                oAccess = (Access.Application) Marshal.BindToMoniker(sDBPath);
                return oAccess;
             }
             catch(Exception e)
             {
                MessageBox.Show(e.Message);
                // Try to quit Access due to an unexpected error:
                try // use try..catch in case oAccess is not set
                {
                   oAccess.Quit(Access.AcQuitOption.acQuitSaveNone);
                }
                catch{}
                NAR(oAccess);
                oAccess = null;
                return null;
             }
          }
    
    private Access.Application ShellGetApp(string sCmdLine,
             ProcessWindowStyle enuWindowStyle)
          {
             //Launches a new instance of Access using System.Diagnostics.
             //Process.Start then returns the Application object via calling:
             //GetActiveObject("Access.Application"). If an instance of
             //Access is already running before calling this function,
             //the function may return the Application object of a
             //previously running instance of Access. If this is not
             //desired, then make sure Access is not running before
             //calling this function, or use the ShellGetDB()
             //function instead. Approach based on Q316125.
             // 
             //Examples:
             //Access.Application oAccess = null;
             //oAccess = ShellGetApp("/nostartup",
             //  ProcessWindowStyle.Minimized);
             // 
             //-or-
             // 
             //Access.Application oAccess = null;
             //string sUser = "Admin";
             //string sPwd = "mypassword";
             //oAccess = ShellGetApp("/nostartup /user " + sUser + "/pwd " + sPwd,
             //  ProcessWindowStyle.Minimized);
    
    Access.Application oAccess = null;
             string sAccPath = null; //path to msaccess.exe
             Process p = null;
             int iMaxTries = 20; //max GetActiveObject attempts before failing
             int iTries = 0; //GetActiveObject attempts made
    
    // Enable exception handler:
             try
             {
                // Obtain the path to msaccess.exe:
                sAccPath = GetOfficeAppPath("Access.Application", "msaccess.exe");
                if(sAccPath == null)
                {
                   MessageBox.Show("Can't determine path to msaccess.exe");
                   return null;
                }
    
    // Start a new instance of Access passing sCmdLine:
                ProcessStartInfo startInfo = new ProcessStartInfo();
                startInfo.FileName = sAccPath;
                startInfo.Arguments = sCmdLine;
                startInfo.WindowStyle = enuWindowStyle;
                p = Process.Start(startInfo);
                p.WaitForInputIdle(60000); //max 1 minute wait for idle input state
    
    // Move focus back to this form. This ensures that Access
                // registers itself in the ROT:
                this.Activate();
    
    tryGetActiveObject:
                // Enable exception handler:
                try
                {   
                   // Attempt to use GetActiveObject to reference a running
                   // instance of Access:
                   oAccess = (Access.Application)
                      Marshal.GetActiveObject("Access.Application");
                }
                catch
                {
                   //GetActiveObject may have failed because enough time has not
                   //elapsed to find the running Office application. Wait 1/2
                   //second and retry the GetActiveObject. If you try iMaxTries
                   //times and GetActiveObject still fails, assume some other
                   //reason for GetActiveObject failing and exit the procedure.
                   iTries++;
                   if(iTries < iMaxTries)
                   {
                      System.Threading.Thread.Sleep(500); //wait 1/2 second
                      this.Activate();
                      goto tryGetActiveObject;
                   }
                   MessageBox.Show("Unable to GetActiveObject after " +
                      iTries + " tries.");
                   return null;
                }
    
    // Return the Access Application object:
                return oAccess;
             }
             catch(Exception e)
             {
                MessageBox.Show(e.Message);
                // Try to quit Access due to an unexpected error:
                try // use try..catch in case oAccess is not set
                {
                   oAccess.Quit(Access.AcQuitOption.acQuitSaveNone);
                }
                catch{}
                NAR(oAccess);
                oAccess = null;
                return null;
             }
          }
    
    private string GetOfficeAppPath(string sProgId, string sEXE)
          {
             //Returns path of the Office application. e.g.
             //GetOfficeAppPath("Access.Application", "msaccess.exe") returns
             //full path to Microsoft Access. Approach based on Q240794.
             //Returns null if path not found in registry.
    
    // Enable exception handler:
             try
             {
                Microsoft.Win32.RegistryKey oReg = 
                   Microsoft.Win32.Registry.LocalMachine;
                Microsoft.Win32.RegistryKey oKey = null;
                string sCLSID = null;
                string sPath = null;
                int iPos = 0;
    
    // First, get the clsid from the progid from the registry key
                // HKEY_LOCAL_MACHINE\Software\Classes\<PROGID>\CLSID:
                oKey = oReg.OpenSubKey(@"Software\Classes\" + sProgId + @"\CLSID");
                sCLSID = oKey.GetValue("").ToString();
                oKey.Close();
    
    // Now that we have the CLSID, locate the server path at
                // HKEY_LOCAL_MACHINE\Software\Classes\CLSID\ 
                // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx}\LocalServer32:
                oKey = oReg.OpenSubKey(@"Software\Classes\CLSID\" + sCLSID +
                   @"\LocalServer32");
                sPath = oKey.GetValue("").ToString();
                oKey.Close();
    
    // Remove any characters beyond the exe name:
                iPos = sPath.ToUpper().IndexOf(sEXE.ToUpper()); // 0-based position
                sPath = sPath.Substring(0, iPos + sEXE.Length);
                return sPath.Trim();
             }
             catch
             {
                return null;
             }
          }
    
    private void Print_Report()
          {
             // Prints the "Summary of Sales by Year" report in Northwind.mdb.
    
    Access.Application oAccess = null;
             string sDBPath = null; //path to Northwind.mdb
             string sReport = null; //name of report to print
    
    // Enable exception handler:
             try
             {
                sReport = "Summary of Sales by Year";
    
    // Start a new instance of Access for Automation:
                oAccess = new Access.ApplicationClass();
    
    // Determine the path to Northwind.mdb:
                sDBPath = oAccess.SysCmd(Access.AcSysCmdAction.acSysCmdAccessDir,
                   moMissing, moMissing).ToString();
                sDBPath = sDBPath + @"Samples\Northwind.mdb";
    
    // Open Northwind.mdb in shared mode:
                oAccess.OpenCurrentDatabase(sDBPath, false, "");
                // If using Access 10.0 object library, use this instead:
                //oAccess.OpenCurrentDatabase(sDBPath, false, null);
    
    // Select the report name in the database window and give focus
                // to the database window:
                oAccess.DoCmd.SelectObject(Access.AcObjectType.acReport, sReport, true);
    
    // Print the report:
                oAccess.DoCmd.OpenReport(sReport,
                   Access.AcView.acViewNormal, moMissing, moMissing, 
                   Access.AcWindowMode.acWindowNormal, moMissing);
                // If using Access 10.0 object library, use this instead:
                //oAccess.DoCmd.OpenReport(sReport,
                //  Access.AcView.acViewNormal, moMissing, moMissing,
                //  Access.AcWindowMode.acWindowNormal, moMissing);
             }
             catch(Exception e)
             {
                MessageBox.Show(e.Message);
             }
             finally
             {
                // Release any Access objects and quit Access:
                try // use try..catch in case oAccess is not set
                {
                   oAccess.Quit(Access.AcQuitOption.acQuitSaveNone);
                }
                catch{}
                NAR(oAccess);
                oAccess = null;
             }
          }
    
    private void Preview_Report()
          {
             // Previews the "Summary of Sales by Year" report in Northwind.mdb.
    
    Access.Application oAccess = null;
             Access.Form oForm = null;
             string sDBPath = null; //path to Northwind.mdb
             string sReport = null; //name of report to preview
    
    // Enable exception handler:
             try
             {
                sReport = "Summary of Sales by Year";
    
    // Start a new instance of Access for Automation:
                oAccess = new Access.ApplicationClass();
    
    // Make sure Access is visible:
                if(!oAccess.Visible) oAccess.Visible = true;
    
    // Determine the path to Northwind.mdb:
                sDBPath = oAccess.SysCmd(Access.AcSysCmdAction.acSysCmdAccessDir,
                   moMissing, moMissing).ToString();
                sDBPath = sDBPath + @"Samples\Northwind.mdb";
    
    // Open Northwind.mdb in shared mode:
                oAccess.OpenCurrentDatabase(sDBPath, false, "");
                // If using Access 10.0 object library, use this instead:
                //oAccess.OpenCurrentDatabase(sDBPath, false, null);
    
    // Close any forms that Northwind may have opened:
                while(oAccess.Forms.Count > 0)
                {   
                   oForm = oAccess.Forms[0];
                   oAccess.DoCmd.Close(Access.AcObjectType.acForm,
                      oForm.Name, Access.AcCloseSave.acSaveNo);
                   NAR(oForm);
                   oForm = null;
                }
    
    // Select the report name in the database window and give focus
                // to the database window:
                oAccess.DoCmd.SelectObject(Access.AcObjectType.acReport, sReport, true);
    
    // Maximize the Access window:
                oAccess.RunCommand(Access.AcCommand.acCmdAppMaximize);
    
    // Preview the report:
                oAccess.DoCmd.OpenReport(sReport,
                   Access.AcView.acViewPreview, moMissing, moMissing, 
                   Access.AcWindowMode.acWindowNormal, moMissing);
                // If using Access 10.0 object library, use this instead:
                //oAccess.DoCmd.OpenReport(sReport,
                //  Access.AcView.acViewPreview, moMissing, moMissing,
                //  Access.AcWindowMode.acWindowNormal, moMissing);
    
    // Maximize the report window:
                oAccess.DoCmd.Maximize();
    
    // Hide Access menu bar:
                oAccess.CommandBars["Menu Bar"].Enabled = false;
                // Also hide NorthWindCustomMenuBar if it is available:
                try
                {
                   oAccess.CommandBars["NorthwindCustomMenuBar"].Enabled = false;
                }
                catch{}
    
    // Hide Report's Print Preview menu bar:
                oAccess.CommandBars["Print Preview"].Enabled = false;
    
    // Hide Report's right-click popup menu:
                oAccess.CommandBars["Print Preview Popup"].Enabled = false;
    
    // Release Application object and allow Access to be closed by user:
                if(!oAccess.UserControl) oAccess.UserControl = true;
                NAR(oAccess);
                oAccess = null;
             }
             catch(Exception e)
             {
                MessageBox.Show(e.Message);
                // Release any Access objects and quit Access due to error:
                NAR(oForm);
                oForm = null;
                try // use try..catch in case oAccess is not set
                {
                   oAccess.Quit(Access.AcQuitOption.acQuitSaveNone);
                }
                catch{}
                NAR(oAccess);
                oAccess = null;
             }
          }
    
    private void Show_Form()
          {
             // Shows the "Customer Labels Dialog" form in Northwind.mdb
             // and manipulates controls on the form.
    
    Access.Application oAccess = null;
             Access.Form oForm = null;
             Access.Controls oCtls = null;
             Access.Control oCtl = null;
             string sDBPath = null; //path to Northwind.mdb
             string sForm = null; //name of form to show
    
    // Enable exception handler:
             try
             {
                sForm = "Customer Labels Dialog";
    
    // Start a new instance of Access for Automation:
                oAccess = new Access.ApplicationClass();
    
    // Make sure Access is visible:
                if(!oAccess.Visible) oAccess.Visible = true;
    
    // Determine the path to Northwind.mdb:
                sDBPath = oAccess.SysCmd(Access.AcSysCmdAction.acSysCmdAccessDir,
                   moMissing, moMissing).ToString();
                sDBPath = sDBPath + @"Samples\Northwind.mdb";
    
    // Open Northwind.mdb in shared mode:
                oAccess.OpenCurrentDatabase(sDBPath, false, "");
                // If using Access 10.0 object library, use this instead:
                //oAccess.OpenCurrentDatabase(sDBPath, false, null);
    
    // Close any forms that Northwind may have opened:
                while(oAccess.Forms.Count > 0)
                {   
                   oForm = oAccess.Forms[0];
                   oAccess.DoCmd.Close(Access.AcObjectType.acForm,
                      oForm.Name, Access.AcCloseSave.acSaveNo);
                   NAR(oForm);
                   oForm = null;
                }
    
    // Select the form name in the database window and give focus
                // to the database window:
                oAccess.DoCmd.SelectObject(Access.AcObjectType.acForm, sForm, true);
    
    // Show the form:
                oAccess.DoCmd.OpenForm(sForm, Access.AcFormView.acNormal, moMissing,
                   moMissing, Access.AcFormOpenDataMode.acFormPropertySettings,
                   Access.AcWindowMode.acWindowNormal, moMissing);
    
    // Use Controls collection to edit the form:
    
    oForm = oAccess.Forms[sForm];
                oCtls = oForm.Controls;
    
    // Set PrintLabelsFor option group to Specific Country:
    
    oCtl = (Access.Control)oCtls["PrintLabelsFor"];
                object[] Parameters = new Object[1];
                Parameters[0] = 2; //second option in option group
                oCtl.GetType().InvokeMember("Value", BindingFlags.SetProperty,
                   null, oCtl, Parameters);
                NAR(oCtl);
                oCtl = null;
    
    // Put USA in the SelectCountry combo box:
                oCtl = (Access.Control)oCtls["SelectCountry"];
                Parameters[0] = true;
                oCtl.GetType().InvokeMember("Enabled", BindingFlags.SetProperty,
                   null, oCtl, Parameters);
                oCtl.GetType().InvokeMember("SetFocus", BindingFlags.InvokeMethod,
                   null, oCtl, null);
                Parameters[0] = "USA";
                oCtl.GetType().InvokeMember("Value", BindingFlags.SetProperty,
                   null, oCtl, Parameters);
                NAR(oCtl);
                oCtl = null;
    
    // Hide the Database Window:
                oAccess.DoCmd.SelectObject(Access.AcObjectType.acForm, sForm, true);
                oAccess.RunCommand(Access.AcCommand.acCmdWindowHide);
    
    // Set focus back to the form:
                oForm.SetFocus();
    
    // Release Controls and Form objects:       
                NAR(oCtls);
                oCtls = null;
                NAR(oForm);
                oForm = null;
    
    // Release Application object and allow Access to be closed by user:
                if(!oAccess.UserControl) oAccess.UserControl = true;
                NAR(oAccess);
                oAccess = null;
             }
             catch(Exception e)
             {
                MessageBox.Show(e.Message);
                // Release any Access objects and quit Access due to error:
                NAR(oCtl);
                oCtl = null;
                NAR(oCtls);
                oCtls = null;
                NAR(oForm);
                oForm = null;
                try // use try..catch in case oAccess is not set
                {
                   oAccess.Quit(Access.AcQuitOption.acQuitSaveNone);
                }
                catch{}
                NAR(oAccess);
                oAccess = null;
             }
          }
    
    private void Print_Report_Security()
          {
             //Shows how to automate Access when user-level
             //security is enabled and you wish to avoid the logon
             //dialog asking for user name and password. In this
             //example we're assuming default security so we simply
             //pass the Admin user with a blank password to print the
             //"Summary of Sales by Year" report in Northwind.mdb.
    
    Access.Application oAccess = null;
             string sDBPath = null; //path to Northwind.mdb
             string sUser = null; //user name for Access security
             string sPwd = null; //user password for Access security
             string sReport = null; //name of report to print
    
    // Enable exception handler:
             try
             {
                sReport = "Summary of Sales by Year";
    
    // Determine the path to Northwind.mdb:
                sDBPath = GetOfficeAppPath("Access.Application", "msaccess.exe");
                if(sDBPath == null)
                {
                   MessageBox.Show("Can't determine path to msaccess.exe");
                   return;
                }
                sDBPath = sDBPath.Substring(0, sDBPath.Length - "msaccess.exe".Length)
                   + @"Samples\Northwind.mdb";
                if(!System.IO.File.Exists(sDBPath))
                {
                   MessageBox.Show("Can't find the file '" + sDBPath + "'");
                   return;
                }
    
    // Specify the user name and password for the Access workgroup
                // information file, which is used to implement Access security.
                // Note: If you are not using the system.mdw in the default
                // location, you may include the /wrkgrp command-line switch to
                // point to a different workgroup information file.
                sUser = "Admin";
                sPwd = "";
    
    // Start a new instance of Access with user name and password:
                oAccess = ShellGetDB(sDBPath, "/user " + sUser + " /pwd " + sPwd,
                   ProcessWindowStyle.Minimized, 1000);
                //or
                //oAccess = ShellGetApp(@"""" + sDBPath + @"""" + 
                //  " /user " + sUser + " /pwd " + sPwd,
                //  ProcessWindowStyle.Minimized);
    
    // Select the report name in the database window and give focus
                // to the database window:
                oAccess.DoCmd.SelectObject(Access.AcObjectType.acReport, sReport, true);
    
    // Print the report:
                oAccess.DoCmd.OpenReport(sReport,
                   Access.AcView.acViewNormal, moMissing, moMissing,
                   Access.AcWindowMode.acWindowNormal, moMissing );
                // If using Access 10.0 object library, use this instead:                       
                //oAccess.DoCmd.OpenReport(sReport,
                //  Access.AcView.acViewNormal, moMissing, moMissing,
                //  Access.AcWindowMode.acWindowNormal, moMissing);
             }
             catch(Exception e)
             {   
                MessageBox.Show(e.Message);
             }
             finally
             {
                // Release any Access objects and quit Access:
                try // use try..catch in case oAccess is not set
                {
                   oAccess.Quit(Access.AcQuitOption.acQuitSaveNone);
                }
                catch{}
                NAR(oAccess);
                oAccess = null;
             }
          }
    
    private void Preview_Report_Runtime()
          {
             //Shows how to automate the Access Runtime to preview
             //the "Summary of Sales by Year" report in Northwind.mdb.
    
    Access.Application oAccess = null;
             Access.Form oForm = null;
             string sDBPath = null; //path to Northwind.mdb
             string sReport = null; //name of report to preview
    
    // Enable exception handler:
             try
             {
                sReport = "Summary of Sales by Year";
    
    // Determine the path to Northwind.mdb:
                sDBPath = GetOfficeAppPath("Access.Application", "msaccess.exe");
                if(sDBPath == null)
                {
                   MessageBox.Show("Can't determine path to msaccess.exe");
                   return;
                }
    
    sDBPath = sDBPath.Substring(0, sDBPath.Length - "msaccess.exe".Length)
                   + @"Samples\Northwind.mdb";
                if(!System.IO.File.Exists(sDBPath))
                {
                   MessageBox.Show("Can't find the file '" + sDBPath + "'");
                   return;
                }
    
    // Start a new instance of Access with a database. If the
                // retail version of Access is not installed, and only the
                // Access Runtime is installed, launches a new instance
                // of the Access Runtime (/runtime switch is optional):
                oAccess = ShellGetDB(sDBPath, "/runtime",
                   ProcessWindowStyle.Minimized, 1000);
                //or
                //oAccess = ShellGetApp(@"""" + sDBPath + @"""" + " /runtime",
                //  ProcessWindowStyle.Minimized);
    
    // Make sure Access is visible:
                if(!oAccess.Visible) oAccess.Visible = true;
    
    // Close any forms that Northwind may have opened:
                while(oAccess.Forms.Count > 0)
                {   
                   oForm = oAccess.Forms[0];
                   oAccess.DoCmd.Close(Access.AcObjectType.acForm,
                      oForm.Name, Access.AcCloseSave.acSaveNo);
                   NAR(oForm);
                   oForm = null;
                }
    
    // Select the report name in the database window and give focus
                // to the database window:
                oAccess.DoCmd.SelectObject(Access.AcObjectType.acReport, sReport, true);
    
    // Maximize the Access window:
                oAccess.RunCommand(Access.AcCommand.acCmdAppMaximize);
    
    // Preview the report:
                oAccess.DoCmd.OpenReport(sReport,
                   Access.AcView.acViewPreview, moMissing, moMissing,
                   Access.AcWindowMode.acWindowNormal, moMissing );
                // If using Access 10.0 object library, use this instead:
                //oAccess.DoCmd.OpenReport(sReport,
                //  Access.AcView.acViewPreview, moMissing, moMissing,
                //  Access.AcWindowMode.acWindowNormal, moMissing);
    
    // Maximize the report window:
                oAccess.DoCmd.Maximize();
    
    // Hide Access menu bar:
                oAccess.CommandBars["Menu Bar"].Enabled = false;
                // Also hide NorthWindCustomMenuBar if it is available:
                try
                {
                   oAccess.CommandBars["NorthwindCustomMenuBar"].Enabled = false;
                }
                catch{}
    
    // Release Application object and allow Access to be closed by user:
                if(!oAccess.UserControl) oAccess.UserControl = true;
                NAR(oAccess);
                oAccess =  null;
             }
             catch(Exception e)
             {
                MessageBox.Show(e.Message);
                // Release any Access objects and quit Access due to error:
                NAR(oForm);
                oForm = null;
                try // use try..catch in case oAccess is not set
                {
                   oAccess.Quit(Access.AcQuitOption.acQuitSaveNone);
                }
                catch{}
                NAR(oAccess);
                oAccess = null;
             }
          }
    
    
  11. Form1.cs의 Using 지시문에 다음 코드를 추가합니다.

    using System.Runtime.InteropServices;
    using System.Diagnostics;
    using System.Reflection; 
    
  12. F5 키를 눌러 프로그램을 빌드하고 실행합니다. Form1이 표시됩니다.

  13. 보고서 인쇄를 클릭한 다음 Go!를 클릭합니다. Print_Report 프로시저는 Northwind 데이터베이스에서 보고서를 출력합니다.

  14. 미리 보기 보고서를 클릭한 다음 Go!를 클릭합니다. Preview_Report 절차는 Northwind 데이터베이스에서 보고서를 미리 봅니다. 계속 진행할 준비가 되면 Access 인스턴스를 닫습니다.

  15. 양식 표시를 클릭한 다음 Go!를 클릭합니다. Show_Form 프로시저는 Northwind 데이터베이스의 고객 레이블 대화 상자 양식을 표시합니다. 또한 양식의 옵션 그룹을 "특정 국가"로 설정하고 목록에서 "USA"를 선택합니다. 계속 진행할 준비가 되면 Access 인스턴스를 닫습니다.

  16. 보고서 인쇄(보안)를 클릭한 다음 Go!를 클릭합니다. Print_Report_Security 절차에서는 Access를 자동화하는 방법과 사용자 수준 보안이 켜져 있는 경우 로그온 대화 상자를 방지하는 방법을 보여 있습니다. 이 예제에서는 빈 암호로 사용자 관리 전달하여 기본 로그온을 가정합니다. 그런 다음 코드는 Northwind 데이터베이스에 보고서를 출력합니다.

  17. 미리 보기 보고서(런타임)를 클릭한 다음 Go!를 클릭합니다. Preview_Report_Runtime 절차에서는 Access Runtime을 자동화하여 Northwind 데이터베이스에서 보고서를 미리 보는 방법을 보여줍니다. 소매 버전의 Access가 설치되어 있으면 프로시저가 여전히 올바르게 작동합니다. 계속할 준비가 되면 Access 인스턴스를 닫습니다.

참조

자세한 내용은 다음 MSDN 웹 사이트: Visual Studio https://msdn.microsoft.com/en-us/library/aa188489(office.10).aspx를 사용한 Microsoft Office Development를 참조하세요. 자세한 내용은 다음 문서 번호를 클릭하여 Microsoft 기술 자료의 문서를 확인합니다.

317109 Office 애플리케이션은 Visual Studio .NET 클라이언트에서 자동화한 후 종료되지 않습니다.

316126 Visual C#을 사용하여 Office 프로그램의 실행 중인 인스턴스를 자동화하는 방법