이 글은 제가 검색하는 과정도 포함되어 있습니다.

윈도우에서 파일의 정보를 가져오기 위해서 기본적으로 사용하고 있는 클래스는 FileInfo 입니다.
하지만 어느 카메라로 찍었는지, 어디서 찍었는지 등에 대한 정보를 확인하기 위해서는 MetaData를 확인해야 합니다.

그래서 구글에서 검색을 시작하였습니다. 처음으로 검색한 단어는 "read image metadata c#" 입니다.
관련 코드를 쉽게 찾을 수 있었습니다.

출처: Reading data metadata from JPEG, XMP or EXIF in C#
주소: https://stackoverflow.com/questions/2280948/reading-data-metadata-from-jpeg-xmp-or-exif-in-c-sharp?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa

위 제공된 코드는 아래와 같습니다.

    public string GetDate(FileInfo f)
    {
        using(FileStream fs = new FileStream(f.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
        {
            BitmapSource img = BitmapFrame.Create(fs);
            BitmapMetadata md = (BitmapMetadata)img.Metadata;
            string date = md.DateTaken;
            Console.WriteLine(date);
            return date;
        }
    }

그래서 Visual Studio 에서 바로 실행해 보기로 했습니다.

1. Visual Studio(2017 기준) 를 실행하고 새로운 프로젝트를 생성합니다.
상단 메뉴의 파일(F) - 새로 만들기(N) - 프로젝트(P) 를 선택합니다.

좌측 메뉴에 Visual C# - Windows 클래식 바탕화면을 선택하고 가운데 메뉴에 Windows Forms 앱(,net Framework)를 선택합니다.
앱 이름은 WindowsFormsGetMetaData 로 정하겠습니다. 폴더는 원하는 위치를 지정해 주세요. 아래 그림과 같이 설정이 끝났으면 확인 버튼을 클릭합니다.

폼 이름 및 크기를 바꿔볼께요.
폼을 선택하고 속성 도구를 열고 Text와 Size 속성을 바꿉니다.
(Name): Form1 - Text: 메타데이터 읽기 / Size: 400, 600

다음에 컨트톨을 추가해 보겠습니다.
도구 상자탭을 선택하고 원하는 도구 상자를 드래그해서 폼 안에 넣으면 됩니다.

저는 아래와 같이 넣었습니다.

각 도구의 주요 속성은 다음과 같습니다.

버튼(Button) - (Name): button1 / Location: 20, 20 / AutoSize: False / Size: 75, 23 / Text: 파일 선택
라벨(Label) - (Name): label1 / Location: 20, 60 / AutoSize: True / Size: 73, 12(자동으로 설정됨) / Text: 선택된 파일:
라벨(Label) - (Name): label2 / Location: 100, 60 / AutoSize: True / Size: 29, 12(자동으로 설정됨) / Text: 없음
자료보기창(DataGridView) - (Name): dataGridView1 / Location: 20, 90 / AutoSize: False / Size: 350, 450

외형을 완성했으면 이제 프로그래밍을 해보겠습니다.
폴더 선택 버튼을 더블클릭하면 자동으로 이벤트가 추가되고 코드보기 화면으로 전환됩니다.

우선 버튼 클릭 부분에는 OpenFileDialog 를 생성해서 파일이 있으면 파일명을 MessageBox에서 보여주도록 코드를 작성하였습니다.

버튼클릭 이벤트 아래쪽에 위에서 찾은 코드를 복사합니다. 우선 FileInfo 는 using System.IO; 를 활용해서 불러옵니다.
이렇게 하면 아래 그림과 같이 오류가 발생합니다.

이제부터 오류가 발생하는 부분을 찾아보겠습니다.

BitmapSource 를 구글에서 찾아보니 아래 링크에서 해당 클래스 정보를 확인할 수 있습니다.
제목: BitmapSource 클래스
네임스페이스:   System.Windows.Media.Imaging
어셈블리:  PresentationCore(PresentationCore.dll에 있음)
https://msdn.microsoft.com/ko-kr/library/system.windows.media.imaging.bitmapsource(v=vs.110).aspx

위 내용을 보면 PresentationCore 어셈블리를 추가하면 될 것으로 보입니다.
아래 그림과 같이 솔루션 탐색기에서 참조에 마우스를 대고 오른쪽 버튼을 클릭한 후에 참조 추가 메뉴를 클릭합니다.

오른쪽 어셈블리에서 프레임워크를 선택하고 오른쪽 검색창에 "presentationcore" 를 검색하면 결과가 하나만 나타납니다.
추가하려면 이름 옆에 있는 체크박스를 클릭해서 체크표시 한 후에 확인 버튼을 클릭하면 PresentationCore 어셈블리를 사용할 수 있습니다.

그리고 코딩 파일에 "using System.Windows.Media.Imaging;" 을 입력해서 해당 네임 스페이스를 불러옵니다.
그러면 BitmapSource, BitmapFrame, BitmapMetadata 사용이 가능합니다. 하지만 여전히 "BitmapFrame.Create" 부분에서 오류가 발생하네요.
오류 내용은 다음과 같습니다.

'Freezable' 형식이 참조되지 않은 어셈블리에 정의되었습니다. 'WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' 어셈블리에 참조를 추가해야 합니다.

이 부분도 동일하게 해결 가능합니다.

솔루션 탐색기에서 참조에 마우스를 대고 오른쪽 버튼을 클릭한 후에 참조 추가 메뉴를 클릭합니다.
오른쪽 어셈블리에서 프레임워크를 선택하고 오른쪽 검색창에 "windowsbase" 를 검색하면 결과가 하나만 나타납니다.
추가하려면 이름 옆에 있는 체크박스를 클릭해서 체크표시 한 후에 확인 버튼을 클릭하면 WindowsBase 어셈블리를 사용할 수 있습니다.

이제 오류는 다 잡았습니다. 지금부터는 원하는 정보를 가져와서 DataGridView에 보여주면 되겠네요.
메서드1. 위에 제공된 코드를 아래와 같이 수정합니다. 기존 코드는 파일을 만든 날짜만 확인하였는데 전 확인 가능한 모든 속성을 가져오겠습니다.

        /// <summary>
        /// 선택한 파일의 메타데이터를 DataTable 형식으로 보냅니다.
        /// </summary>
        /// <param name="f">자료를 가져올 파일의 FileInfo를 입력합니다.</param>
        /// <returns></returns>
        private DataTable GetDate(FileInfo f)
        {
            using (FileStream fs = new FileStream(f.FullName, FileMode.Open, FileAccess.Read, FileShare.Read)) // 선택된 파일의 FileStream 을 생성합니다. 
            {
                DataTable dt1 = new DataTable(); // 새로운 DataTable을 생성합니다.
                dt1.Columns.Add("attribute"); // 속성 이름을 저장합니다.
                dt1.Columns.Add("value"); // 속성 값을 저장합니다.

                BitmapSource img = BitmapFrame.Create(fs); // 선택된 파일의 FileStream 를 활용하여 BitmapSource 를 생성합니다.
                BitmapMetadata md = (BitmapMetadata)img.Metadata; // 

                // BitmapMetadata 에서 제공하는 모든 속성 값을 불러옵니다. 시작
                // https://msdn.microsoft.com/ko-kr/library/system.windows.media.imaging.bitmapmetadata(v=vs.110).aspx
                dt1.Rows.Add("ApplicationName", md.ApplicationName);
                dt1.Rows.Add("Author", md.Author);
                dt1.Rows.Add("CameraManufacturer", md.CameraManufacturer);
                dt1.Rows.Add("CameraModel", md.CameraModel);
                dt1.Rows.Add("CanFreeze", md.CanFreeze);
                dt1.Rows.Add("Comment", md.Comment);
                dt1.Rows.Add("Copyright", md.Copyright);
                dt1.Rows.Add("DateTaken", md.DateTaken);
                dt1.Rows.Add("DependencyObjectType", md.DependencyObjectType);
                dt1.Rows.Add("Dispatcher", md.Dispatcher);
                dt1.Rows.Add("Format", md.Format);
                dt1.Rows.Add("IsFixedSize", md.IsFixedSize);
                dt1.Rows.Add("IsFrozen", md.IsFrozen);
                dt1.Rows.Add("IsReadOnly", md.IsReadOnly);
                dt1.Rows.Add("IsSealed", md.IsSealed);
                dt1.Rows.Add("Keywords", md.Keywords);
                dt1.Rows.Add("Location", md.Location);
                dt1.Rows.Add("Rating", md.Rating);
                dt1.Rows.Add("Subject", md.Subject);
                dt1.Rows.Add("Title", md.Title);
                // BitmapMetadata 에서 제공하는 모든 속성 값을 불러옵니다. 끝

                return dt1;
            }
        }


매서드2. 위에서 제공된 결과를 DataGridView 컨트롤에서 볼 수 있도록 가져옵니다.

        /// <summary>
        /// 선택한 폴더의 파일 목록을 가져와서 DataGridView 도구에 보여줍니다.
        /// </summary>
        /// <param name="dt1">선택한 폴더의 파일 목록이 들어있는 DataTable을 입력합니다.</param>
        /// <param name="dgv1">결과를 출력할 DataGridView를 선택합니다.</param>
        private void ShowDataFromDataTableToDataGridView(DataTable dt1, DataGridView dgv1)
        {
            dgv1.Rows.Clear(); // 이전 정보가 있을 경우, 모든 행을 삭제합니다.
            dgv1.Columns.Clear(); // 이전 정보가 있을 경우, 모든 열을 삭제합니다.

            foreach (DataColumn dc1 in dt1.Columns) // 선택한 파일 목록이 들어있는 DataTable의 모든 열을 스캔합니다.
            {
                dgv1.Columns.Add(dc1.ColumnName, dc1.ColumnName); // 출력할 DataGridView에 열을 추가합니다.
            }

            int row_index = 0; // 행 인덱스 번호(초기 값)
            foreach (DataRow dr1 in dt1.Rows) // 선택한 파일 목록이 들어있는 DataTable의 모든 행을 스캔합니다.
            {
                dgv1.Rows.Add(); // 빈 행을 하나 추가합니다.
                foreach (DataColumn dc1 in dt1.Columns) // 선택한 파일 목록이 들어있는 DataTable의 모든 열을 스캔합니다.
                {
                    dgv1.Rows[row_index].Cells[dc1.ColumnName].Value = dr1[dc1.ColumnName]; // 선택 행 별로, 스캔하는 열에 해당하는 셀 값을 입력합니다.
                }
                row_index++; // 다음 행 인덱스를 선택하기 위해 1을 더해줍니다.
            }

            foreach (DataGridViewColumn drvc1 in dgv1.Columns) // 결과를 출력할 DataGridView의 모든 열을 스캔합니다.
            {
                drvc1.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; // 선택 열의 너비를 자동으로 설정합니다.
            }
        }

위에서 만든 2개의 매서드를 활용하여 버튼클릭 이벤트를 아래와 같이 수정합니다.

        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog1 = new OpenFileDialog(); // 새로운 OpenFileDialog 를 생성합니다.
            if (openFileDialog1.ShowDialog() == DialogResult.OK) // 파일이 정상적으로 선택되었을 경우에 동작합니다.
            {
                label2.Text = openFileDialog1.FileName; // 선택된 파일을 label2에 출력합니다.
                FileInfo f = new FileInfo(openFileDialog1.FileName); // 파일 전체 경로로 해당 파일의 FileInfo를 생성합니다.
                DataTable dt_metadata = GetDate(f);
                ShowDataFromDataTableToDataGridView(dt_metadata,dataGridView1);
            }
        }

전체 코드는 아래와 같습니다.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using System.IO;
using System.Windows.Media.Imaging;

namespace WindowsFormsGetMetaData
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog1 = new OpenFileDialog(); // 새로운 OpenFileDialog 를 생성합니다.
            if (openFileDialog1.ShowDialog() == DialogResult.OK) // 파일이 정상적으로 선택되었을 경우에 동작합니다.
            {
                label2.Text = openFileDialog1.FileName; // 선택된 파일을 label2에 출력합니다.
                FileInfo f = new FileInfo(openFileDialog1.FileName); // 파일 전체 경로로 해당 파일의 FileInfo를 생성합니다.
                DataTable dt_metadata = GetDate(f);
                ShowDataFromDataTableToDataGridView(dt_metadata,dataGridView1);
            }
        }

        /// <summary>
        /// 선택한 파일의 메타데이터를 DataTable 형식으로 보냅니다.
        /// </summary>
        /// <param name="f">자료를 가져올 파일의 FileInfo를 입력합니다.</param>
        /// <returns></returns>
        private DataTable GetDate(FileInfo f)
        {
            생략(매서드1)
        }

        /// <summary>
        /// 선택한 폴더의 파일 목록을 가져와서 DataGridView 도구에 보여줍니다.
        /// </summary>
        /// <param name="dt1">선택한 폴더의 파일 목록이 들어있는 DataTable을 입력합니다.</param>
        /// <param name="dgv1">결과를 출력할 DataGridView를 선택합니다.</param>
        private void ShowDataFromDataTableToDataGridView(DataTable dt1, DataGridView dgv1)
        {
            생략(매서드2)
        }

    }
}

이제 실행해 보겠습니다.
실행하면 다음과 같이 나타납니다.

메타데이터가 있는 그림파일을 선택하면 다음과 같이 읽어오는 것을 볼 수 있습니다.

하지만 윈도우 탐색기에서 파일 선택해서 마우스 오른쪽 버튼 클릭 후 속성 클릭 후 자세히 보기에 나타나는 정보는 기본적으로 제공하는 MetaData 보다 많은 것을 확인할 수 있습니다. 이 부분에 대해 아시는 분 있으면 댓글 남겨주세요. 저도 관련 정보를 더 찾아보도록 하겠습니다.

감사합니다.

+ Recent posts