Accessing file extended properties in .NET

D

daveh551

My apologies for posting this twice. I meant to post in the C# group,
and posted in Visual C instead,so I'm reposting here:

Many types of files have a number of "extended properties" beyond the
basic file size, creation time, modified time, accessed time, etc.
For example (the one I am particularly interested in), image files
(jpg, etc.) have a dimensions (H x W in pixels) attribute, etc. These
attributes are readily available to the operating system - just hover
your mouse pointer over the thumbnail of an image file in the
directory, and it will come up with the dimensions as well as some
other properties.

I found the following link http://www.microsoft.com/technet/scriptcenter/guide/sas_fil_lunl.mspx...
related to the windows scripting engine in Windows 2000 that lists the
extended attributes that are stored. In the following code,
originally written in VB6 and upgraded to VB.NET, these properties can
be extracted:

Dim objShell as Object
Dim objFolder as Object
Dim strDimensions as Object

objShell = CreateObject("Shell.Application")
objFolder = objShell.Namespace("C:\temp"); ' path to the folder
containing the file
strDimensions = objFolder.GetDetailsOf(objFolder.ParseName
("test.jpg"), 26)

This code will set strDimensions to "3008 x 2000", or whatever the
dimensions of the file are.

Now, for my question: I have searched and searched and searched all
the help files and forums and other documentation I can think of for
some managed code (.NET) equivalent to this functionality without
resorting to creating an unmanaged object to invoke the shell
scripting engine, and I have not been successful. Surely something
this basic is available somehow?

Does anyone know how to do this in C#?

Thanks for your help.
 
R

rhaazy

My apologies for posting this twice. I meant to post in the C# group,
and posted in Visual C instead,so I'm reposting here:

Many types of files have a number of "extended properties" beyond the
basic file size, creation time, modified time, accessed time, etc.
For example (the one I am particularly interested in), image files
(jpg, etc.) have a dimensions (H x W in pixels) attribute, etc.  These
attributes are readily available to the operating system - just hover
your mouse pointer over the thumbnail of an image file in the
directory, and it will come up with the dimensions as well as some
other properties.

I found the following linkhttp://www.microsoft.com/technet/scriptcenter/guide/sas_fil_lunl.mspx...
related to the windows scripting engine in Windows 2000 that lists the
extended attributes that are stored.  In the following code,
originally written in VB6 and upgraded to VB.NET, these properties can
be extracted:

Dim objShell as Object
Dim objFolder as Object
Dim strDimensions as Object

objShell = CreateObject("Shell.Application")
objFolder = objShell.Namespace("C:\temp");   ' path to the folder
containing the file
strDimensions = objFolder.GetDetailsOf(objFolder.ParseName
("test.jpg"), 26)

This code will set strDimensions to "3008 x 2000", or whatever the
dimensions of the file are.

Now, for my question: I have searched and searched and searched all
the help files and forums and other documentation I can think of for
some managed code (.NET) equivalent to this functionality without
resorting to creating an unmanaged object to invoke the shell
scripting engine, and I have not been successful.  Surely something
this basic is available somehow?

Does anyone know how to do this in C#?

Thanks for your help.

Sample Code to Produce File Listing with Properties
The following code will populate a DataTable with a list of files and
their properties. The DataTable could be bound to a DataGrid or
another display control as desired. Be sure you've added the
appropriate reference to the dsofile.dll that exposes the file
properties. Because this is a COM-based DLL, COM Interop will be used
to interact with the DLL.

// Setup the data table
DataTable fileTable = new DataTable("Files");
DataRow fileRow;
fileTable.Columns.Add("Name");
fileTable.Columns.Add("Title");
fileTable.Columns.Add("Subject");
fileTable.Columns.Add("Description");

// Open the directory
DirectoryInfo docDir = new DirectoryInfo("C:\\My Documents\\");
if( !docDir.Exists )
{
docDir.Create();
}

// Add the document info into the table
DSOleFile.PropertyReader propReader =
new DSOleFile.PropertyReaderClass();
DSOleFile.DocumentProperties docProps;

foreach(FileInfo file in docDir.GetFiles())
{
try
{
fileRow = fileTable.NewRow();
docProps = propReader.GetDocumentProperties(file.FullName);
fileRow["Name"] = file.Name;
fileRow["Title"] = docProps.Title;
fileRow["Subject"] = docProps.Subject;
fileRow["Description"] = docProps.Comments;
fileTable.Rows.Add(fileRow);
}
catch( Exception exception )
{
Console.WriteLine("Error occurred: " + exception.Message);
}
}
propReader = null;
this.DocumentGrid.DataSource = fileTable;
this.DocumentGrid.DataBind();

// Force cleanup so dsofile doesn't keep files locked open
GC.Collect();
 
J

Jeff Johnson

Now, for my question: I have searched and searched and searched all
the help files and forums and other documentation I can think of for
some managed code (.NET) equivalent to this functionality without
resorting to creating an unmanaged object to invoke the shell
scripting engine, and I have not been successful. Surely something
this basic is available somehow?

Does anyone know how to do this in C#?

http://www.codeproject.com/KB/cs/ntfsstreams.aspx
 
I

Ignacio Machin ( .NET/ C# MVP )

My apologies for posting this twice. I meant to post in the C# group,
and posted in Visual C instead,so I'm reposting here:

Many types of files have a number of "extended properties" beyond the
basic file size, creation time, modified time, accessed time, etc.
For example (the one I am particularly interested in), image files
(jpg, etc.) have a dimensions (H x W in pixels) attribute, etc.  These
attributes are readily available to the operating system - just hover
your mouse pointer over the thumbnail of an image file in the
directory, and it will come up with the dimensions as well as some
other properties.

I found the following linkhttp://www.microsoft.com/technet/scriptcenter/guide/sas_fil_lunl.mspx...
related to the windows scripting engine in Windows 2000 that lists the
extended attributes that are stored.  In the following code,
originally written in VB6 and upgraded to VB.NET, these properties can
be extracted:

Dim objShell as Object
Dim objFolder as Object
Dim strDimensions as Object

objShell = CreateObject("Shell.Application")
objFolder = objShell.Namespace("C:\temp");   ' path to the folder
containing the file
strDimensions = objFolder.GetDetailsOf(objFolder.ParseName
("test.jpg"), 26)

This code will set strDimensions to "3008 x 2000", or whatever the
dimensions of the file are.

Now, for my question: I have searched and searched and searched all
the help files and forums and other documentation I can think of for
some managed code (.NET) equivalent to this functionality without
resorting to creating an unmanaged object to invoke the shell
scripting engine, and I have not been successful.  Surely something
this basic is available somehow?

Does anyone know how to do this in C#?

Thanks for your help.

Look into the archives for this group, this question has been answered
a number of time before, IIRC there is a class that get this in
sourceforge or in codeproject
 
D

daveh551

My apologies for posting this twice. I meant to post in the C# group,
and posted in Visual C instead,so I'm reposting here:
Many types of files have a number of "extended properties" beyond the
basic file size, creation time, modified time, accessed time, etc.
For example (the one I am particularly interested in), image files
(jpg, etc.) have a dimensions (H x W in pixels) attribute, etc.  These
attributes are readily available to the operating system - just hover
your mouse pointer over the thumbnail of an image file in the
directory, and it will come up with the dimensions as well as some
other properties.
I found the following linkhttp://www.microsoft.com/technet/scriptcenter/guide/sas_fil_lunl.mspx...
related to the windows scripting engine in Windows 2000 that lists the
extended attributes that are stored.  In the following code,
originally written in VB6 and upgraded to VB.NET, these properties can
be extracted:
Dim objShell as Object
Dim objFolder as Object
Dim strDimensions as Object
objShell = CreateObject("Shell.Application")
objFolder = objShell.Namespace("C:\temp");   ' path to the folder
containing the file
strDimensions = objFolder.GetDetailsOf(objFolder.ParseName
("test.jpg"), 26)
This code will set strDimensions to "3008 x 2000", or whatever the
dimensions of the file are.
Now, for my question: I have searched and searched and searched all
the help files and forums and other documentation I can think of for
some managed code (.NET) equivalent to this functionality without
resorting to creating an unmanaged object to invoke the shell
scripting engine, and I have not been successful.  Surely something
this basic is available somehow?
Does anyone know how to do this in C#?
Thanks for your help.

Sample Code to Produce File Listing with Properties
The following code will populate a DataTable with a list of files and
their properties. The DataTable could be bound to a DataGrid or
another display control as desired. Be sure you've added the
appropriate reference to the dsofile.dll that exposes the file
properties. Because this is a COM-based DLL, COM Interop will be used
to interact with the DLL.

// Setup the data table
DataTable fileTable = new DataTable("Files");
DataRow fileRow;
fileTable.Columns.Add("Name");
fileTable.Columns.Add("Title");
fileTable.Columns.Add("Subject");
fileTable.Columns.Add("Description");

// Open the directory
DirectoryInfo docDir = new DirectoryInfo("C:\\My Documents\\");
if( !docDir.Exists )
{
  docDir.Create();

}

// Add the document info into the table
DSOleFile.PropertyReader propReader =
       new DSOleFile.PropertyReaderClass();
DSOleFile.DocumentProperties docProps;

foreach(FileInfo file in docDir.GetFiles())
{
  try
  {
   fileRow = fileTable.NewRow();
   docProps = propReader.GetDocumentProperties(file.FullName);
   fileRow["Name"] = file.Name;
   fileRow["Title"] = docProps.Title;
   fileRow["Subject"] = docProps.Subject;
   fileRow["Description"] = docProps.Comments;
   fileTable.Rows.Add(fileRow);
  }
  catch( Exception exception )
  {
   Console.WriteLine("Error occurred: " + exception.Message);
  }}

propReader = null;
this.DocumentGrid.DataSource = fileTable;
this.DocumentGrid.DataBind();

// Force cleanup so dsofile doesn't keep files locked open
GC.Collect();

Thanks for responding. I appreciate the effort.

However, there are two problems.

First, using the dsofile.dll currently available for download from
Microsoft (http://support.microsoft.com/default.aspx?scid=kb;en-us;
224351), there is no DSOleFile object defined, and thus, not
DSOleFile.PropertyReader, so the supplied code will not build.

However, the demo project that Microsoft provided in the download did
build and run, but does not appear to be at all suitable for what I am
trying to do. It is designed for reading the extended properties such
as Author, Title, EditingTime, etc. that Microsoft Office components
add to a file. There is nothing that would appear to allow it to read
the properties of media files like images, video clips, audio files,
etc. Specifically, I'm looking for the pixel dimensions of an image
(jpg) file, and there is nothing there to allow to me to extract
those, and I could not see any way to extend it.
 
J

Jeff Johnson

That was a very interesting article, but I built his code and ran it
against a jpg file and it returned no alternate streams, so that won't
help in this case.

You can't count on this to work for everything. Office documents store their
properties inside them in OLE Document storage, not in streams. MP3s use ID3
tags, not streams. JPGs may used what are called EXIF tags, but I'm not
positive. Even if they don't, it's possible that Windows Explorer can report
a JPG's dimensions by simply examining the file and not because the data is
stored explicitly. So I guess you should tell us exactly what you're trying
to do.
 
R

rhaazy

You can't count on this to work for everything. Office documents store their
properties inside them in OLE Document storage, not in streams. MP3s use ID3
tags, not streams. JPGs may used what are called EXIF tags, but I'm not
positive. Even if they don't, it's possible that Windows Explorer can report
a JPG's dimensions by simply examining the file and not because the data is
stored explicitly. So I guess you should tell us exactly what you're trying
to do.

Try "Googling" for this using the keyword "metadata". You will find
the information you need.
 
D

daveh551

Look into the archives for this group, this question has been answered
a number of time before, IIRC there is a class that get this in
sourceforge or in codeproject

Ignacio,
I'm sure you are correct. I have just scrolled back through each of
over 50 entries in this group, and the question has been asked many,
many times. But I cannot find a single case where it was answered in
a relevant fashion. There are a few answers that say something like
"Use FileInfo" (which does not provide the info the user has
requested), and a few more that, like the responder above, reference
the DSOFile.dll, which provides some extended properties for MS Office
files such as Word or Excel. There were a few that were old and
referenced links that are no longer active.

If anyone can send me a link to something that actually answers my
question, I would really appreciate it.

This information (jpeg dimensions) is readily available to the os. WHY
does Microsoft make it so difficult to get to?
 
D

daveh551

You can't count on this to work for everything. Office documents store their
properties inside them in OLE Document storage, not in streams. MP3s use ID3
tags, not streams. JPGs may used what are called EXIF tags, but I'm not
positive. Even if they don't, it's possible that Windows Explorer can report
a JPG's dimensions by simply examining the file and not because the data is
stored explicitly. So I guess you should tell us exactly what you're trying
to do.

Exactly what I'm trying to do is write a function that, as quickly and
efficiently as possible, given a jpg file path, will return the pixel
dimensions:

struct size { int x, int y};
size GetDimensions(string jpgPath);

Actually, more specifically what I want is the aspect ratio. I want
to set the height and width parameters for an HTML <img> tag such that
the displayed image fits within the allotted space, but maintains the
aspect ratio of the original file.

I know I can do it by loading the file into some sort of image object
and getting the dimensions from the image, but I do not want to read
in the whole file, since I'm going to turn around and hand it off to
IIS which will then read it again.

And I don't believe that the OS is reading the JPEG file each time it
displays those attributes when you hover your mouse over the
thumbnail. I once thought they might be stored in the thumbs.db, but
I removed that and set options to keep it from being regenerated, and
the dimensions are still displayed.
 
J

Jeff Johnson

And I don't believe that the OS is reading the JPEG file each time it
displays those attributes when you hover your mouse over the
thumbnail.

I'm willing to bet that it does. I'm not a graphics expert, but given the
little bit I know about Windows BMP files, there's a structure at the very
beginning of the file that tells you things like dimensions, bit depths,
etc. You don't have to read the whole file to get this, just the first 100
bytes or whatever. I would think most other graphics formats would be
structured the same way. After all, if you don't put the information at the
beginning of the file, how are you suppoed to find it?!
 
D

daveh551

I'm willing to bet that it does. I'm not a graphics expert, but given the
little bit I know about Windows BMP files, there's a structure at the very
beginning of the file that tells you things like dimensions, bit depths,
etc. You don't have to read the whole file to get this, just the first 100
bytes or whatever. I would think most other graphics formats would be
structured the same way. After all, if you don't put the information at the
beginning of the file, how are you suppoed to find it?!

Semantics. Yes, it may actually be reading the first part of the
file. I meant that it's not loading the whole file into an image
structure the way some of the methods were suggesting in order to
extract the properties.

However it is getting it, the OS has a systematic algorithm built into
it for extracting these properties. Just right click on any jpeg file,
select properties, select the Summary tab, and click Advanced. All the
info is right there. Why is it so difficult to get to from a program?
Especially since there was a published API (the GetDetailsOf method
mentioned in the original post) that worked pre-.NET.
 
J

J.B. Moreno

daveh551 said:
This information (jpeg dimensions) is readily available to the os. WHY
does Microsoft make it so difficult to get to?

I don't know, and I've looked at other extended properties for other
purposes.

Given the specialized properties that you are interested in, perhaps
because it's not readily available to the OS? I.e. the OS does exactly
the same thing as an application would do, parse the file for the
information.

Here's a link to a blog with code (not C# or even .net) to do so:

<http://www.anttikupila.com/flash/getting-jpg-dimensions-with-as3-withou
t-loading-the-entire-file/>.

Why don't you translate that into C# and then post it back here?
 
I

Ignacio Machin ( .NET/ C# MVP )

Ignacio,
I'm sure you are correct.  I have just scrolled back through each of
over 50 entries in this group, and the question has been asked many,
many times.  But I cannot find a single case where it was answered in
a relevant fashion.  There are a few answers that say something like
"Use FileInfo"  (which does not provide the info the user has
requested), and a few more that, like the responder above, reference
the DSOFile.dll, which provides some extended properties for MS Office
files such as Word or Excel.  There were a few that were old and
referenced links that are no longer active.

If anyone can send me a link to something that actually answers my
question, I would really appreciate it.

This information (jpeg dimensions) is readily available to the os. WHY
does Microsoft make it so difficult to get to?

I'm not sure it's readily available. File Explorer might been opening
the file and check in the header the info. I doubt that all the jpegs
file in your hdd have extra metadata.
You would have to detect the file format and knows how to deal with
it.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top