前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一种将快捷方式从开始菜单“常用应用”的中去除的方法

一种将快捷方式从开始菜单“常用应用”的中去除的方法

作者头像
方亮
发布2019-01-16 11:01:05
9020
发布2019-01-16 11:01:05
举报
文章被收录于专栏:方亮方亮

      当我们安装一款软件的时候,这款软件的一些快捷方式可能被设置到开始菜单的“常用应用”区域。但是,如果是“卸载”快捷方式被“钉”到该区域,就会造成非常不好的体验。毕竟把“卸载”接口暴露得如此醒目,如同把该款软件的地狱大门暴露出来。(转载请指明出于breaksoftware的csdn博客)

        如下图,python就将卸载程序放到了“常用区域”。从而会导致windows会将该快捷方式放到“常用应用”区域。

        一种解决方案就是,不将“卸载”快捷方式放到开始菜单的“普通区域”。很多应用都是使用这种方式。

        另一种就是如何将该项从“常用应用”区域删除。本文就是讲解这套方案的研究和分析。

        首先,我们使用RegSnap抓取一次注册表快照。然后在”常用应用“区域删除notepad++的启动快捷方式,再生成一次快照。对比两次快照。我们可以得出如下结果:

Deleted keys HKEY_USERS\S-1-5-21-3689171631-189274284-2341753515-176562\Software\Microsoft\Windows\CurrentVersion\Explorer\RecentDocs\70 HKEY_USERS\S-1-5-21-3689171631-189274284-2341753515-176562\Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist\{F4E57C4B-2036-45F0-A9AB-443BCFE33D9F}\Count\{0139Q44R-6NSR-49S2-8690-3QNSPNR6SSO8}\Abgrcnq++\Abgrcnq++.yax

        从对比图中,我们可以看到一个叫Abgrcnq++.yax被删除了。这个是个非常有意思的名字,我们可以看出来,这个名字明显是被加密的,但是加号和点号没有被加密。我又观察了其他的键(HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist\{CEBFF5CD-ACE2-4F4F-9178-9926F41749EA}\Count下)

        从后缀rkr可以想象,这个可能是exe的加密结果。后来我做了下计算,发现字符间存在13的差值。后来才知道这个就是所谓的ROT13置换转换码。该算法的详细介绍可以见

http://baike.baidu.com/link?url=a3UL0bMbmzzINfomfkCgTHyUOQDwBk83WkEjcgH6gZdvproZg7OTcXkt6G3oLLFpZnBXwXWhFWeGhqXBN8Tuhq

        后来,我又做了一个实验——删除了HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist\{F4E57C4B-2036-45F0-A9AB-443BCFE33D9F}\Count的一个键,该键对应的快捷方式在开始菜单的”常用应用“区域。发现,该键被删除后,该快捷方式就消失了。

        以下是测试代码:

代码语言:javascript
复制
// RegExplorerUserAssist.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include <windows.h>
#include <string>

/*
Registry value names are limited to 32,767 bytes. 
The ANSI version of this function treats this parameter as a SHORT value. 
Therefore, if you specify a value greater than 32,767 bytes, there is an overflow and the function may return ERROR_MORE_DATA.
*/
#define MAX_VALUE_NAME 16383

// http://baike.baidu.com/link?url=a3UL0bMbmzzINfomfkCgTHyUOQDwBk83WkEjcgH6gZdvproZg7OTcXkt6G3oLLFpZnBXwXWhFWeGhqXBN8Tuhq

std::wstring ConvertData( LPCWSTR lpBuffer, DWORD dwLength ) {
	std::wstring wstrValueName;
	for ( DWORD dwIndex = 0; dwIndex < dwLength; dwIndex++ ) {
		WCHAR wchSingle = *( lpBuffer + dwIndex );

		unsigned char ucsa = LOBYTE(WCHAR('a'));
		unsigned char ucsz = LOBYTE(WCHAR('z'));
		unsigned char ucbA = LOBYTE(WCHAR('A'));
		unsigned char ucbZ = LOBYTE(WCHAR('Z'));

		if ( ( WCHAR('a') <= wchSingle && WCHAR('z') >= wchSingle ) || ( WCHAR('A') <= wchSingle && WCHAR('Z') >= wchSingle )  ) {
			unsigned char uc = LOBYTE(wchSingle);
			if ( ucsa <= uc && ucsz >= uc ) {
				uc = ( ( uc + 13 ) > ucsz  ) ? uc - 13 : uc + 13;
			}
			else if ( ucbA <= uc && ucbZ >= uc ) {
				uc = ( ( uc + 13 ) > ucbZ  ) ? uc - 13 : uc + 13;
			}

			wchSingle = WCHAR(MAKELONG(uc,0));
		}
		wstrValueName.append( &wchSingle, 1 );
	}

#ifdef DEBUG
	std::wstring wstrOutput = wstrValueName;
	wstrOutput.append( WCHAR('\n'), 1);
	OutputDebugStringW(wstrOutput.c_str());
#endif
	
	return wstrValueName;
}

BOOL DeleteValue(HKEY hKey, const std::wstring& wstrSubString) 
{ 
	WCHAR wchValueName[MAX_VALUE_NAME] = {0};
	LPWSTR lpValueNameBuffer = wchValueName;
	DWORD dwValueNameBufferLength = ARRAYSIZE(wchValueName);

	BOOL bSuc = FALSE;
	do {
		DWORD    dwValuesCount = 0;              // number of values for key 
		DWORD    dwMaxValueNameLen = 0;          // longest value name 
		// Get the class name and the value count. 
		LONG lretCode = RegQueryInfoKey( hKey,
			NULL, NULL, NULL, NULL, NULL, NULL, &dwValuesCount, &dwMaxValueNameLen, NULL, NULL, NULL );
	
		if ( ERROR_SUCCESS != lretCode ) {
			break;
		}
		// Enumerate the key values.

		if ( 0 != dwValuesCount) {
			for ( DWORD dwIndex = 0; dwIndex < dwValuesCount; dwIndex++ )  { 

				DWORD dwValueNameInlineLength = dwValueNameBufferLength;
				wmemset( lpValueNameBuffer, 0, dwValueNameInlineLength);

				lretCode = RegEnumValue(hKey, dwIndex, 
					lpValueNameBuffer, &dwValueNameInlineLength, NULL, NULL, NULL, NULL);

				if ( ERROR_NO_MORE_ITEMS == lretCode ) { 
					// Suc
					bSuc = TRUE;
					break;
				} 

				if ( ERROR_MORE_DATA == lretCode ) {
					if ( wchValueName != lpValueNameBuffer ) {
						if ( NULL != lpValueNameBuffer ) {
							delete [] lpValueNameBuffer;
							lpValueNameBuffer = NULL;
						}
					}
					lpValueNameBuffer = new WCHAR[dwValueNameInlineLength];
					dwValueNameBufferLength = dwValueNameInlineLength;
					dwIndex--;
				}

				if ( ERROR_SUCCESS == lretCode ) {
					std::wstring wstrValueName = ConvertData( lpValueNameBuffer, dwValueNameInlineLength );
					if ( std::wstring::npos == wstrValueName.find( wstrSubString.c_str() ) ) {
						continue;
					}
					else {
						bSuc = RegDeleteValue( hKey, wstrValueName.c_str() );
						break;
					}
				}
			}
		}
	} while (0);

	if ( lpValueNameBuffer != wchValueName ) {
		delete [] lpValueNameBuffer;
		lpValueNameBuffer = NULL;
	}

	return bSuc;
}

int _tmain(int argc, _TCHAR* argv[])
{
	HKEY hTestKey;

	if( RegOpenKeyEx( HKEY_CURRENT_USER,
		TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\UserAssist\\{F4E57C4B-2036-45F0-A9AB-443BCFE33D9F}\\Count"),
		0,
		KEY_READ,
		&hTestKey) == ERROR_SUCCESS
		)
	{
		DeleteValue(hTestKey, L"\\360安全中心\\360安全卫士\\360安全卫士.lnk");
	}

	return 0;
}

        有一点需要说明——XP下不是该注册表路径。如果想将方案移植到XP上,使用相同的方法应该可以得出注册表路径。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2014年04月07日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档