删除桌面快捷方式其实是删除桌面上的快捷方式文件,那我们如何去删除桌面快捷方式文件呢?软件可能已经发布过多个版本,其中的一些版本的快捷方式文件名称可能了多次改动,程序中不可能记录每个版本的快捷方式名称,没法直接去删除快捷方式文件。本文就给出一种有效的处理办法,能很好地满足实际的需求。

  1. 实现思路
    删除指定程序的桌面快捷方式的具体思路是,先获取桌面的完整路径,然后遍历桌面文件夹中的所有.lnk快捷方式文件,然后通过IShellLink COM接口去获取快捷方向的exe名称,通过比对exe名称,确定是我们软件的桌面快捷方式。找到快捷方式文件,删除即可。一般情况下,软件的exe程序是不怎么变动的,所以这种方法是比行的。

    删除桌面快捷方式操作一般在安装包中进行的。在启动安装包安装程序时,会先将程序老的桌面快捷方式和开始菜单快捷方式删除,然后再去创建新的桌面和开始菜单方式。

  2. 调用SHGetSpecialFolderLocation获取桌面的路径
    通过调用系统API接口SHGetSpecialFolderLocation,我们可以获取多个系统路径,比如所有用户的公用桌面路径(传入CSIDL_COMMON_DESKTOPDIRECTORY参数),前登录用户的appdata路径(传入CSIDL_APPDATA)等。
    此处我们假定软件的快捷方式是放置在公用桌面上的,我们就要使用CSIDL_COMMON_DESKTOPDIRECTORY参数去获取公用桌面的路径:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

CString strCommonDesktopPath;
bRet = GetSpecialFolderPath( strCommonDesktopPath, CSIDL_COMMON_DESKTOPDIRECTORY );


// 获取 桌面、开始->程序组 的路径
// 参数:int nFolder,对应CSIDL_COMMON_PROGRAMS、CSIDL_COMMON_DESKTOPDIRECTORY等
BOOL GetSpecialFolderPath( CString& strFolderPath, int nFolderType )
{
LPITEMIDLIST ppidl;
if ( SHGetSpecialFolderLocation( NULL, nFolderType, &ppidl ) == S_OK )
{
TCHAR achTargetPath[MAX_PATH] = { 0 };
BOOL bRet = SHGetPathFromIDList( ppidl, achTargetPath );
strFolderPath = achTargetPath;
CoTaskMemFree( ppidl );
return bRet;
}

return FALSE;
}
  1. 通过IShellLink COM接口获取快捷方式指向的exe文件完整路径
    通过IShellLink COM接口类获取快捷方式指向的exe文件完整路径,然后判断是否是我们的程序,封装的接口如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
BOOL IsTargetLnkFile( CString strLnkPath )
{
HRESULT hres;
IShellLink *psl;
IPersistFile *ppf;

BOOL bTarget = FALSE;
//hres = ::CoInitialize(NULL);
//if ( hres != S_OK ) //初始化COM库失败,直接返回
//{
// return bTarget;
//}

hres = CoCreateInstance( CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&psl );
if ( !SUCCEEDED(hres) )
{
return bTarget;
}

hres = psl->QueryInterface( IID_IPersistFile, (void**)&ppf );
if( SUCCEEDED(hres) )
{
TCHAR achLnkExeFilePath[MAX_PATH*2] = { 0 };
hres = ppf->Load( strLnkPath, 0 );
if( SUCCEEDED(hres) )
{
WIN32_FIND_DATA wfd;
hres = psl->GetPath( achLnkExeFilePath, sizeof(achLnkExeFilePath), &wfd, 0 );
}

// 假定我们的程序的名称为Test.exe
CUIString strExePath = achLnkExeFilePath;
if ( strExePath .Find( _T("Test.exe") ) != -1 )
{
bTarget = TRUE;
}

ppf->Release();
}

psl->Release();
//::CoUninitialize();

return bTarget;
}
  1. 遍历桌面文件中的所有快捷方式文件,找出我们程序的快捷方式
    相关函数的实现上面已经给出了,下面就轮到我们去遍历桌面文件夹中的所有快捷方式文件,然后判断是否是我们程序的,然后删除之。相关代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// 获取公用桌面的路径
CString strCommonDesktopPath;
bRet = GetSpecialFolderPath( strCommonDesktopPath, CSIDL_COMMON_DESKTOPDIRECTORY );
if ( !bRet )
{
//::CoUninitialize();
return;
}

// 将公用桌面路径传递给下面的接口
DeleteDesktopShortCut( strCommonDesktopPath );
void DeleteDesktopShortCut( const CString strDir )
{
CString strFilePath;
CFileFind fileFinder;
BOOL bFind = fileFinder.FindFile( strDir + _T("\\*.*") );
while ( bFind )
{
bFind = fileFinder.FindNextFile();
if( !fileFinder.IsDots() )
{
strFilePath = fileFinder.GetFilePath();
if( fileFinder.IsDirectory() )
{
continue;
}

int nLen = strFilePath.GetLength();
// 过滤出快捷方式文件
if( nLen > 4 && !_tcscmp( strFilePath.Right(4), _T(".lnk") ) )
{
// 判断快捷方式文件是否是我们程序的
BOOL bTarget = IsTargetLnkFile( strFilePath );
if ( bTarget )
{
// 找到我们程序的快捷方式了,删除之
DeleteFile( strFilePath );
}
}
}
}

fileFinder.Close();
}

有人可能会问,那我要删除开始菜单中的快捷方式该怎么弄呢?其实很简单,上述接口是通用的,只要传入开始菜单文件夹路径进去就可以了。