Display pretty file icons in your ASP.NET applications with IconHandler

*************************************************
Update - 4/26/08:
IconHandler 2.0 released

**************************************************
Update - 1/20/2007:
Use the IconHandler in conjunction with the DirectoryListingModule to set up a nice-looking directory listing for your IIS website, or create a your own directory listing template.
**************************************************

Do you like file icons?  I do.  They make it pretty easy to visually digest file lists in Windows,  when you open a file system folder with explorer.

Displaying icons in your web application can also be pretty compelling (for example, to spruce up that boring directory listing page, or visually represent documents in your web app).  Wouldn't it be cool if you can write an ASP.NET control or page that can embed these icons on your custom directory listing view? 

Unfortunately, there is no easy way to get icons for files in the .NET framework, so you have to do a little interop with the Windows shell to get the icon for a file / file extension, and then figure out a way to serve it over the web as an image.  So, I wrote an ASP.NET image handler that serves the icon for an aritrary file or extension, that you can simply drop into your application to get these pretty icons for whatever purposes you need.

Here is an example:



The basic idea is:

  1. Make a request to geticon.axd?file=FILENAME
  2. Get back the icon as a PNG file that can be displayed in the browser

You can also specify the optional size querystring parameter to select between small and large icons, for example geticon.axd?file=.ppt&size=small will give you a small version of the icon above.

Download the IconHandler application that shows how to use the icon handler here. (NOTE: This download is not affiliated with Microsoft, and is not officially supported by Microsoft or myself).  This will work on any IIS version that supports ASP.NET 2.0 (IIS 5.1, IIS6, and IIS7).

Some interesting tid-bits about the handler:

  1. It uses P/Invoke interop to get the icon using the Shell32.dll's SHGetFileInfo API
  2. It supports doing lookup of both real files (in case they override the icons), or by file type (extension).
  3. It uses the CriticalHandle class to make sure the icon handles are disposed properly
  4. It provides support for caching the handle lookups, and client/proxy caching of the returned images for improved performance
  5. You can configure a number of settings for the handler in the <iconHandler> configuration section inside your web.config

In the next post, I will include the download of the spiced up directory browsing component for IIS, that uses the icon handler to provide a skinnable directory listing for IIS.  Here is an advanced preview:

Enjoy!  As soon as I get to it, and if there is interest, I will post the source code / interesting impementation details.

Published 11 January 07 05:07 by Mike Volodarsky

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# Bazile said on January 12, 2007 2:47 AM:
This IS really usefull handler. And would be very interseting to see the sources. Of ource they can be seen using Reflector but there will be no author comments.
# Rodrigo said on January 12, 2007 8:02 AM:
Very interesting!
# Adam said on January 12, 2007 9:34 AM:
Very cool. Looking forward to the source code/tutorial! ;)
# Kharik said on January 12, 2007 8:03 PM:
Great!!!
# snow said on January 15, 2007 5:38 AM:

Excelent!!! Waiting for source code... :)

# Jason said on January 19, 2007 9:46 PM:
Thanks for the great post. I am implementing a file list for a client at the moment :)
# Mike Volodarsky said on January 20, 2007 10:51 PM:

Score!  I had a feeling this was just what the doctor ordered for a lot of people :)

# Arthur Nugent said on January 22, 2007 6:00 PM:
Mike, Nice job I have a engineering directory with 50k files that this will spruce up nicely Thanks
# Martin Payne said on January 24, 2007 2:31 PM:
I am trying to download from mvolo.com but, for some reason, I am redirected to an image that (to put it politely) is telling me that I am trying to download it from elsewhere and I should be trying to download from mvolo.com?
# Mike Volodarsky said on January 24, 2007 5:52 PM:
Martin, you are running into the LeechGuard in action Smile. If something is stripping your referrer header, then the module thinks you are linking to the file directly and redirecting you to the scary clown leech url. I re-configured the module to allow direct access to the files. You will still get redirected if some other website links to the download files directly, which is exactly what I want :) Let me know if you still have issues downloading.
# Adam said on January 26, 2007 7:07 AM:

Dont suppose i could get a copy of the source code from you could i?

# Mike Volodarsky said on January 26, 2007 11:00 AM:

I'll have the source posted shortly ... Just need to clean it up a bit.

# Mark said on January 26, 2007 11:44 AM:
Mike, I assume that you do know that the referer header is OPTIONAL and no user-agent is required to send it. I know most do, but I'm just sayin'.
# Mike Volodarsky said on January 26, 2007 12:03 PM:

Sure I do :)  Check out the LeechGuard post for some discussion of that.

# Andy said on February 15, 2007 1:22 PM:
Okay I am very new at this web stuff so how do you use this within a dataview. I want to show the icon and not the file name? Thanks for any help!
# Mike Volodarsky said on February 16, 2007 8:37 AM:
Andy, please read up on asp.net page controls at http://quickstarts.asp.net/QuickStartv20/aspnet/Default.aspx. The sample template page shows how to use the file collection as a data source, from which you can use the data binding syntax inside a data bound control to bind to any field of the DirectoryListingEntry object or computed value based on it.
# Kevin said on February 20, 2007 1:22 PM:
OK, it's been a while since I've done any ASP.NET development so I apologize in advance if this is a stupid question, but where the heck did the "GetIcon.axd" file come from? All I had when I unzipped the folder where 2 dlls and a config file. Take pity on someone who's been doing Windows Form development for the past year and a half and tell me what I'm missing.
# Mike Volodarsky said on February 21, 2007 1:28 AM:

Kevin,

GetIcon.axd doesnt exist as a file - its a virtual handler mapping to the IconHandler type, which provides request processing for requests to "GetIcon.axd" urls (serving the icon you request).  This is the standard way to extend ASP.NET with custom handler functionality.

Look in the web.config for this mapping, in the <httpHandlers> section for IIS5/6 and <handlers> for IIS7.

Thanks,

Mike

# Mike Volodarsky said on February 21, 2007 1:41 AM:
I noticed a reference to IconHandler at http://telerikwatch.com/2007/01/add-windows-icons-to-your-web-app.html. They correctly mention that the IconHandler can only display the icons for extensions registered on the web server, so there will be cases where particular files like *.ppt (and other office extensions) may be missing. While there is no workaround directly, you can always install the IconHandler on your dev XP or Vista machine, use it to capture all the icon PNGs you need, and then just use them as static files on your webserver for icons. This way, you dont need to go back to square 1 and manually capture / draw your own icons.
# Jerry said on March 23, 2007 6:51 PM:
HELP!! :-) I can get this to work to save my life. I'm running Windows server 2003, IIS 6. Output of the two DLL files in the BIN folder and (for the sake of testing) replaced my original web.config file with the one provided. I get the following error: Parser Error Message: Could not load type Mvolo.ShellIcons.Web.ShellIconHandler from assembly System.Web, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a. Source Error: Line 9: Line 10: Line 11: Line 12: Line 13: Source File: C:\Inetpub\Walnut\web.config Line: 11 Walnut is the name of my root web folder. What am I doing wrong? Much thanks in advance! Jerry
# Mike Volodarsky said on March 24, 2007 6:05 PM:

Jerry,

ASP.NET is trying to load the ShellIconHandler type from the System.Web assembly, instead of the assembly that contians the type.  This could happen if you disabled loading of bin assemblies for your application.

Try adding the following to the <system.web> section of your web.config:

<compilation>

   <assemblies>

               <add assembly="*" />

   </assemblies>

</compilation>

# Ed said on April 9, 2007 5:20 AM:
Hi, I'm trying to get this to work on Vista x64, and getting the following error, any ideas? Exception Details: System.ComponentModel.Win32Exception: An attempt was made to reference a token that does not exist Stack Trace: [Win32Exception (0x80004005): An attempt was made to reference a token that does not exist] Mvolo.ShellIcons.ShellIcons.GetIconFromShell(String path, Boolean useExtension, Boolean largeIcon) +333 Mvolo.ShellIcons.Web.ShellIconHandler.ProcessRequest(HttpContext context) +1355 System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +610 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +177 Thanks, Ed
# Mike Volodarsky said on April 10, 2007 7:54 PM:

Hi Ed,

I havent tried this on the 64bit Vista, there may be a 64-bit specific bug that you are hitting.  Let me investigate and let you know if I find something.

Thanks,

Mike

# Bob said on April 16, 2007 11:17 AM:
Source Please!!!! :P
# Krtko said on June 4, 2007 1:31 AM:
Hi, sorry to disturb you, but I haven't seen any notice about license, or usage policy. Are there any restrictions? Thanks for reply.
# Scott Wojan said on June 4, 2007 5:19 PM:
Please O' Please post the source!!
# Partha said on June 5, 2007 4:56 AM:
I am not able to find out anything from this.....I download the files which consist of 3 files and i have added the dll in the project. Can u provide me the details code how to use this......
# Mike Volodarsky said on June 8, 2007 10:24 AM:

Partha,

Check out the directory browsing module post for one example on how to use it - basically, all you have to do is unzip the files into the root of your ASP.NET application, and you should be able to use the handler right away by making a request to it as shown above.

Thanks,

Mike

# Mike Volodarsky said on June 8, 2007 10:26 AM:

Krtko,

You can freely use the binaries for IconHandler here in any application you chose.  There is currently no source provided for it - when it is, I will add the license information.  I usually use the Microsoft Permissive License.

Thanks,

Mike

# Krtko said on June 13, 2007 11:47 PM:
Thank you very much, Mike.
# Riptide said on July 17, 2007 3:14 PM:

Suggest to add a sample cache mechanism.

# Mike Volodarsky said on July 17, 2007 5:23 PM:

Riptide,

The handler already provides two caching mechanisms: 1) caching the icon bitmap for an extension on the server, so subsequent requests for files with that extension dont have to call the OS for the icon, and 2) allowing the icon to be cached on the client browser.

Look in the web.config file in the sample for the configuration settings to control this behavior.

Thanks,

Mike

# midas said on August 11, 2007 6:43 AM:
when we can see the source?
# Bill said on October 27, 2007 7:52 AM:
I have a couple questions here... 1). Is there a way to display the contents of a directory that doesn't contain the files necessary to run the app, nor link back to the directory that contains the files for the app. 2). Is there any way to use a custom icon.dll that is separate from the one that windows uses? For example, i don't want people viewing the directory and seeing a Firefox icon on all html docs, however, I want to be able to see that when I browse them locally on the server in Windows file explorer. 3). If there's no way to be able to do question one, is there a way to exclude any files from being listed in the directory browser? For example, hidden files are shown, but I'd rather them not be. I don't want to not be able to view files by their extension either, for example, I don't want to see the Windows "thumbs.db" file for every folder, but at the same time, I want to be able to view a "mysql.db" file. Thanks a million!
# Mike Volodarsky said on October 27, 2007 9:50 PM:

Hi Bill,

Not sure about your #1 - can you clarify what you mean?

Re #2 and #3, they make excellent feature requests for the next version :) I have a few other ones, now just need to get the time to implement it ...

Thanks,

Mike

# Mike Volodarsky's ServerSide said on October 28, 2007 3:02 AM:

Over the past several year, I&#39;ve written quite a few modules for IIS7 / ASP.NET. Some of these were

# Bill said on October 28, 2007 3:17 AM:
Thanks for the reply. I guess to clarify my #1, what I meant to say was.. Is there a way for me to use your app, but not show the contents of the app itself, for example; the bin directory, web directory, dirlisting.aspx, or the web.config files? I'd like to be able to set it up so that I can view the contents of "/upload" and it be completely empty since nobody has uploaded any files to it. I don't want users to be able to browse the other stuff mentioned. Maybe I'm not 100% sure on how to set it up right, but if you can offer a suggestion, I'd be very thankful.
# Email filtering news and tools said on December 7, 2007 6:48 PM:

As you are looking for porn filtering articles and pages, be certain to tap into everyone of the sources available.

# MichaelOSS said on January 7, 2008 2:15 PM:
Having a hard time getting this working with my VB.NET code. Any suggestions?
<%# GetDocumentIcon(Container.DataItem) %>
Where GetDocumentIcon Function gets the extension and returns the icon BUT only if I have the gif for the icon.
# Mr Peds said on January 30, 2008 7:27 AM:
Hi there, Could you give us some step, by step process on how to enable this application? I am having a little bit of a hard time trying to enable it for a particular virtual directory I created...
# Clumpton said on February 8, 2008 3:06 AM:
I too am having trouble getting this to work on IIS6. Directory lister works fine, but no icons. ShellIcon dlls in the same "bin" as the directory lister. Trying direct access to using /geticon.axd?file=.txt just gives a 404. No errors that I can see elsewhere.
# Andrew Macdonald said on March 7, 2008 6:58 AM:

Hi,

I would just like to start by saying this is a great helper for those shell icons :)

I have implemented it in a solution I am creating, but I have been noticing a few unhandled exceptions appearing in the event log arising from the use of the handler.

without posting an entire exception trace to this post, below is an excerpt from one of them:

Exception information:

   Exception type: ArgumentException

   Exception message: Win32 handle that was passed to Icon is not valid or is the wrong type.

Request information:

   Request URL: http://localhost:49573/geticon.axd?file=.nvram&size=small

   Request path: /geticon.axd

   User host address: 127.0.0.1

   User: admin

   Is authenticated: True

   Authentication Type: Forms

Is this something that I’m not going to be able to work around, if so, is there a chance that you could release a version of the helper that swallows this specific exception (I know… really bad) so that end users don’t notice the issue ;)

Regards Andy

# Mike Volodarsky said on March 7, 2008 11:15 AM:

Andrew,

Thanks for letting me know. This shouldnt be happening at all - can you share the full exception stack, and repro steps that cause this to happen? You can email me directly (@microsoft.com).

Thanks,

Mike

# Rainer Engblom said on April 24, 2008 7:55 AM:
Hello, I stumbled upon this page while trying to find the reason for the same error message as mentioned above. I'm using a function that extracts the window file icon from a file name, and after a few thousand extractions, it always ends up with that same message. The call I use is hIcon = SHGetFileInfo(File, FILE_ATTRIBUTE_NORMAL, ref shinfo, (uint)Marshal.SizeOf(shinfo), SHGFI_ICON | SHGFI_USEFILEATTRIBUTES); and after that I return System.Drawing.Icon.FromHandle(shinfo.hIcon); and the execution seems to halt on the line "Bitmap dImg = docIcon.ToBitmap();" where docIcon is the extracted Icon. The amount of iterations before error is always the same for same file type, but different for different file types.
# Mike Volodarsky said on April 25, 2008 2:24 AM:

Hi Adam, Rainer,

SHGetFileInfo seems to have a limit on the number of CGI+ icon handles it can have open. After a certain number (around 3000 in one of my tests), it just returns an invalid handle of 0, without indicating failure.

To avoid this, make sure to close the handles when you are done with them. For example, the IconHandler implementation creates a Bitmap over the handle and disposes of the handle immediately.

You can call into the Mvolo.ShellIcons.ShellIcons class to get the icon wrapped in a CriticalHandle to save you the trouble of implementing it (which you should Dispose() right after getting it). It's in the ShellIcons.dll included with IconHandler.

Adam, if you are seeing this exception, try:
enableServerCaching="true"
useExtensionOnly="true"
Passing extensions to the handler (no full file names)

This should reduce the number of handles that are ever open at any given time.

I have v2.0 coming in the next few days with an improvement that should help avoid this issue.

Thanks,

Mike

# MVolo's Blog said on April 27, 2008 2:57 AM:

Since its release, IconHandler has been a pretty popular module (on its own and with the custom DirectoryListingModule

# Mike Volodarsky said on April 27, 2008 3:01 AM:

The new version of IconHandler is out at http://mvolo.com/blogs/serverside/archive/2008/04/27/IconHandler-2.0-File-icons-in-ASP.NET-applications.aspx.

By the way, you can use the included ShellIcons class in ShellIcons.dll to get icons from the OS, without having to implement the p/invoke goo yourself. It's nice and wrapped in a CriticalHandle too for all your memory leak needs :)

Thanks,

Mike

# Rainer Engblom said on April 28, 2008 6:04 AM:
Yes, thank you. I use the DestroyIcon from user32.dll and it seems to do the job.
# turkey said on July 30, 2008 1:16 PM:
You can call into the Mvolo.ShellIcons.ShellIcons class to get the icon wrapped in a CriticalHandle to save you the trouble of implementing it (which you should Dispose() right after getting it). It's in the ShellIcons.dll included with IconHandler.
# Sasha said on September 11, 2008 10:08 AM:
Hello Mike, i guess my question same as Bill's (see October post). I'd like to expose some of the folders on windows server via web, but default sorting of the file and display is pretty rubbish. The example you show means that it displays the content of the folder where your application is. The question is how can i use this look and fill on the other @web enabled@ folders. is there some kind of template that can be applied ? thanks in advance
# Mike Volodarsky said on September 12, 2008 1:59 AM:

Hi Sasha,

You are asking for the "virtual" directory listing. Its a v2.0 feature that I have to add to the module ...

I've been busy with other things lately so havent gotten a chance to make several of these updates I promised - keep bugging me and I will do it.

Sorry for the lame answer :(

Mike

# Darren Lim said on October 15, 2008 2:59 PM:
Hello Mike, I've been researching this error "Loading this assembly would produce a different grant set from other instances. (Exception from HRESULT: 0x80131401)" and found this post "http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=285171" which references the ShellIconHandler". Is there any validity to this post. I am using the shellIconHandler and do receive this error sporadically when the site is updated. Thanks, Darren

Leave a Comment

(required) 
(optional)
(required) 
Enter the code you see below


About Mike Volodarsky

For the past 5 years, I was the core Program Manager for Microsoft ASP.NET 2.0 and IIS 7.0 products. I drove the design and development of the IIS 7.0 web server core, the IIS FastCGI support, the AppCmd command line tool, the ASP.NET Integrated pipeline, and other special projects around server security, performance, and scalability. Now, I am working on my own on cutting edge web server tech on top of the Microsoft IIS platform, and continue blogging about it here.

About me



For the past 5 years, I was the core server Program Manager for the IIS 7.0 and ASP.NET 2.0 products at Microsoft.
Now, I work on advanced web server tech using IIS 7.0, .NET, and Windows Server 2008 and write about it in this blog.

View Michael Volodarsky's profile on LinkedIn

Writings



TechNet Magazine
>Top 10 Performance Improvements in IIS 7.0

MSDN Magazine
>IIS 7.0: Build Web Server Solutions with End-To-End Extensibility
>IIS 7.0: Enhance Your Apps with the Integrated ASP.NET Pipeline
>IIS 7.0: Explore The Web Server For Windows Vista And Beyond
>Design and Deploy Secure Web Apps with ASP.NET 2.0 and IIS 6.0
>Fast, Scalable, and Secure Session State Management for Your Web Applications


Tools and Modules

LeechGuard
IconHandler 2.0
DirectoryListing
HttpRedirection
IIS Auth for Wordpress
iisschema.exe
PortCheck.exe v2.0

Popular Posts

- ASP.NET 2.0 Breaking Changes on IIS 7.0
- Develop IIS7 modules and handlers with .NET
- Troubleshoot IIS7 errors like a pro
- Troubleshooting 503 / "service unavailable" errors
- Troubleshooting "server not found" errors
- Create IIS7 sites, applications, and virtual directories
- Run Ruby on Rails with IIS FastCGI
- VS Debugging of ASP.NET applications on Windows Vista
- Stop hot-linking with IIS and ASP.NET

Tags

Search

Go

This Blog

Archives

Good IIS Blogs

Disclaimer

These postings are provided as is with no warranties, and confer no rights. The views expressed in this blog are entirely my own.

Syndication