*************************************************
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:
- Make a request to geticon.axd?file=FILENAME
- 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:
- It uses P/Invoke interop to get the icon using the Shell32.dll's SHGetFileInfo API
- It supports doing lookup of both real files (in case they override the icons), or by file type (extension).
- It uses the CriticalHandle class to make sure the icon handles are disposed properly
- It provides support for caching the handle lookups, and client/proxy caching of the returned images for improved performance
- 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.
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.
Anonymous
Very interesting!
Anonymous
Very cool. Looking forward to the source code/tutorial! 😉
Anonymous
Great!!!
Anonymous
Excelent!!! Waiting for source code… 🙂
Anonymous
Thanks for the great post.
I am implementing a file list for a client at the moment 🙂
Mike Volodarsky
Score! I had a feeling this was just what the doctor ordered for a lot of people 🙂
Anonymous
Mike, Nice job I have a engineering directory with 50k files that this will spruce up nicely
Thanks
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?
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.
Anonymous
Dont suppose i could get a copy of the source code from you could i?
Mike Volodarsky
I’ll have the source posted shortly … Just need to clean it up a bit.
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’.
Mike Volodarsky
Sure I do 🙂 Check out the LeechGuard post for some discussion of that.
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!
Mike Volodarsky
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.
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.
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
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.
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
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:
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
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
Anonymous
Source Please!!!! 😛
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.
Anonymous
Please O’ Please post the source!!
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……
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
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
Anonymous
Thank you very much, Mike.
Anonymous
Suggest to add a sample cache mechanism.
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
Anonymous
when we can see the source?
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!
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
Anonymous
Over the past several year, I've written quite a few modules for IIS7 / ASP.NET. Some of these were
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.
Anonymous
As you are looking for porn filtering articles and pages, be certain to tap into everyone of the sources available.
Anonymous
Having a hard time getting this working with my VB.NET code. Any suggestions?
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…
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.
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
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
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.
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
Anonymous
Since its release, IconHandler has been a pretty popular module (on its own and with the custom DirectoryListingModule
Mike Volodarsky
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
Anonymous
Yes, thank you. I use the DestroyIcon from user32.dll and it seems to do the job.
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.
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
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
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
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
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 🙂
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 –