VC++에서 복합 문서 속성을 직접 읽는 방법

기술 자료 번역 기술 자료 번역
기술 자료: 186898 - 이 문서가 적용되는 제품 보기.
이 문서는 이전에 다음 ID로 출판되었음: KR186898
모두 확대 | 모두 축소

이 페이지에서

요약

서버를 실행하거나 설치하지 않고도 표준 인터페이스를 사용하여 문서에서 복합 문서 속성을 검색할 수 있습니다. 예를 들어, Microsoft Office 97 문서의 기본 문서 속성(예: 만든 이, 마지막 수정 시간 및 페이지 수)뿐 아니라 기타 사용자 정의 문서 속성도 검색할 수 있습니다.

추가 정보

다음은 Microsoft Visual C++에서 복합 문서 속성 뷰어를 만드는 절차입니다. Win32 콘솔 응용 프로그램 프로젝트를 예로 사용했으며 사용자의 필요에 맞게 이를 수정할 수 있습니다.

예제를 만드는 단계

  1. 새로운 Win32 콘솔 응용 프로그램 프로젝트를 만들고 PropDump라는 이름을 지정합니다.
  2. main.cpp라는 새로운 파일을 프로젝트에 추가합니다.
  3. 다음 코드를 main.cpp에 복사합니다.
       #include <stdio.h>
       #include <windows.h>
       #include <ole2.h>
       #include <locale.h>
    
    
    
       // Dumps simple PROPVARIANT values.
       void DumpPropVariant(PROPVARIANT *pPropVar) {
          // Don't iterate arrays, just inform as an array.
          if(pPropVar->vt & VT_ARRAY) {
             printf("(Array)\n");
             return;
          }
    
          // Don't handle byref for simplicity, just inform byref.
          if(pPropVar->vt & VT_BYREF) {
             printf("(ByRef)\n");
             return;
           }
    
          // Switch types.
          switch(pPropVar->vt) {
          case VT_EMPTY:
             printf("(VT_EMPTY)\n");
             break;
          case VT_NULL:
             printf("(VT_NULL)\n");
             break;
          case VT_BLOB:
             printf("(VT_BLOB)\n");
             break;
          case VT_BOOL:
             printf("%s (VT_BOOL)\n",
             pPropVar->boolVal ? "TRUE/YES" : "FALSE/NO");
             break;
          case VT_I2: // 2-byte signed int.
             printf("%d (VT_I2)\n", (int)pPropVar->iVal);
             break;
          case VT_I4: // 4-byte signed int.
             printf("%d (VT_I4)\n", (int)pPropVar->lVal);
             break;
          case VT_R4: // 4-byte real.
             printf("%.2lf (VT_R4)\n", (double)pPropVar->fltVal);
             break;
          case VT_R8: // 8-byte real.
             printf("%.2lf (VT_R8)\n", (double)pPropVar->dblVal);
             break;
             case VT_BSTR: // OLE Automation string.
             {
                // Translate into ASCII.
                char dbcs[1024];
                char *pbstr = (char *)pPropVar->bstrVal;
                int i = wcstombs(
                dbcs, pPropVar->bstrVal, *((DWORD *)(pbstr-4)));
                dbcs[i] = 0;
                printf("%s (VT_BSTR)\n", dbcs);
             }
             break;
          case VT_LPSTR: // Null-terminated string.
             {
             printf("%s (VT_LPSTR)\n", pPropVar->pszVal);
             }
             break;
          case VT_FILETIME:
             {
                char *dayPre[] =
                             {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
    
                FILETIME lft;
                FileTimeToLocalFileTime(&pPropVar->filetime, &lft);                SYSTEMTIME lst;
                FileTimeToSystemTime(&lft, &lst);
    
                printf("%02d:%02d.%02d %s, %s %02d/%02d/%d (VT_FILETIME)\n",
                   1+(lst.wHour-1)%12, lst.wMinute, lst.wSecond,
                   (lst.wHour>=12) ? "pm" : "am",
                   dayPre[lst.wDayOfWeek%7],
                   lst.wMonth, lst.wDay, lst.wYear);
             }
             break;
          case VT_CF: // Clipboard format.
             printf("(Clipboard format)\n");
    
             break;
          default: // Unhandled type, consult wtypes.h's VARENUM structure.
             printf("(Unhandled type: 0x%08lx)\n", pPropVar->vt);
             break;
          }
       }
    
       // Dump's built-in properties of a property storage.
       void DumpBuiltInProps(IPropertySetStorage *pPropSetStg) {
          printf("\n==================================================\n");
          printf("BuiltInProperties Properties...\n");
          printf("==================================================\n");
    
          IPropertyStorage *pPropStg = NULL;
          HRESULT hr;
    
          // Open summary information, getting an IpropertyStorage.
          hr = pPropSetStg->Open(FMTID_SummaryInformation,
          STGM_READ | STGM_SHARE_EXCLUSIVE, &pPropStg);
          //hr = pPropSetStg->Open(FMTID_UserDefinedProperties,
             //STGM_READ | STGM_SHARE_EXCLUSIVE, &pPropStg);
          if(FAILED(hr)) {
             printf("No Summary-Information.\n");
             return;
          }
          // Array of PIDSI's you are interested in.
          struct pidsiStruct {
             char *name;
             long pidsi;
          } pidsiArr[] = {
             {"Title",            PIDSI_TITLE}, // VT_LPSTR
             {"Subject",          PIDSI_SUBJECT}, // ...
             {"Author",           PIDSI_AUTHOR},
             {"Keywords",         PIDSI_KEYWORDS},
             {"Comments",         PIDSI_COMMENTS},
             {"Template",         PIDSI_TEMPLATE},
             {"LastAuthor",       PIDSI_LASTAUTHOR},
             {"Revision Number",  PIDSI_REVNUMBER},
             {"Edit Time",        PIDSI_EDITTIME}, // VT_FILENAME (UTC)
             {"Last printed",     PIDSI_LASTPRINTED}, // ...
             {"Created",          PIDSI_CREATE_DTM},
             {"Last Saved",       PIDSI_LASTSAVE_DTM},
             {"Page Count",       PIDSI_PAGECOUNT}, // VT_I4
             {"Word Count",       PIDSI_WORDCOUNT}, // ...
             {"Char Count",       PIDSI_CHARCOUNT},
    
             {"Thumpnail",        PIDSI_THUMBNAIL}, // VT_CF
             {"AppName",          PIDSI_APPNAME}, // VT_LPSTR
             {"Doc Security",     PIDSI_DOC_SECURITY}, // VT_I4
             {0, 0}
          };
          // Count elements in pidsiArr.
          int nPidsi = 0;
          for(nPidsi=0; pidsiArr[nPidsi].name; nPidsi++);
    
          // Initialize PROPSPEC for the properties you want.
          PROPSPEC *pPropSpec = new PROPSPEC [nPidsi];
          PROPVARIANT *pPropVar = new PROPVARIANT [nPidsi];
    
          for(int i=0; i<nPidsi; i++) {
             ZeroMemory(&pPropSpec[i], sizeof(PROPSPEC));
             pPropSpec[i].ulKind = PRSPEC_PROPID;
             pPropSpec[i].propid = pidsiArr[i].pidsi;
          }
    
    
    
          // Read properties.
          hr = pPropStg->ReadMultiple(nPidsi, pPropSpec, pPropVar);
    
          if(FAILED(hr)) {
             printf("IPropertyStg::ReadMultiple() failed w/error %08lx\n",
                    hr);
          }
          else {
             // Dump properties.
             for(i=0; i<nPidsi; i++) {
                printf("%16s: ", pidsiArr[i].name);
                DumpPropVariant(pPropVar + i);
             }
          }
    
          // De-allocate memory.
          delete [] pPropVar;
          delete [] pPropSpec;
    
          // Release obtained interface.
          pPropStg->Release();
    
       }
    
       // Dump's custom properties of a property storage.
       void DumpCustomProps(IPropertySetStorage *pPropSetStg) {
          printf("\n==================================================\n");
          printf("Custom Properties...\n");
          printf("==================================================\n");
    
          IPropertyStorage *pPropStg = NULL;
          HRESULT hr;
          IEnumSTATPROPSTG *pEnumProp;
    
          // Open User-Defined-Properties, getting an IpropertyStorage.
          hr = pPropSetStg->Open(FMTID_UserDefinedProperties,
             STGM_READ | STGM_SHARE_EXCLUSIVE, &pPropStg);
          if(FAILED(hr)) {
             printf("No User Defined Properties.\n");
             return;
          }
    
          // Get property enumerator.
          hr = pPropStg->Enum(&pEnumProp);
          if(FAILED(hr)) {
          pPropStg->Release();
             printf("Couldn't enumerate custom properties.\n");
             return;
          }
    
          // Enumerate properties.
          STATPROPSTG sps;
          ULONG fetched;
          PROPSPEC propSpec[1];
          PROPVARIANT propVar[1];
          while(pEnumProp->Next(1, &sps, &fetched) == S_OK) {
             // Build a PROPSPEC for this property.
             ZeroMemory(&propSpec[0], sizeof(PROPSPEC));
             propSpec[0].ulKind = PRSPEC_PROPID;
             propSpec[0].propid = sps.propid;
    
             // Read this property.
    
             hr = pPropStg->ReadMultiple(1, &propSpec[0], &propVar[0]);
             if(!FAILED(hr)) {
                // Translate Prop name into ASCII.
                char dbcs[1024];
                char *pbstr = (char *)sps.lpwstrName;
                int i = wcstombs(dbcs, sps.lpwstrName,
                                 *((DWORD *)(pbstr-4)));
                dbcs[i] = 0;
    
                // Dump this property.
                printf("%16s: ", dbcs);
                DumpPropVariant(&propVar[0]);
             }
          }
    
          // Release obtained interface.
          pEnumProp->Release();
          pPropStg->Release();
    
       }
    
       // Dump's custom and built-in properties of a compound document.
       void DumpProps(char *filename) {
          // Translate filename to Unicode.
          WCHAR wcFilename[1024];
          setlocale( LC_ALL, "" );
          int i = mbstowcs(wcFilename, filename, strlen(filename));
          setlocale( LC_ALL, "C" );
          wcFilename[i] = 0;
    
          IStorage *pStorage = NULL;
          IPropertySetStorage *pPropSetStg = NULL;
          HRESULT hr;
    
          // Open the document as an OLE compound document.
          hr = ::StgOpenStorage(wcFilename, NULL,
          STGM_READ | STGM_SHARE_EXCLUSIVE, NULL, 0, &pStorage);
    
          if(FAILED(hr)) {
             if(hr == STG_E_FILENOTFOUND)
                printf("File not found.");
             else if(hr == STG_E_FILEALREADYEXISTS)
                printf("Not a compound file.");
             else
                printf("StgOpenStorage() failed w/error %08lx", hr);
             return;
          }
    
          // Obtain the IPropertySetStorage interface.
          hr = pStorage->QueryInterface(
                  IID_IPropertySetStorage, (void **)&pPropSetStg);
          if(FAILED(hr)) {
             printf("QI for IPropertySetStorage failed w/error %08lx", hr);
             pStorage->Release();
             return;
          }
    
          // Dump properties.
          DumpBuiltInProps(pPropSetStg);
          DumpCustomProps(pPropSetStg);
    
          // Release obtained interfaces.
          pPropSetStg->Release();
          pStorage->Release();
       }
    
       // Program entry-point.
       void main(int argc, char **argv) {
          // Validate arguments.
          if(argc != 2) {
             printf("- OLE Document Property Viewer\n");
             printf("- Usage: %s filename", argv[0]);
             return;
          }
    
          // Pass filename to the subroutine.
          DumpProps(argv[1]);
       }
    					
  4. 프로그램을 컴파일합니다.
예제를 실행하려면 PropDump.exe 파일을 기본 경로의 디렉터리(예: c:\Windows\ 또는 c:\Windows\Command\)로 복사해야 합니다. 그런 다음 복합 문서 파일이 포함되어 있는 디렉터리에서 PropDump와 해당 파일 이름을 차례로 입력합니다. 아래와 유사한 출력이 표시됩니다.

==================================================

BuiltInProperties Properties...

           Title: MyTitle (VT_LPSTR)
         Subject: MySubject (VT_LPSTR)
          Author: MyAuthor (VT_LPSTR)
        Keywords: MyKeywords (VT_LPSTR)
        Comments: MyComments (VT_LPSTR)
        Template: Normal (VT_LPSTR)
      LastAuthor: Me (VT_LPSTR)

 Revision Number: 8 (VT_LPSTR)

       Edit Time: 01:05.47 pm, Mon 01/01/1601 (VT_FILETIME)
    Last printed: (VT_EMPTY)
         Created: 01:42.00 pm, Fri 05/29/1998 (VT_FILETIME)
      Last Saved: 12:31.00 pm, Mon 06/01/1998 (VT_FILETIME)
      Page Count: 1 (VT_I4)
      Word Count: 3 (VT_I4)
      Char Count: 19 (VT_I4)
       Thumpnail: (VT_EMPTY)
         AppName: Microsoft Word 8.0 (VT_LPSTR)
    Doc Security: 0 (VT_I4)
				
==================================================

Custom Properties...

   _PID_LINKBASE: (VT_BLOB)

       _PID_GUID: (VT_BLOB)
       CustProp1: CustProp1TextValue (VT_LPSTR)
       CustProp2: 77777 (VT_I4)
       CustProp3: TRUE/YES (VT_BOOL)
       CustProp4: 00:00.00 am, Tue 05/17/1977 (VT_FILETIME)
				

추가 정보

COM의 원래 릴리스에서는 IPropertyStorage 인터페이스와 IPropertySetStorage 인터페이스가 정의되지 않았으므로 이 예제 코드를 실행하려면 다음과 같은 시스템 사양이 필요합니다.
  • Windows NT 4.0 이상
  • Internet Explorer 버전 4.0 이상이 설치된 Windows 95
  • DCOM이 설치된 Windows 95
이전 버전의 COM에는 속성과 그 사용법이 거의 지정되지 않았지만, 개발자가 속성과 속성 집합을 IStorage 인스턴스에 저장할 수 있도록 일련의 형식이 정의되었습니다. 문서에 대한 요약 정보에 사용되는 단일 속성 집합의 속성 식별자와 구문도 정의되었습니다. 당시에는 그러한 구조를 직접 데이터 스트림으로 만들고 조작해야 했습니다. 속성 집합의 순차적인 데이터 형식 구조에 대한 자세한 내용은 Microsoft Developer Network의 "OLE Serialized Property Set Format"을 참조하십시오.

(c) Microsoft Corporation 1999, All Rights Reserved. 기고: Joe Crump, Microsoft Corporation.

참조

Microsoft Developer Network: Persistent Property Sets

Microsoft Developer Network: OLE Serialized Property Set Format





Microsoft 제품 관련 기술 전문가들과 온라인으로 정보를 교환하시려면 Microsoft 뉴스 그룹에 참여하시기 바랍니다.

속성

기술 자료: 186898 - 마지막 검토: 2006년 4월 21일 금요일 - 수정: 4.3
본 문서의 정보는 다음의 제품에 적용됩니다.
  • Microsoft Project 2000 Standard Edition
  • Microsoft Excel 2000 Standard Edition
  • Microsoft Visual C++ 5.0 Enterprise Edition
  • Microsoft Visual C++ 5.0 Professional Edition
  • Microsoft Excel 97 Standard Edition
  • Microsoft PowerPoint 97 Standard Edition
  • Microsoft Word 97 Standard Edition
  • Microsoft PowerPoint 2000 Standard Edition
  • Microsoft Word 2000 Standard Edition
  • Microsoft Excel 2002 Standard Edition
  • Microsoft PowerPoint 2002 Standard Edition
  • Microsoft Word 2002 Standard Edition
키워드:?
kbhowto kbcmpdoc kbfaq KB186898

피드백 보내기

 

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