Archive for November, 2008

Delete a file to the recycle bin from C++

Friday, November 14th, 2008

Today, I was looking for a way to delete a file to the recycle bin using C++, but couldn’t find any simple example, so here it is:

SHFILEOPSTRUCT operation;
operation.wFunc = FO_DELETE;
operation.pFrom = "c:\\file\to\delete.txt";
operation.fFlags = FOF_ALLOWUNDO;

SHFileOperation(&operation);

Get the 48×48 or 256×256 icon of a file on Windows

Thursday, November 13th, 2008

Getting the 16×16 and 32×32 icons on Windows is relatively easy and is often as simple as one call to ExtractIconEx.

However, getting the extra large (48×48) and jumbo (256×256) icons introduced respectively by XP and Vista is slighly more complex. This is normally done by:

  1. Getting the file information, in particular the icon index, for the given file using SHGetFileInfo
  2. Retrieving the system image list where all the icons are stored
  3. Casting the image list to an IImageList interface and getting the icon from there

Below is the code I’m using in Appetizer to retrieve the extra large icon. If needed it can easily be adapted to get the jumbo icon.

Update: To do the same thing in C#, see the link in the comments below.

#include <shlobj.h>
#include <shlguid.h>
#include <shellapi.h>
#include <commctrl.h>
#include <commoncontrols.h>

// Get the icon index using SHGetFileInfo
SHFILEINFOW sfi = {0};
SHGetFileInfo(filePath, -1, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX);

// Retrieve the system image list.
// To get the 48x48 icons, use SHIL_EXTRALARGE
// To get the 256x256 icons (Vista only), use SHIL_JUMBO
HIMAGELIST* imageList;
HRESULT hResult = SHGetImageList(SHIL_EXTRALARGE, IID_IImageList, (void**)&imageList);

if (hResult == S_OK) {
  // Get the icon we need from the list. Note that the HIMAGELIST we retrieved
  // earlier needs to be casted to the IImageList interface before use.
  HICON hIcon;
  hResult = ((IImageList*)imageList)->GetIcon(sfi.iIcon, ILD_TRANSPARENT, &hIcon);

  if (hResult == S_OK) {
    // Do something with the icon here.
    // For example, in wxWidgets:
    wxIcon* icon = new wxIcon();
    icon->SetHICON((WXHICON)hIcon);
    icon->SetSize(48, 48);
  }
}

Appetizer 1.0 is out

Wednesday, November 12th, 2008

I have just released version 1.0 of Appetizer. It is a free application launcher, or dock, for Windows. It allows organizing and launching your applications and other shortcuts into a convenient dock. The app is skinable and entirely customizable. It is currently available in five different languages.

The application also supports the PortableApps USB format. So if you use Appetizer on a USB key in the PortableApps format, the application will detect it and automatically import all your applications along with the ‘Documents’, ‘Videos’, ‘Music’ and ‘Pictures’ folders.

Follow this link to download it.

Appetizer

Dump a SVN repository from a URL

Friday, November 7th, 2008

Dumping a repository is sometime necessary, for example when you want to transfer it from one place to the other, say from Google Code to Sourceforge. The dump is normally created using svnadmin. However if you ever try to dump a remote repository, you’ll find out that it can’t be done:

svnadmin dump http://projectname.googlecode.com/svn > repodump

svnadmin: 'http://projectname.googlecode.com/svn' is an URL when it should be a path

One way around that is to use svnsync. This utility allows you to synchronize a local depository with a remote one. So the technique here is to create an empty repository, synchronize it with the remote one, and, finally, dump the local repository.

Here are some notes on how to do that:

1. Create a local repository

svnadmin create c:/repository

2. Add a “pre-revprop-change” hook to the local repository.

echo > c:\repository\hooks\pre-revprop-change.cmd

This is done by opening the “hooks” folder of the repository and adding a blank “pre-revprop-change.cmd” file into it. This will enable revision property change, which is necessary for synchronization.

On Linux and Mac, please follow the instructions in this comment.

3. Synchronize your new repository with the remote one:

svnsync init file:///c:/repository https://example.googlecode.com/svn

svnsync sync file:///c:/repository

Note: if you get this error: “Cannot initialize a repository with content in it“, it means that you’ve made some changes to the repository. In which case, the best thing to do is to just delete it and start over. The repository must be completely empty for the synchronization to work.

4. Finally, once the synchronization is done, simply dump your local repository:

svnadmin dump c:/repository > repodump

If everything went well, repodump should now contain the exact content of the remote repository.

Everything in one batch script

The batch script below allows to do all that in just one script. Simply replace REPO_PATH and REPO_PATH_NUX by the path to your repository and REPO_URL by the repository URL.

SET REPO_PATH=c:\your\local\repository
SET REPO_PATH_NUX=file:///c:/your/local/repository
SET REPO_URL=https://example.com/remote/repository

REM Uncomment the line below if the repository folder already exists
REM rmdir %REPO_PATH% /s/q
mkdir %REPO_PATH%
svnadmin create %REPO_PATH%
echo > %REPO_PATH%\hooks\pre-revprop-change.cmd
svnsync init %REPO_PATH_NUX% %REPO_URL%
svnsync sync %REPO_PATH_NUX%
Copyright © Pogopixels Ltd, 2008-2018