50

I need to set the Company field value for some Word/PDF documents. I am talking about the extended file properties (summary/author/title, etc.) you see under File Properties.

I know how to get them (by using shell32.dll class library). I assumed that I could also set them with the same class library, but it seems like writing extended properties is a little bit more difficult and shell32.dll doesn't allow that.

I found something about taglib-sharp, which seems to have an option to set extended properties, but I don't really understand how it works.

alex
  • 6,818
  • 9
  • 52
  • 103
andree
  • 3,084
  • 9
  • 34
  • 42
  • 1
    I suspect for simple files they're in an alternate NTFS stream, [e.g. this one](http://msdn.microsoft.com/en-us/library/ff469239%28v=PROT.10%29.aspx) but for .docs they'd actually be a property of the doc file itself. I think taglib-sharp is just for mp3 files. There's probably a COM object that's used by Explorer to parse these that you can automate? – Rup Mar 17 '11 at 10:59
  • I cheked out tablib and it is for mp3 only. Maybe give me a clue about COm object, because I dont really understand. I'm a beginner and seem like I'm trying to get something thats over my head. – andree Mar 17 '11 at 11:06
  • @andree - Thanks for sharing your answer. I was working on similar task and did found that using Shell32.dll I can get properties but was not able to set them. Your answer really helped me. – Nikhil Chavan Jul 14 '15 at 12:15
  • Does this answer your question? [Read/Write 'Extended' file properties (C#)](https://stackoverflow.com/questions/220097/read-write-extended-file-properties-c) – Bruno Brant May 24 '20 at 18:33

4 Answers4

72

Add following NuGet packages to your project:

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

Read and Write Properties

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

Important:

The file must be a valid one, created by the specific assigned software. Every file type has specific extended file properties and not all of them are writable.

If you right-click a file on desktop and cannot edit a property, you wont be able to edit it in code too.

Example:

  • Create txt file on desktop, rename its extension to docx. You can't edit its Author or Title property.
  • Open it with Word, edit and save it. Now you can.

So just make sure to use some try catch

Further Topic: MS Docs: Implementing Property Handlers

Community
  • 1
  • 1
Martin Schneider
  • 14,263
  • 7
  • 55
  • 58
  • 2
    Need more +1's for this answer. Can't be having it hanging around at the bottom. Not only is it the best answer for the OP, but also `WindowsAPICodePack` is just awesome. – u8it Jul 07 '16 at 21:22
  • Can I add my custom properties? – Shimmy Weitzhandler Oct 26 '17 at 12:56
  • So the properties (and their read/write -ability) must be determined by the definition of the file extension. If so then where is this at? – ThomasRones Aug 03 '18 at 12:15
  • 2
    For some reason, `ShellPropertyWriter` seems to not save the changes _occasionally_. Changing the value directly [as shown in this answer](https://stackoverflow.com/a/51188687/4934172) seems to work better for me. – 41686d6564 stands w. Palestine Aug 08 '18 at 02:01
  • I switched to this as accepted, time has moved on since my question was asked and right now this seems like the way to go. – andree Aug 25 '18 at 16:47
  • Man, I owe you a beer. I've been banging my head trying to figure out how to change the Media Created (DateEncoded) property of video files using PowerShell (not as easy modifying metadata properties in PS) but just wrote a quick and easy C# script using this information. Thank you!!! – Sina Nov 16 '18 at 20:21
  • 1
    Can you suggest a .net core solution? – Aaron Hudon Feb 06 '20 at 00:42
  • 1
    This works with .NET Core now. See https://stackoverflow.com/questions/65271816/what-is-the-net-5-way-of-working-with-the-windows-shell – Elliveny Aug 28 '22 at 10:03
  • So this doesn't work for an ASP.NET Core app? because it doesn't support the *-windows target? is this correct? – Marcel Jul 27 '23 at 10:12
25

Ok here is answer to my own question, since I wasn't really able to find my answer in this forum, it could be useful for others. Solution is to use dsofile.dll and OleDocumentPropertiesClass. Here is MS article about dsofile.dll - Link In this link, you can download dsofile.dll with some other files. But most probably, just like I did, you will face some weird problems that are hard to find a solution for.

1) After intalling dsofile.dll, you will need to register the class: oped cmd and navigate to c:\dsofile of to directory, where you have extracted your downloaded dsofile.dll. After that - write line regsvr32 dsofile.dll. You should get a messagebox saying that registeration was succesful. If not, most propably you don't have admin rights. You are going to need admin rights in case you want this to work.

2) After trying to use this class in your program, if you are using .NET 4.0 it is possible, that you will see error saying something like "class cannot be embedded ..." Well, for that, right click on dsofile in references list, properties -> embed interop files -> set to FALSE.

3) How to use:

    //creates new class of oledocumentproperties
    var doc = new OleDocumentPropertiesClass();

    //open your selected file
    doc.Open(pathToFile, false, dsoFileOpenOptions.dsoOptionDefault);

    //you can set properties with summaryproperties.nameOfProperty = value; for example
    doc.SummaryProperties.Company = "lol";
    doc.SummaryProperties.Author = "me";

    //after making changes, you need to use this line to save them
    doc.Save();
AnthonyLambert
  • 8,768
  • 4
  • 37
  • 72
andree
  • 3,084
  • 9
  • 34
  • 42
  • Also 1 more possible problem - when trying to write docs which are created with 64-bit office. – andree Mar 21 '11 at 07:00
  • I have office 64-bit and it works great. I haven't experienced any problems as of yet. If you don't mind, which Office version are ya running? I've got Home & Student –  Mar 21 '11 at 07:49
  • I have Professional 64-bit. And it doen't work definetely, while the same code works for 32-bit professional. Seems that there could be problems with some specific 64-bit versions, since the dsofile.dll was written some time ago (2007 I guess) so it might not be ready for some new versions of files. Also found this problem in other forums. To be specific - it doesn't set properties to .doc files, if created in 64-bit pro, but for .docx files it also crashed, showing that file is not an OLE document. – andree Mar 21 '11 at 10:08
  • That's strange, if that's the case, then it should be giving me problems too, i think. –  Mar 21 '11 at 14:25
  • 1
    Does that work for MS Word files only? MS Office files only? What about PDF files which you mentioned in your question? – Nicolas Raoul Nov 01 '12 at 05:52
  • 3
    If I remember correctly - this is only for Office files. For PDFs there are other libraries, which provide this functionality. – andree Nov 01 '12 at 10:35
  • As of 2016, I'd recommend the answer from @MA-Maddin below. – u8it Jul 07 '16 at 21:24
  • i'm unable to find dsofile.dll to download on microsoft.com – johny why Aug 18 '21 at 17:23
  • @u8it MA-Maddin's answer seems gone. – johny why Aug 18 '21 at 17:25
  • 1
    @johnywhy It's now the accepted and top rated answer here: https://stackoverflow.com/a/37987288/3546415 ("MA-Maddin" changed his name to "Martin Schneider") – u8it Aug 19 '21 at 02:11
8

Windows Explorer (using shell32.dll) is able to display the extended properties because it understands a lot of different file formats and can parse these. However, to set an extended property you probably need a file format specific library. E.g. to set the author of an MP3 file file is very different compared to setting the author of an Office document. (Actually Windows Explorer allows you to set some extended properties on Office documents.)

The taglib-sharp only works with media files and is most likely not able to set extended properties of any other type of file.

What you need is a library or a tool you can automate to modify PDF files. You can try to google pdf sdk. If you also need to work with Word files you can use COM automation to automate Word. Depending on the Word file format used you may also be able to work directly with the file without having Word installed (XML being much easier than the old binary "streams" format).

Martin Liversage
  • 104,481
  • 22
  • 209
  • 256
  • 1
    But I'd be very surprised if it understood the file formats itself - I'd expect there'd be something under HKCU for the file extension or file data it references that names a COM object that implements a common interface and does the parsing, so that third-parties can write their own and extend the set of file types supported. (But I can't find this.) But yes, may be easier to just get tools to modify PDFs and DOCs. – Rup Mar 17 '11 at 11:11
2

To set properties, you could utilize Windows' Property System. It provides an interface for accessing the "Property Store Cache" (IPropertyStore) where you can read/set any file's properties (regardless of the format), and add your own custom properties (the c library propkey.h has a comprehensive list of all available properties; you can also find these using prop.exe). This is essentially creating a Property Handler that must be later registered to your file extension. It is officially unsupported in managed code, so you might either want to write your own wrapper or use c++ (since this is a c# tagged question).

If you're specifically asking for media properties, check out metadata handlers, which are essentially codecs that extract your properties from the file and also called by explorer by default if you register them correctly.

Abdo Salem
  • 51
  • 8