'Genişletilmiş' dosya özelliklerini okuyun / yazın (C #)


104

Windows gezginde görebileceğiniz C # örn. Yorum, Bit Hızı, Erişim Tarihi, Kategori vb. Genişletilmiş dosya özelliklerini nasıl okuyacağımı / yazacağımı bulmaya çalışıyorum. Bunun nasıl yapıldığına dağir fikri olan? DÜZENLEME: Esas olarak video dosyalarını okuyacağım / yazacağım (AVI / DIVX / ...)


3
Bu soru açıkça edilir değil genişletilmiş özelliklerini almak için nasıl ve kabul cevap sadece gösterileri beri cevap bunları ayarlamak için değil nasıl .
Dmitri Nesteruk

1
Genişletilmiş özellikleri ayarlamak için stackoverflow.com/questions/5337683/… sayfasına
VoteCoffee

Yanıtlar:


83

VB konusunda deli olmayanlar için, burada c #:

Referanslar iletişim kutusunun COM sekmesinden Microsoft Kabuk Kontrolleri ve Otomasyonuna bir referans eklemeniz gerektiğini unutmayın .

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
bu değerlerden biri nasıl belirlenir? örneğin .txt dosyası için Yazar veya yayıncı. Ben 7 kazandım ve bunu kullandım ve boş bir yazar ve yayıncı ve 282 diğer mülk gösteriyor
Vaibhav Garg

1
@Vainbhav - Bunları ayarlayamazsınız.
csharptest.net

26
Referanslar iletişim kutusunun COM sekmesinden Microsoft Kabuk Kontrolleri ve Otomasyonuna bir referans eklemeniz gerekir.
csharptest.net

2
Bunları nasıl ayarlayacağınız bu soruda daha iyi ele
alınmaktadır

1
Windows 10'da yalnızca Kare hızı, Çerçeve Yüksekliği, Genişlik, .... dahil olmayan 52 alan döndürür.
Minh Nguyen


26

Çözüm 2016

Projenize aşağıdaki NuGet paketlerini ekleyin:

  • Microsoft.WindowsAPICodePack-Shell Microsoft tarafından
  • Microsoft.WindowsAPICodePack-Core Microsoft tarafından

Özellikleri Oku ve Yaz

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();

Önemli:

Dosya, belirli bir atanmış yazılım tarafından oluşturulmuş geçerli bir dosya olmalıdır. Her dosya türünün belirli genişletilmiş dosya özellikleri vardır ve hepsi yazılabilir değildir.

Masaüstünde bir dosyaya sağ tıklarsanız ve bir özelliği düzenleyemezseniz, onu kodda da düzenleyemezsiniz.

Misal:

  • Masaüstünde txt dosyası oluşturun, uzantısını docx olarak yeniden adlandırın. Onun Authorveya Titleözelliğini düzenleyemezsiniz .
  • Word ile açın, düzenleyin ve kaydedin. Şimdi yapabilirsin.

Bu yüzden biraz kullandığınızdan emin olun try catch

Diğer Konu: MSDN: Mülk İşleyicilerini Uygulama


Microsoft'tan bu isimlere sahip herhangi bir paket görmüyorum
Jacob Brewer

1
@JacobBrewer Aslında "acdvorak" tarafından yüklenen: nuget.org/packages/Microsoft.WindowsAPICodePack-Shell . Visual Studio NuGet-Package-Manager'da "Microsoft tarafından" olarak gösterilir. Benzer adlara sahip diğer paketler onun çatallarıdır ve aynı zamanda düzgün ve hatta daha iyi çalışabilir. Bilmiyorum ...
Martin Schneider

25

VB.NET'teki bu örnek, tüm genişletilmiş özellikleri okur:

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

Sen bir başvuru eklemek zorunda Microsoft Shell Kontrolleri ve Otomasyon gelen COM sekmesine Referansları iletişim.


2
Windows 7'de (en azından) arrHeader'ların boyutunu 280'in biraz üzerine çıkarabileceğinizi ve bol miktarda ek meta-veriyi geri alabileceğinizi belirtmek gerekir. Bunu, bir WTV dosyasından (Windows 7 Media Center kaydedilmiş televizyon programı) meta veri almanın bir yolunu ararken buldum.
Richard

1
İ = 0 - 34 arası döngü için ilki, i = 0 - Tamsayı.MaxValue için olmalıdır. Ardından objFolder.GetDetailsOf (objFolder.Items, i) 'nin dönüş değerini test edin. Boş veya boşluk döndürürse, tüm başlıklara sahipsiniz demektir.
Tim Murphy

@TimMurphy, maalesef bu doğru değil (en azından Windows 10 veya 7'de). Bazı başlıklar boştur, bu nedenle tüm dizinleri gözden geçirmeniz gerekir. (Elbette, milyonlarcası olmadığı için döngüyü 1.000 ile sınırlayabilirsiniz.)
2018

8

Bu konu için teşekkürler arkadaşlar! Bir exe'nin dosya sürümünü bulmak istediğimde bana yardımcı oldu. Ancak, Genişletilmiş Özellikler denen şeyin son kısmını kendim bulmam gerekiyordu.

Windows Gezgini'nde bir exe (veya dll) dosyasının özelliklerini açarsanız, bir Sürüm sekmesi ve bu dosyanın Genişletilmiş Özelliklerinin bir görünümünü elde edersiniz. Bu değerlerden birine erişmek istedim.

Bunun çözümü, özellik dizinleyici FolderItem.ExtendedProperty'dir ve özelliğin adındaki tüm boşlukları bırakırsanız, değeri alırsınız. Örneğin, Dosya Sürümü FileVersion'a gider ve işte orada.

Umarım bu başka birine yardımcı olur, sadece bu bilgiyi bu konuya ekleyeceğimi düşündüm. Şerefe!


2
Bu aynı zamanda kodunuzun (en azından çoğunlukla) İngilizce olmayan makinelerde çalışmasını sağlar.
Ed Norris

1
Buradaki küçük bir gelişme, FolderItem ExtendedProperty () içermiyor. FolderItem2 bunu yapar.
Mixxiphoid

Bu cevap diğerlerinden biraz daha basit. Burada çalışan örnek kodu
verdim

8

GetDetailsOf()Yöntem - Bir klasördeki bir öğenin ayrıntılarını alır. Örneğin, boyutu, türü veya son değiştirilme zamanı. Dosya Özellikleri Windows-OSsürüme göre değişebilir .

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);
 }

Yukarıdaki aynı kodu kopyaladım ve kullandım. Ancak, burada çalışma zamanında COM istisnası alıyorum Folder rFolder = shell.NameSpace(_rootPath);. Bilginize, Windows 8 işletim sistemi kullanıyorum.
DonMax

1
Bu hata nedir? Shell32.dll'nin doğru sürümünü kullandığınızdan emin olun. Bunu kontrol et belki Yararlı
RajeshKdev

1
Yukarıdaki bağlantı için +1. Önerdiğiniz bağlantı düzgün çalışıyor. Senden bir yardıma daha ihtiyacım var. yani, meta verileri almak için tek dosyayı nasıl iletebilirim? çünkü yalnızca klasörü geçirmeyi kabul eder.
DonMax

6
  • Bu iş parçacığında ve başka yerlerde bir dizi çözüme baktıktan sonra aşağıdaki kod bir araya getirildi. Bu sadece bir mülkü okumak içindir.
  • Shell32.FolderItem2.ExtendedProperty işlevinin çalışmasını sağlayamadım, bir dize değeri alması ve bu özellik için doğru değeri ve türü döndürmesi gerekiyor ... bu benim için her zaman boştu ve geliştirici referans kaynakları çok zayıftı.
  • WindowsApiCodePack bize aşağıdaki kodu getiren Microsoft tarafından terk edilmiş gibi görünüyor.

Kullanım:

string propertyValue = GetExtendedFileProperty("c:\\temp\\FileNameYouWant.ext","PropertyYouWant");
  1. Size verilen dosya ve özellik adı için bir dize olarak istediğiniz genişletilmiş özelliğin değerini döndürür.
  2. Yalnızca belirtilen özelliği bulana kadar döngüler - bazı örnek kodlar gibi tüm özellikler keşfedilene kadar değil
  3. Windows server 2008 gibi Windows sürümlerinde çalışacak ve sadece Shell32 Nesnesini normal olarak yaratmaya çalışıyorsanız, "'System .__ ComObject' tipinde COM nesnesi 'Shell32.Shell' arayüz tipine dönüştürülemiyor" hatası alacaksınız.

    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 () kullanmak yerine shell, IShellDispatcharabirimlerden (1-6) herhangi birine çevrim yapabileceğinizi ve üyeyi doğrudan arayabileceğinizi unutmayın. Shell32.IShellDispatch ishell = (Shell32.IShellDispatch)shell; Shell32.Folder shellFolder = ishell.NameSpace(baseFolder);
2018

5

Jerker'in cevabı biraz daha basit. İşte MS'ten çalışan örnek kod :

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

Shell32'ye statik olarak başvuramayanlar için, bunu dinamik olarak şu şekilde çalıştırabilirsiniz:

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

Hangi tür dosyalar için özellikleri yazmaya çalıştığınızdan emin değilim, ancak taglib-sharp , tüm bu işlevselliği güzelce tamamlayan mükemmel bir açık kaynaklı etiketleme kitaplığıdır. Popüler medya dosyası türlerinin çoğu için çok sayıda yerleşik desteğe sahiptir, ancak aynı zamanda hemen hemen her dosyayla daha gelişmiş etiketleme yapmanıza olanak tanır.

DÜZENLEME: taglib sharp bağlantısını güncelledim. Eski bağlantı artık çalışmıyordu.

DÜZENLE: Bağlantı, kzu'nun yorumuna göre bir kez daha güncellendi.


Bu çok ilginç görünüyor, esas olarak video dosyalarına (AVI, DIVX vb.) Bakacağım. İşaretçi için teşekkürler
David Hayes

Taglib keskin bağlantı ölü gibi görünüyor :-( - bu ... developer.novell.com/wiki/index.php/TagLib_Sharp:_Examples ... adresindeki wiki kadar garip ... bu URL'yi gösteriyor
SteveC

Teşekkürler SteveC, bunu gönderdiğimde her iki bağlantı da geçerliydi ve gideceğim resmi yerin hangisi olduğundan emin değildim, görünüşe göre bu kitaplık için şu anda başvurulacak doğru site novell.
mockobject

Uyarılar için teşekkürler kzu, orijinal cevabımdaki bağlantıyı github konumunu da gösterecek şekilde güncelledim.
mockobject

1

Burada, bu sayfada ve shell32 nesneleriyle ilgili yardımda bulduğuma dayalı olarak genişletilmiş özellikleri okumak - yazmak için bir çözüm var .

Açık olmak gerekirse bu bir hack. Görünüşe göre bu kod hala Windows 10'da çalışacak, ancak bazı boş özelliklere isabet edecek. Windows'un önceki sürümü şunları kullanmalıdır:

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

Windows 10'da, boş girişleri okumak ve atlamak için yaklaşık 320 özellik olduğunu varsayıyoruz:

    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;
    }

Belirtildiği gibi, Interop.Shell32 Com derlemesine başvurmanız gerekir.

STA ile ilgili bir istisna alırsanız, çözümü burada bulacaksınız:

Dosya genişletilmiş özelliklerini almak için Shell32 kullanıldığında istisna

Yabancı bir sistemde bu özellik adlarının nasıl olacağı hakkında hiçbir fikrim yok ve sözlüğe erişmek için hangi yerelleştirilebilir sabitlerin kullanılacağı hakkında bilgi bulamadım. Ayrıca, Özellikler iletişim kutusundaki tüm özelliklerin döndürülen sözlükte bulunmadığını da buldum.

BTW bu son derece yavaştır ve - en azından Windows 10'da - alınan dizedeki tarihleri ​​ayrıştırmak zor olabilir, bu yüzden bunu kullanmak kötü bir fikir gibi görünüyor.

Windows 10'da SystemPhotoProperties, SystemMusicProperties vb. İçeren Windows.Storage kitaplığını kesinlikle kullanmalısınız. Https://docs.microsoft.com/en-us/windows/uwp/files/quickstart-getting-file-properties

Ve son olarak, orada WindowsAPICodePack kullanan çok daha iyi bir çözüm yayınladım

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.