훈, IT 공부/C,C++,MFC

C/C++ IPropertyStore / 파일 속성 모두 얻어오기 .doc .docs .xlsx .pptx

IT훈이 2022. 8. 11.
반응형

 

C/C++ IPropertyStore / 파일 속성 모두 얻어오기 .doc .docs .xlsx .pptx

 

IPropertyStore()

 

개발을 진행하다보면 별 특이한 경우를 많이 경험하게 됩니다.

개발을 하다가 발생된 이슈로 인한 

기능정리를 위한 포스팅을 진행할까 합니다.

 

안녕하세요 IT훈이입니다 😁

 

 

이슈

 word 파일의 버전을 취득해야하는 상황입니다.  '속성-자세히-유형' 에 있는 값을 취득하여서 값을 분기처리 해줘야합니다. 해당 값을 얻기위해서 구글링을 진행하는데, 생각보다 원하는 결과를 얻기가 어려웠기에 포스팅으로 기록을 남겨봅니다.

 

 

SHGetPropertyStoreFromParsingName 함수사용

 구글링을 열심히 하다보니, SHGetPropertyStoreFromParsingName 함수를 활용하여 해결할 수 있다는 내용을 확인하고 바로 테스트코드를 작성해보았습니다. MFC를 통하여 개발한점 참고바랍니다. ( 소스는 글 아래 있습니다 )

 SHGetPropertyStoreFromParsingName 함수를 통해서 자세히 영역의 값을 취득하기 위해서는 사용자가 직접 GetValue를 통하여 'INIT_PKEY_ ' 로 시작하는 키 값을 하나씩 넣어서 찾아가는 방식입니다.

 

 

propkey.h 파일을 보시면, 'INIT_PKEY_  ' 로 시작하는 Define들이 있는것을 확인하실 수 있습니다. 해당방식으로 찾게되면 이 많은 정의값들중에서 내가 원하는 갚은 찾아야하는데, 워낙 노가다적인 측면이 있습니다.

 

 

propkey.h 파일의 라인이 8571줄... 어마어마한 길이거든요. 그래서 이렇게 하는 방식보다 좀더 좋은 방식을 아래에서 알려드리겠습니다.

 

소스코드

헤더부분

#include "pch.h"
#include "framework.h"
#include "MFCApplication2.h"
#include "MFCApplication2Dlg.h"
#include "afxdialogex.h"
#include <Windows.h>

#include <shobjidl.h>
#include <propsys.h>
#include <propvarutil.h>
#include <propkey.h>
#include <strsafe.h>

 

 

소스부분

Visual Studio 2022 환경에서 MFC로 개발하였습니다.

void CMFCApplication2Dlg::OnCheck01()
{
	
	HRESULT hr = ::CoInitialize(nullptr);
	IPropertyStore* pps;
	TCHAR wszAppID[MAX_PATH] = { 0, };

	bool success = false;
	if (SUCCEEDED(SHGetPropertyStoreFromParsingName(_T("D:\\reseouch\\MFCApplication2\\test1.doc"), NULL, GPS_DEFAULT, IID_PPV_ARGS(&pps))) )
	{
		PROPVARIANT propvar;
		HRESULT hres = (pps->GetValue(INIT_PKEY_ItemTypeText, &propvar));
		if (SUCCEEDED(hres))
		{
			MessageBox(propvar.pwszVal);
			PropVariantClear(&propvar);
			success = true;
		}

		if (pps) {
			pps->Release();
		}
		CoUninitialize();
	}
}

 

 

GetPropertyStore 함수 사용

우선 결과값을 아래 사진을 통해서 확인해보시면, 파일속성의 모든 데이터를 긁어온것을 확인하실 수 있습니다. 위의 SHGetPropertyStoreFromParsingName 함수를 통한 방법은 하나씩 입력하여 찾는 방식인 반면에 GetPropertyStore함수를 통한 방식은 모든 속성을 찾아오는 방식이기에 좀더 편리합니다.

 

 

소스

헤더부분

#include "pch.h"
#include "framework.h"
#include "MFCApplication2.h"
#include "MFCApplication2Dlg.h"
#include "afxdialogex.h"
#include <Windows.h>

#include <shobjidl.h>
#include <propsys.h>
#include <propvarutil.h>
#include <propkey.h>
#include <strsafe.h>

 

 

소스부분 

Visual Studio 2022 환경에서 MFC로 개발하였습니다.

HRESULT PrintProperty(IPropertyStore* pps, REFPROPERTYKEY key, PCWSTR pszCanonicalName)
{
	PROPVARIANT propvarValue = { 0 };
	HRESULT hr = pps->GetValue(key, &propvarValue);
	if (SUCCEEDED(hr))
	{
		WCHAR wMsg[MAX_PATH] = { 0, };
		PWSTR pszDisplayValue = NULL;
		hr = PSFormatForDisplayAlloc(key, propvarValue, PDFF_DEFAULT, &pszDisplayValue);
		if (SUCCEEDED(hr))
		{
			wsprintf(wMsg,L"%s = %s\n", pszCanonicalName, pszDisplayValue);
			sMsg.Append(wMsg);
			
			CoTaskMemFree(pszDisplayValue);
		}
		PropVariantClear(&propvarValue);
	}
	return hr;
}

HRESULT EnumerateProperties(PCWSTR pszFilename)
{
	IPropertyStore* pps = NULL;

	// Call the helper to get the property store for the initialized item
	// Note that as long as you have the property store, you are keeping the file open
	// So always release it once you are done.

	HRESULT hr = GetPropertyStore(pszFilename, GPS_DEFAULT, &pps);
	if (SUCCEEDED(hr))
	{
		// Retrieve the number of properties stored in the item.
		DWORD cProperties = 0;
		hr = pps->GetCount(&cProperties);
		if (SUCCEEDED(hr))
		{
			for (DWORD i = 0; i < cProperties; i++)
			{
				// Get the property key at a given index.
				PROPERTYKEY key;
				hr = pps->GetAt(i, &key);
				if (SUCCEEDED(hr))
				{
					// Get the canonical name of the property
					PWSTR pszCanonicalName = NULL;
					hr = PSGetNameFromPropertyKey(key, &pszCanonicalName);
					if (SUCCEEDED(hr))
					{
						hr = PrintProperty(pps, key, pszCanonicalName);
						CoTaskMemFree(pszCanonicalName);
					}
				}
			}
		}
		pps->Release();
	}
	else
	{
		wprintf(L"Error %x: getting the propertystore for the item.\n", hr);
	}
	return hr;
}

void CMFCApplication2Dlg::OnCheck02()
{
	EnumerateProperties(_T("D:\\reseouch\\MFCApplication2\\test1.doc"));

	MessageBox(sMsg);
}

 

상세한 소스확인은 해당 깃허브를 참고해주세요

https://github.com/microsoft/Windows-classic-samples/blob/main/Samples/Win7Samples/winui/shell/appplatform/PropertyEdit/PropertyEdit.cpp

 

GitHub - microsoft/Windows-classic-samples: This repo contains samples that demonstrate the API used in Windows classic desktop

This repo contains samples that demonstrate the API used in Windows classic desktop applications. - GitHub - microsoft/Windows-classic-samples: This repo contains samples that demonstrate the API u...

github.com

 

반응형

댓글