Windows 탐색기에서 볼 수있는 C #의 확장 파일 속성 (예 : 설명, 비트 전송률, 액세스 한 날짜, 범주 등)을 읽고 쓰는 방법을 찾으려고합니다. 이 작업을 수행하는 방법에 대한 아이디어가 있습니까? 편집 : 주로 비디오 파일 (AVI / DIVX / ...)을 읽고 쓸 것입니다.
Windows 탐색기에서 볼 수있는 C #의 확장 파일 속성 (예 : 설명, 비트 전송률, 액세스 한 날짜, 범주 등)을 읽고 쓰는 방법을 찾으려고합니다. 이 작업을 수행하는 방법에 대한 아이디어가 있습니까? 편집 : 주로 비디오 파일 (AVI / DIVX / ...)을 읽고 쓸 것입니다.
답변:
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)}");
}
}
}
ID3 리더를위한 CodeProject 기사 가 있습니다 . 다른 속성에 대한 자세한 정보가 있는 kixtart.org 의 스레드 . 기본적으로, 당신은 호출 할 필요는 GetDetailsOf()
방법 상의 폴더 에 대한 셸 개체를 shell32.dll
.
프로젝트에 다음 NuGet 패키지를 추가합니다.
Microsoft.WindowsAPICodePack-Shell
MicrosoftMicrosoft.WindowsAPICodePack-Core
Microsoftusing 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();
중대한:
파일은 지정된 특정 소프트웨어에서 만든 유효한 파일이어야합니다. 모든 파일 유형에는 특정 확장 파일 속성이 있으며 모두 쓰기 가능한 것은 아닙니다.
데스크톱에서 파일을 마우스 오른쪽 버튼으로 클릭하고 속성을 편집 할 수없는 경우 코드에서도 파일을 편집 할 수 없습니다.
예:
Author
또는 Title
속성을 편집 할 수 없습니다 .그래서 몇 가지를 사용하십시오 try
catch
추가 항목 : MSDN : 속성 처리기 구현
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 컨트롤 및 자동화 에 대한 참조를 추가해야합니다 .
이 스레드에 감사드립니다! exe의 파일 버전을 알아 내고 싶을 때 도움이되었습니다. 그러나 확장 속성이라고하는 마지막 부분을 직접 파악해야했습니다.
Windows 탐색기에서 exe (또는 dll) 파일의 속성을 열면 버전 탭과 해당 파일의 확장 속성보기가 나타납니다. 나는 그 가치 중 하나에 접근하고 싶었다.
이에 대한 해결책은 속성 인덱서 FolderItem.ExtendedProperty이며 속성 이름에 모든 공백을 삭제하면 값을 얻을 수 있습니다. 예를 들어 파일 버전은 FileVersion이되며 거기에 있습니다.
이것이 다른 사람에게 도움이되기를 바랍니다.이 정보를이 스레드에 추가 할 것이라고 생각했습니다. 건배!
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);
}
Folder rFolder = shell.NameSpace(_rootPath);
. 참고로 Windows 8 OS를 사용하고 있습니다.
사용하다:
string propertyValue = GetExtendedFileProperty("c:\\temp\\FileNameYouWant.ext","PropertyYouWant");
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;
}
shell
모든 IShellDispatch
인터페이스 (1-6)로 캐스트 하고 멤버를 직접 호출 할 수 있습니다. Shell32.IShellDispatch ishell = (Shell32.IShellDispatch)shell; Shell32.Folder shellFolder = ishell.NameSpace(baseFolder);
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.
}
속성을 작성하려는 파일 유형이 무엇인지 모르겠지만 taglib-sharp 는이 모든 기능을 멋지게 포장 한 훌륭한 오픈 소스 태깅 라이브러리입니다. 대부분의 인기있는 미디어 파일 유형에 대한 지원이 많이 내장되어 있지만 거의 모든 파일에 대해 고급 태그 지정을 수행 할 수도 있습니다.
편집하다: taglib sharp에 대한 링크를 업데이트했습니다. 이전 링크는 더 이상 작동하지 않습니다.
편집 : kzu의 댓글에 따라 링크를 다시 한 번 업데이트했습니다.
다음은이 페이지에서 찾은 내용 과 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하는 것이 훨씬 더 나은 솔루션을 가