'확장'파일 속성 읽기 / 쓰기 (C #)


104

Windows 탐색기에서 볼 수있는 C #의 확장 파일 속성 (예 : 설명, 비트 전송률, 액세스 한 날짜, 범주 등)을 읽고 쓰는 방법을 찾으려고합니다. 이 작업을 수행하는 방법에 대한 아이디어가 있습니까? 편집 : 주로 비디오 파일 (AVI / DIVX / ...)을 읽고 쓸 것입니다.


3
허용 된 답변은 확장 된 속성 을 설정하는 방법이 아닌 가져 오는 방법 만 보여주기 때문에이 질문에 대한 답은 명확 하지 않습니다 .
Dmitri Nesteruk

1
확장 속성을 설정하려면 stackoverflow.com/questions/5337683/…을
VoteCoffee

답변:


83

VB에 열광하지 않는 사람들을 위해 여기에 C #이 있습니다.

참조 대화 상자의 COM 탭에서 Microsoft Shell 컨트롤 및 자동화 에 대한 참조를 추가해야합니다 .

public static void Main(string[] args)
{
    List<string> arrHeaders = new List<string>();

    Shell32.Shell shell = new Shell32.Shell();
    Shell32.Folder objFolder;

    objFolder = shell.NameSpace(@"C:\temp\testprop");

    for( int i = 0; i < short.MaxValue; i++ )
    {
        string header = objFolder.GetDetailsOf(null, i);
        if (String.IsNullOrEmpty(header))
            break;
        arrHeaders.Add(header);
    }

    foreach(Shell32.FolderItem2 item in objFolder.Items())
    {
        for (int i = 0; i < arrHeaders.Count; i++)
        {
            Console.WriteLine(
              $"{i}\t{arrHeaders[i]}: {objFolder.GetDetailsOf(item, i)}");
        }
    }
}

3
이 값 중 하나를 어떻게 설정합니까? 예를 들어 .txt 파일의 작성자 또는 게시자. 나는 승리 7이고 이것을 사용했고 그것은 빈 저자와 출판사 및 282 개의 다른 속성을 보여줍니다
Vaibhav Garg

1
@Vainbhav-설정할 수 없습니다.
csharptest.net 2010

26
참조 대화 상자의 COM 탭에서 Microsoft Shell 컨트롤 및 자동화에 대한 참조를 추가해야합니다.
csharptest.net 2011

2
설정 방법은 다음 질문에서 더 잘 다룹니다. stackoverflow.com/questions/5337683/…
Nicolas Raoul

1
Windows 10에서는 프레임 속도, 프레임 높이, 너비 등을 제외한 52 개의 필드 만 반환합니다.
호치민 응웬


26

솔루션 2016

프로젝트에 다음 NuGet 패키지를 추가합니다.

  • Microsoft.WindowsAPICodePack-Shell Microsoft
  • Microsoft.WindowsAPICodePack-Core Microsoft

속성 읽기 및 쓰기

using Microsoft.WindowsAPICodePack.Shell;
using Microsoft.WindowsAPICodePack.Shell.PropertySystem;

string filePath = @"C:\temp\example.docx";
var file = ShellFile.FromFilePath(filePath);

// Read and Write:

string[] oldAuthors = file.Properties.System.Author.Value;
string oldTitle = file.Properties.System.Title.Value;

file.Properties.System.Author.Value = new string[] { "Author #1", "Author #2" };
file.Properties.System.Title.Value = "Example Title";

// Alternate way to Write:

ShellPropertyWriter propertyWriter =  file.Properties.GetPropertyWriter();
propertyWriter.WriteProperty(SystemProperties.System.Author, new string[] { "Author" });
propertyWriter.Close();

중대한:

파일은 지정된 특정 소프트웨어에서 만든 유효한 파일이어야합니다. 모든 파일 유형에는 특정 확장 파일 속성이 있으며 모두 쓰기 가능한 것은 아닙니다.

데스크톱에서 파일을 마우스 오른쪽 버튼으로 클릭하고 속성을 편집 할 수없는 경우 코드에서도 파일을 편집 할 수 없습니다.

예:

  • 바탕 화면에 txt 파일을 만들고 확장자를 docx로 바꿉니다. Author또는 Title속성을 편집 할 수 없습니다 .
  • Word로 열고 편집하고 저장하십시오. 이제 할 수 있습니다.

그래서 몇 가지를 사용하십시오 try catch

추가 항목 : MSDN : 속성 처리기 구현


Microsoft에서 이러한 이름의 패키지를 볼 수 없습니다
Jacob Brewer 2018

1
@JacobBrewer 실제로 "acdvorak"에 의해 업로드 된 입니다 : nuget.org/packages/Microsoft.WindowsAPICodePack-Shell . Visual Studio NuGet-Package-Manager에서는 "by Microsoft"로 표시됩니다. 비슷한 이름을 가진 다른 패키지는 포크이며 제대로 작동하거나 더 잘 작동 할 수도 있습니다. 나는 모르겠어 ...
마틴 슈나이더에게

25

VB.NET의이 샘플은 모든 확장 속성을 읽습니다.

Sub Main()
        Dim arrHeaders(35)

        Dim shell As New Shell32.Shell
        Dim objFolder As Shell32.Folder

        objFolder = shell.NameSpace("C:\tmp")

        For i = 0 To 34
            arrHeaders(i) = objFolder.GetDetailsOf(objFolder.Items, i)
        Next
        For Each strFileName In objfolder.Items
            For i = 0 To 34
                Console.WriteLine(i & vbTab & arrHeaders(i) & ": " & objfolder.GetDetailsOf(strFileName, i))
            Next
        Next

    End Sub

참조 대화 상자 의 COM 탭 에서 Microsoft Shell 컨트롤 및 자동화 에 대한 참조를 추가해야합니다 .


2
Windows 7 (적어도)에서는 arrHeaders의 크기를 280 개 이상으로 늘리고 많은 추가 메타 데이터를 다시 가져올 수 있다는 점에 주목할 가치가 있습니다. WTV 파일 (Windows 7 Media Center 녹화 TV 쇼)에서 메타 데이터를 가져 오는 방법을 찾고있을 때 이것을 발견했습니다.
Richard

1
i = 0 ~ 34 루프의 첫 번째는 i = 0 ~ Integer.MaxValue 여야합니다. 그런 다음 objFolder.GetDetailsOf (objFolder.Items, i)의 반환 값을 테스트합니다. null 또는 공백을 반환하면 모든 헤더가있는 것입니다.
Tim Murphy

@TimMurphy, 불행히도 맞지 않습니다 (적어도 Windows 10 또는 7에서는). 일부 헤더는 비어 있으므로 모든 색인을 반복해야합니다. (물론 수백만 개가 아니기 때문에 루프를 1,000 개로 제한 할 수 있습니다.)
skst

8

이 스레드에 감사드립니다! exe의 파일 버전을 알아 내고 싶을 때 도움이되었습니다. 그러나 확장 속성이라고하는 마지막 부분을 직접 파악해야했습니다.

Windows 탐색기에서 exe (또는 dll) 파일의 속성을 열면 버전 탭과 해당 파일의 확장 속성보기가 나타납니다. 나는 그 가치 중 하나에 접근하고 싶었다.

이에 대한 해결책은 속성 인덱서 FolderItem.ExtendedProperty이며 속성 이름에 모든 공백을 삭제하면 값을 얻을 수 있습니다. 예를 들어 파일 버전은 FileVersion이되며 거기에 있습니다.

이것이 다른 사람에게 도움이되기를 바랍니다.이 정보를이 스레드에 추가 할 것이라고 생각했습니다. 건배!


2
이것은 또한 당신의 코드가 (적어도 대부분) 영어가 아닌 기계에서 여전히 작동하도록 보장합니다.
Ed Norris

1
여기서 한 가지 작은 개선점은 FolderItem에 ExtendedProperty ()가 포함되어 있지 않습니다. 그러나 FolderItem2는 수행합니다.
Mixxiphoid

이 답변은 다른 답변보다 약간 간단합니다. 여기에서 작동하는 샘플 코드를 제공했습니다. stackoverflow.com/a/46648086/661933
nawfal

8

GetDetailsOf()방법-폴더의 항목에 대한 세부 정보를 검색합니다. 예를 들어 크기, 유형 또는 마지막 수정 시간입니다. 파일 속성은 Windows-OS버전 에 따라 다를 수 있습니다 .

List<string> arrHeaders = new List<string>();

 Shell shell = new ShellClass();
 Folder rFolder = shell.NameSpace(_rootPath);
 FolderItem rFiles = rFolder.ParseName(filename);

 for (int i = 0; i < short.MaxValue; i++)
 {
      string value = rFolder.GetDetailsOf(rFiles, i).Trim();
      arrHeaders.Add(value);
 }

위의 동일한 코드를 복사하여 사용했습니다. 하지만 여기 runime에서 COM 예외가 발생합니다.Folder rFolder = shell.NameSpace(_rootPath); . 참고로 Windows 8 OS를 사용하고 있습니다.
DonMax

1
그 오류는 무엇입니까? 올바른 버전의 Shell32.dll을 사용하고 있는지 확인하십시오. 이것을 확인하십시오.
RajeshKdev

1
위 링크에 +1. 제안한 링크가 제대로 작동합니다. 당신의 도움이 하나 더 필요합니다. 즉, 메타 데이터를 얻기 위해 단일 파일을 어떻게 전달할 수 있습니까 ?? 이후 폴더 만 전달을 허용합니다.
DonMax 2014 년

6
  • 이 스레드와 다른 곳에서 여러 솔루션을 살펴본 후 다음 코드가 함께 작성되었습니다. 이것은 단지 속성을 읽기위한 것입니다.
  • Shell32.FolderItem2.ExtendedProperty 함수가 작동하도록 할 수 없었습니다. 문자열 값을 가져와 해당 속성에 대한 올바른 값과 유형을 반환해야합니다 ... 이것은 항상 저에게 null이었고 개발자 참조 리소스는 매우 얇았습니다.
  • WindowsApiCodePack는 우리에게 아래의 코드를 제공하는 마이크로 소프트에 의해 포기 된 것으로 보인다.

사용하다:

string propertyValue = GetExtendedFileProperty("c:\\temp\\FileNameYouWant.ext","PropertyYouWant");
  1. 주어진 파일 및 속성 이름에 대한 문자열로 원하는 확장 속성의 값을 반환합니다.
  2. 지정된 속성을 찾을 때까지만 반복합니다. 일부 샘플 코드처럼 모든 속성이 검색 될 때까지 반복하지 않습니다.
  3. Windows Server 2008과 같은 Windows 버전에서 작동 합니다. Shell32 개체를 정상적으로 만들려고하면 " 'System .__ ComObject'유형의 COM 개체를 인터페이스 유형 'Shell32.Shell'로 캐스팅 할 수 없습니다." 라는 오류 메시지가 표시 됩니다.

    public static string GetExtendedFileProperty(string filePath, string propertyName)
    {
        string value = string.Empty;
        string baseFolder = Path.GetDirectoryName(filePath);
        string fileName = Path.GetFileName(filePath);
    
        //Method to load and execute the Shell object for Windows server 8 environment otherwise you get "Unable to cast COM object of type 'System.__ComObject' to interface type 'Shell32.Shell'"
        Type shellAppType = Type.GetTypeFromProgID("Shell.Application");
        Object shell = Activator.CreateInstance(shellAppType);
        Shell32.Folder shellFolder = (Shell32.Folder)shellAppType.InvokeMember("NameSpace", System.Reflection.BindingFlags.InvokeMethod, null, shell, new object[] { baseFolder });
    
        //Parsename will find the specific file I'm looking for in the Shell32.Folder object
        Shell32.FolderItem folderitem = shellFolder.ParseName(fileName);
        if (folderitem != null)
        {
            for (int i = 0; i < short.MaxValue; i++)
            {
                //Get the property name for property index i
                string property = shellFolder.GetDetailsOf(null, i);
    
                //Will be empty when all possible properties has been looped through, break out of loop
                if (String.IsNullOrEmpty(property)) break;
    
                //Skip to next property if this is not the specified property
                if (property != propertyName) continue;    
    
                //Read value of property
                value = shellFolder.GetDetailsOf(folderitem, i);
            }
        }
        //returns string.Empty if no value was found for the specified property
        return value;
    }

1
InvokeMember () 를 사용하는 대신 shell모든 IShellDispatch인터페이스 (1-6)로 캐스트 하고 멤버를 직접 호출 할 수 있습니다. Shell32.IShellDispatch ishell = (Shell32.IShellDispatch)shell; Shell32.Folder shellFolder = ishell.NameSpace(baseFolder);
skst

5

Jerker의 대답 은 조금 더 간단합니다. 다음 은 MS에서 작동하는 샘플 코드입니다 .

var folder = new Shell().NameSpace(folderPath);
foreach (FolderItem2 item in folder.Items())
{
    var company = item.ExtendedProperty("Company");
    var author = item.ExtendedProperty("Author");
    // Etc.
}

shell32를 정적으로 참조 할 수없는 경우 다음과 같이 동적으로 호출 할 수 있습니다.

var shellAppType = Type.GetTypeFromProgID("Shell.Application");
dynamic shellApp = Activator.CreateInstance(shellAppType);
var folder = shellApp.NameSpace(folderPath);
foreach (var item in folder.Items())
{
    var company = item.ExtendedProperty("Company");
    var author = item.ExtendedProperty("Author");
    // Etc.
}

1

속성을 작성하려는 파일 유형이 무엇인지 모르겠지만 taglib-sharp 는이 모든 기능을 멋지게 포장 한 훌륭한 오픈 소스 태깅 라이브러리입니다. 대부분의 인기있는 미디어 파일 유형에 대한 지원이 많이 내장되어 있지만 거의 모든 파일에 대해 고급 태그 지정을 수행 할 수도 있습니다.

편집하다: taglib sharp에 대한 링크를 업데이트했습니다. 이전 링크는 더 이상 작동하지 않습니다.

편집 : kzu의 댓글에 따라 링크를 다시 한 번 업데이트했습니다.


이것은 매우 흥미로워 보입니다. 주로 비디오 파일 (AVI, DIVX 등)을 살펴볼 것입니다. 포인터 주셔서 감사합니다
David Hayes

taglib-sharp 링크가 죽은 것 같습니다. :-(-위키의 ... developer.novell.com/wiki/index.php/TagLib_Sharp:_Examples ...가 해당 URL을 가리키는 것처럼 이상합니다
SteveC

감사합니다, SteveC, 내가이 두 링크를 올렸을 때 두 링크가 유효했고 어느 곳이 공식적인 장소인지 확신 할 수 없었습니다. novell이 지금이 lib를위한 올바른 사이트 인 것 같습니다.
mockobject

kzu를 알려 주셔서 감사합니다. 원래 답변의 링크도 github 위치를 가리 키도록 업데이트했습니다.
mockobject

1

다음은이 페이지에서 찾은 내용 과 shell32 객체 에 대한 도움말을 기반으로 한 확장 속성 읽기 (쓰기가 아님)에 대한 솔루션입니다. .

분명히 이것은 해킹입니다. 이 코드는 여전히 Windows 10에서 실행되지만 일부 빈 속성에 부딪 힐 것 같습니다. 이전 버전의 Windows는 다음을 사용해야합니다.

        var i = 0;
        while (true)
        {
            ...
            if (String.IsNullOrEmpty(header)) break;
            ...
            i++;

Windows 10에서는 읽을 속성이 약 320 개 있다고 가정하고 단순히 빈 항목을 건너 뜁니다.

    private Dictionary<string, string> GetExtendedProperties(string filePath)
    {
        var directory = Path.GetDirectoryName(filePath);
        var shell = new Shell32.Shell();
        var shellFolder = shell.NameSpace(directory);
        var fileName = Path.GetFileName(filePath);
        var folderitem = shellFolder.ParseName(fileName);
        var dictionary = new Dictionary<string, string>();
        var i = -1;
        while (++i < 320)
        {
            var header = shellFolder.GetDetailsOf(null, i);
            if (String.IsNullOrEmpty(header)) continue;
            var value = shellFolder.GetDetailsOf(folderitem, i);
            if (!dictionary.ContainsKey(header)) dictionary.Add(header, value);
            Console.WriteLine(header +": " + value);
        }
        Marshal.ReleaseComObject(shell);
        Marshal.ReleaseComObject(shellFolder);
        return dictionary;
    }

언급했듯이 Com 어셈블리 Interop.Shell32를 참조해야합니다.

STA 관련 예외가 발생하면 여기에서 해결책을 찾을 수 있습니다.

Shell32를 사용하여 파일 확장 속성을 가져올 때 예외

해당 속성 이름이 외부 시스템에서 어떤 것인지 알 수 없으며 사전에 액세스하기 위해 사용할 지역화 가능한 상수에 대한 정보를 찾을 수 없습니다. 또한 속성 대화 상자의 모든 속성이 반환 된 사전에 존재하는 것은 아닙니다.

BTW 이것은 매우 느리고 적어도 Windows 10에서는 검색 된 문자열의 날짜를 구문 분석하는 것이 어려울 수 있으므로 이것을 사용하는 것은 시작하는 것이 좋지 않은 것 같습니다.

Windows 10에서는 SystemPhotoProperties, SystemMusicProperties 등이 포함 된 Windows.Storage 라이브러리를 반드시 사용해야합니다. https://docs.microsoft.com/en-us/windows/uwp/files/quickstart-getting-file-properties

그리고 마지막으로, 나는 게시 가 사용하는 WindowsAPICodePack하는 것이 훨씬 더 나은 솔루션을

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.