Click here to Skip to main content
15,867,756 members
Articles / Desktop Programming / ATL
Article

Display content size for a folder in Explorer using shell extensions

Rate me:
Please Sign up or sign in to vote.
4.60/5 (17 votes)
18 Nov 20032 min read 151.3K   1.3K   37   37
How to add a column to Explorer to show the size of the content of folders

Sample Image - SHDireSizeColumn.jpg

Introduction

Don't tell me you never had to right click a folder only to see in the properties the size of the content. If you never did it, skip reading this article!!!

Let's take a look at the code

If you did it, what you need is a shell extension!!! What is a shell extension? You will find the right answer reading The Michael Dunn's Complete Idiot's Guide to Writing Shell Extensions, here on CodeProject. What I did is read the Part VIII of the series and modify two functions to get my content-size-column in the Explorer. First of all, I did all the building without the last Platform SDK. So, I needed to add manually to my code the IColumnProvider interface declaration, plus some other declarations in my header files, like this
// remove all this stuff if you have the right shlobj.h file
// *** start stuff

typedef struct {
    GUID fmtid;
    DWORD pid;
} SHCOLUMNID, *LPSHCOLUMNID;
typedef const SHCOLUMNID* LPCSHCOLUMNID;


typedef struct {
    ULONG    dwFlags;
    ULONG    dwReserved;
    WCHAR    wszFolder[MAX_PATH];
} SHCOLUMNINIT, *LPSHCOLUMNINIT;

#define MAX_COLUMN_NAME_LEN 80
#define MAX_COLUMN_DESC_LEN 128

#pragma pack(1)
typedef struct {
    SHCOLUMNID  scid;
    VARTYPE     vt;
    DWORD       fmt;
    UINT        cChars;
    DWORD       csFlags; 
    WCHAR wszTitle[MAX_COLUMN_NAME_LEN];
    WCHAR wszDescription[MAX_COLUMN_DESC_LEN];
} SHCOLUMNINFO, *LPSHCOLUMNINFO;


#define SHCDF_UPDATEITEM        0x00000001      

typedef struct {
    ULONG   dwFlags;
    DWORD   dwFileAttributes;
    ULONG   dwReserved;
    WCHAR   *pwszExt;
    WCHAR   wszFile[MAX_PATH];
} SHCOLUMNDATA, *LPSHCOLUMNDATA;
typedef const SHCOLUMNDATA* LPCSHCOLUMNDATA;


DECLARE_INTERFACE_(IColumnProvider, IUnknown)
{
    // IUnknown methods
    STDMETHOD (QueryInterface)(THIS_ REFIID riid, void **ppv) PURE;
    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
    STDMETHOD_(ULONG, Release)(THIS) PURE;

    // IColumnProvider methods
    STDMETHOD (Initialize)(THIS_ LPSHCOLUMNINIT psci) PURE;
    STDMETHOD (GetColumnInfo)(THIS_ DWORD dwIndex, LPSHCOLUMNINFO psci) PURE;
    STDMETHOD (GetItemData)(THIS_ LPCSHCOLUMNID pscid, LPCSHCOLUMNDATA pscd,
VARIANT *pvarData) PURE;
};

// *** end stuff
Remember to remove all this code (in DirSizeColumn.h) if you have the right Platform SDK or you'll get some compiler error. The core of the dll are the two functions CDirSizeColumn::GetColumnInfo and CDirSizeColumn::GetItemData. The first tells Explorer that there will be a new column, right aligned etc etc:
STDMETHODIMP CDirSizeColumn::GetColumnInfo ( DWORD dwIndex, 
    LPSHCOLUMNINFO psci )
{
    HRESULT hRes=S_FALSE;

    if (dwIndex==0)
    {
        psci->scid.fmtid = *_Module.pguidVer;   
        psci->scid.pid   = MY_COLUMN_ID;                               
        psci->vt         = VT_LPSTR;                                        
        psci->fmt        = LVCFMT_RIGHT;                                  
        psci->csFlags    = 0x22; // this is  SHCOLSTATE_TYPE_INT | 
                                 // SHCOLSTATE_SLOW
        psci->cChars     = 6;
        lstrcpyW ( psci->wszTitle, L"Content Size\0");
        lstrcpyW ( psci->wszDescription, 
             L"Size of all files and subfolders contained\0");
                            
        hRes=S_OK;
    }

    return hRes;
}
The second one will do the calc stuff for any directory being passed as param
STDMETHODIMP CDirSizeColumn::GetItemData (
    LPCSHCOLUMNID   pscid,
    LPCSHCOLUMNDATA pscd,
    VARIANT*        pvarData )
{
    HRESULT hRes=S_FALSE;

    // is my module?
    if ( pscid->fmtid == *_Module.pguidVer )
    {
        // is a directory?
        if ( (pscd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)==
            FILE_ATTRIBUTE_DIRECTORY)
        {
            // is my column?
            if ( pscid->pid == MY_COLUMN_ID )
            {
                CString strFileName(pscd->wszFile);

                char szText[100];
                sprintf(szText,"%I64d KB",(__int64)(
                     GetDirSize(strFileName)/(__int64)1024));

                CComVariant vData(szText);

                vData.Detach ( pvarData );

                hRes=S_OK;
            }
        }
    }

    return hRes;
}
Really simple, isn't it? :) The function that read folders size is a simple recursive function, uses CFileFind from MFC and iterate in any subfolder and any file in a given folder.
__int64 GetDirSize(CString strFileName)
{
    __int64 i64Size=0;

    TRY
    {
        CFileFind finder;
        BOOL bWorking = finder.FindFile(strFileName+"\\*.*");

        while (bWorking)
        {
            bWorking = finder.FindNextFile();

            // check for dots
            if (!finder.IsDots())
            {
                // check for recursion
                if (finder.IsDirectory())
                    i64Size=i64Size+GetDirSize(finder.GetFilePath());
                else
                    i64Size=i64Size+finder.GetLength64();
            }
        }
    }
    CATCH(CException, ex)
    {
        // catch any error here

        i64Size=0;
    }
    END_CATCH

    return i64Size;
}

Install/Uninstall

To install the extension use the following command:
regsvr32 SHDireSizeColumn.dll
and to uninstall, type:
regsvr32 /u SHDireSizeColumn.dll
Remember to close all Explorer windows and next time you want to know the size of the content of a dir you will have to right click etc etc etc... :)

And then...

Many many thanks to Michael Dunn, writing this article has been a matter of minutes once I read his guides!!! :) See you soon.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior) Leonardo
Italy Italy
Hi Smile | :)
I was born in 1970 (Augusta - Italy).
I live in Taranto - Italy.
I work in Taranto - Italy.
I like computer science!!!
That's all!

Comments and Discussions

 
QuestionCan't debug :( ? Pin
bosfan18-Jun-08 6:13
bosfan18-Jun-08 6:13 
GeneralDoesn't work on Vista :( Pin
kitx10-Jun-08 15:02
kitx10-Jun-08 15:02 
GeneralVisual C++ 2008 Express missing afxwin.h Pin
prader23-May-08 21:47
prader23-May-08 21:47 
GeneralSHDireSizeColumn_demo does not work! Pin
CdD9821-Nov-04 14:35
CdD9821-Nov-04 14:35 
GeneralRe: SHDireSizeColumn_demo does not work! Pin
Khan-Dam0625-Oct-06 0:48
Khan-Dam0625-Oct-06 0:48 
Questioncan we add image bar also in column? Pin
AJAYP31-Aug-04 0:28
AJAYP31-Aug-04 0:28 
GeneralAnother Newbie Question Pin
Jackboy17-Jul-04 6:23
Jackboy17-Jul-04 6:23 
GeneralIs the new column necessary - Part II Pin
Rage7-May-04 2:57
professionalRage7-May-04 2:57 
GeneralRe: Is the new column necessary - Part II Pin
Anthony_Yio3-May-06 0:24
Anthony_Yio3-May-06 0:24 
GeneralSorting ability with size in KB, MB, GB... Pin
Anonymous10-Apr-04 15:58
Anonymous10-Apr-04 15:58 
GeneralRe: Sorting ability with size in KB, MB, GB... Pin
sazerty5-Jul-04 12:13
sazerty5-Jul-04 12:13 
GeneralCached & realtime updated (NTFS only)! Pin
MarkPorsby7-Dec-03 3:13
MarkPorsby7-Dec-03 3:13 
GeneralCompiler Errors Pin
Tradon-Dev26-Nov-03 3:47
Tradon-Dev26-Nov-03 3:47 
GeneralRe: Compiler Errors Pin
Sharan Basappa27-Nov-03 22:09
Sharan Basappa27-Nov-03 22:09 
GeneralRe: Compiler Errors Pin
csavie17-Jul-04 8:39
csavie17-Jul-04 8:39 
GeneralReading Pin
espelly21-Nov-03 1:58
espelly21-Nov-03 1:58 
GeneralPerformance question Pin
dog_spawn20-Nov-03 8:32
dog_spawn20-Nov-03 8:32 
GeneralRe: Performance question Pin
Massimiliano Conte20-Nov-03 21:13
Massimiliano Conte20-Nov-03 21:13 
GeneralRe: Performance question Pin
gebrudergrimm26-Nov-03 14:03
gebrudergrimm26-Nov-03 14:03 
GeneralI just use Total Commander for this ;) Pin
Kochise19-Nov-03 23:24
Kochise19-Nov-03 23:24 
GeneralCheck out Directory Opus as well. Pin
Leo Davidson21-Nov-03 3:02
Leo Davidson21-Nov-03 3:02 
GeneralCompiler errors. Pin
WREY19-Nov-03 22:30
WREY19-Nov-03 22:30 
QuestionIs new column necessary? Pin
Hans Dietrich19-Nov-03 22:12
mentorHans Dietrich19-Nov-03 22:12 
AnswerRe: Is new column necessary? Pin
Massimiliano Conte19-Nov-03 23:02
Massimiliano Conte19-Nov-03 23:02 
GeneralRe: Is new column necessary? Pin
Hans Dietrich20-Nov-03 1:54
mentorHans Dietrich20-Nov-03 1:54 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.