Windows 10:取消已关联文件扩展名

陪她去流浪 桃子 2015年01月07日 编辑 阅读次数:10536

前不久,Microsoft发布了Windows 10的技术预览版(Windows Technical Preview),出于新奇,下载下来尝尝鲜。结果一来就让我发现一个让我非常不能忍的feature:总是把所选择的程序关联到该文件扩展名。简单点说就是:如果我选择了用记事本打开xml文件,那么,以后就总是使用记事本打开xml文件了,而且xml文件的图标也变成了记事本的图标。

这有什么不好?假如我有一个html网页文件,不用说也应该明白html文件默认都应该被浏览器打开的,但我现在想要编辑一下html文件的内容,怎么办?用记事本打开?当然可以了,但是,这样一来,下次你双击打开html的时候,默认就是记事本,再也不是浏览器了……简直让人无法直视。

一直在想?这M$的人是不是脑子进水了?这难道能说得上是“智能”?我怎么感觉像是把用户当成傻X一样对待了??

来看一张图,这就是打开已知扩展名的情况:

如果你忘记取消上面那个钩,你就悲剧鸟!你会发现桌面图标一闪。。。你应该不会愿意每次都先取消然后再点击程序吧?

再来看一张,这是打开未知扩展名的情况:

注意:这个时候你是*不能*取消扩展名自动关联的了(已经没了那个选项)。一旦你点击任一程序,以后你都得用那个程序打开了,而且桌面又是一闪,文件图标又是一闪,简直要命!难道我就不能临时用某个程序查看一下文件的内容?难道我用十六进制编辑器查看某文件的十六进制来分辨一下文件类型就不行吗?我不是白痴,请不要这样对我!


下面就说下怎么取消该死的默认文件关联!

我Google了很久,都没找到好的解决方案。因为Windows从来就只支持关联扩展名,根本没有提供取消关联!而且据我所知,不同版本的Windows系统取消关联的方式并不相同,这是真的!

我的解决思路及解决办法:历来Windows都是把文件关联保存到注册表中的,这次肯定也一样,于是我就用 Process Explorer 监控“打开方式”这个程序的注册表操作,得到了以下操作:

  1. 增加了HKCU\Software\Classes\扩展名_auto_file
  2. 增加了HKCU\Software\Classes\.扩展名
  3. 增加了HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.扩展名
  4. 增加了HKCU\Software\Microsoft\Windows\Roaming\OpenWith\FileExts\.扩展名

上面是增加的注册表主键,子键我没必要列出来。而我们要做的就是相反的工作:把上面的子键通通删除即可!怎么删?请打开注册表。。

删除了上面的注册表键后,文件扩展名现在应该是被取消关联了,但是,可能要重启桌面才能看到效果,有多种方法可以实现,只是麻烦程度不同而已:

  1. 重启电脑。麻烦,不推荐!
  2. 重启桌面。在任务管理器中找到explorer.exe,结束即可,可能有多个,至于哪个是真正的桌面进程,难以判断。不知道的话,全部结束即可。
  3. 编程通知桌面刷新图标缓存。可以使用如下代码:
    SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);

结束语:手动修改起来比较麻烦,你可以用各种编程语言来自动化,以达到一劳永逸的效果。比如PowerShell、批处理脚本、C语言。。。

我也随手写了一个:源代码+可执行文件

源代码(仅一个C++组成):

#include <string>
#include <iostream>
#include <io.h>
#include <fcntl.h>

#include <tchar.h>
#include <windows.h>
#include <ShlObj.h>

const wchar_t* str_hkey(HKEY hRootKey){
	if(hRootKey == HKEY_CURRENT_USER) return L"HKEY_CURRENT_USER";

	return L"UNKNOWN";
}

bool delete_key(HKEY hRootKey, std::wstring strSubkey, std::wstring strKeyToDelete)
{
	HKEY hkOpen;

	std::wcout 
		<< L"\t将删除: " 
		<< str_hkey(hRootKey) 
		<< L"\\" 
		<< strSubkey 
		<< L"\\" 
		<< strKeyToDelete 
		<< std::endl;

	if(RegOpenKeyExW(
		hRootKey,
		strSubkey.c_str(),
		0,
		DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE | KEY_SET_VALUE,
		&hkOpen
		)
		!= ERROR_SUCCESS)
	{

		std::wcerr << L"\t无法打开该键!" << std::endl;
		return false;
	}

	LSTATUS lr = RegDeleteTree(hkOpen, strKeyToDelete.c_str());
	if(lr != ERROR_SUCCESS && lr!=ERROR_FILE_NOT_FOUND){
		std::wcout << L"\t无法删除该键(" << lr << L")!" << std::endl;
		RegCloseKey(hkOpen);
		return false;
	}

	std::wcout << L"\t已删除!\n\n";

	return true;
}

void unassoc(const std::wstring& ext)
{
	delete_key(
		HKEY_CURRENT_USER,
		LR"(Software\Classes)",
		ext + L"_auto_file"
		)
		&& delete_key(
		HKEY_CURRENT_USER,
		LR"(Software\Classes)",
		std::wstring(L".") + ext
		)
		&& delete_key(
		HKEY_CURRENT_USER,
		LR"(Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts)",
		std::wstring(L".") + ext
		)
		&& delete_key(
		HKEY_CURRENT_USER,
		LR"(Software\Microsoft\Windows\Roaming\OpenWith\FileExts)",
		std::wstring(L".") + ext
		)
		;
	SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nullptr, nullptr);
}

int main()
{
	_setmode(_fileno(stdout), _O_U16TEXT);

	std::wcout <<
LR"(--- Win10文件扩展名关联去除 ---

该程序用于去除程序与文件扩展名的关联。
请仅将该程序用于 “Windows 10” 系统。

警告:随意地删除已关联的文件扩展名可能会对系统造成不可挽回的、
灾难性的后果,请谨慎地使用该程序。

免责声明:本人不承担对使用该程序造成的后果的任何责任。在此及以前,
本程序都不会对系统造成任何不良后果。若不同意该声明,请立即停止
使用本程序。

联系:女孩不哭 QQ:191035066 Em:anhbk@qq.com 2015-03-05

主页: http://blog.twofei.com/windows/usage/win10-unassoc-file-extension.html

)";

	std::wcout << LR"(同意以上的协议请输入“yes”: )";
	std::wstring yes_or_no;
	std::getline(std::wcin, yes_or_no);
	if(yes_or_no != L"yes"){
		return 1;
	}

	std::wcout << std::endl;

	for(;;){
		std::wcout << LR"(请小心地输入单个扩展名(不包含小数点):)";
		std::wstring ext;
		std::getline(std::wcin, ext);
		if(ext == L"" || ext.find(L' ') != std::wstring::npos){
			std::wcout << LR"(不正确的扩展名!)" << std::endl;
			continue;
		}

		unassoc(ext);
	}

	return 0;
}

标签:代码片段 · WinAPI