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.

55 Comments

  1. Anonymous

    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.

  2. Anonymous

    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?

  3. Mike Volodarsky

    Martin, you are running into the LeechGuard in action [:)]. 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.

  4. Anonymous

    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’.

  5. Anonymous

    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!

  6. Anonymous

    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.

  7. Mike Volodarsky

    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 section for IIS5/6 and for IIS7.

    Thanks,

    Mike

  8. Mike Volodarsky

    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.

  9. Anonymous

    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:InetpubWalnutweb.config Line: 11

    Walnut is the name of my root web folder.

    What am I doing wrong?

    Much thanks in advance!

    Jerry

  10. Mike Volodarsky

    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 section of your web.config:





  11. Anonymous

    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

  12. Mike Volodarsky

    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

  13. Anonymous

    Hi,

    sorry to disturb you, but I haven’t seen any notice about license, or usage policy.

    Are there any restrictions?

    Thanks for reply.

  14. Anonymous

    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……

  15. Mike Volodarsky

    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

  16. Mike Volodarsky

    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

  17. Mike Volodarsky

    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

  18. Anonymous

    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!

  19. Mike Volodarsky

    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

  20. Anonymous

    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.

  21. Anonymous

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

  22. Anonymous

    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…

  23. Anonymous

    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.

  24. Anonymous

    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

  25. Mike Volodarsky

    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

  26. Anonymous

    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.

  27. Mike Volodarsky

    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

  28. Anonymous

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

  29. Anonymous

    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.

  30. Anonymous

    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

  31. Mike Volodarsky

    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

  32. Anonymous

    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

  33. Anonymous

    Hey Mike –

    Great app. I have a small silly problem.

    In the browser, instead of displaying the traditional yello folder bitmap, the app displays the bitmap of a hard drive (grey) —

    Your modules are running on IIS7 on Win2008 R2

    Any idea?

    Thanks

  34. Anonymous

    Hi again – One more thing –

    Thanks for the thorough explanations on how to not display hidden files and folders.

    Now, in my case, I have some folders that are NTFS restricted (for security reason); the IIS site is set to authenticate using Windows authentication – All good.

    Some users login on will have access to all folders. But some users with less security might stumble upon security restricted folders.

    When that happens, the app will generate a runtime error:

    “Failed to start monitoring changes to ‘%Path%web.config’ because access is denied.”

    I guess that’s better than a non-authorize user having access to that content. But what if instead we could setup a pretty “Access Denied” custom error instead of a runtime error?

    Thoughts?

    Thanks again 🙂

  35. Anonymous

    Hey Mike –

    Everything works well for me, except that the folder icons have been replaced by “grey Hard drive” icons.

    This is a IIS 7.5 on 64-bit 2008 R2 box. Any idea what this could be?

    Thanks –

Leave a Reply

Your email address will not be published. Required fields are marked *