例子:进行文件关联的头文件及例子

优质
小牛编辑
183浏览
2023-12-01
引用 Assoc.nsh 的内容:

/****************************

文件关联 NSIS 实用函数(修正)



By:Ansifa

修正:2008年2月15日
*修正了关联错误(发布太急了,没发现,惭愧).
	就是将下面代码改好了.大家自己找找改了什么:p
	WriteRegStr HKCR "${Project}.${type}" "" "${desc}"
	WriteRegStr HKCR "${Project}.${type}\shell" "" open
	WriteRegStr HKCR "${Project}.${type}\shell\open" "" "打开(&O)"
	WriteRegStr HKCR "${Project}.${type}\shell\open\command" "" '${openexe} "%1"'
*将关联普通文件的"播放(&P)"改为"打开(&O)",这样好些^_^.
*增加检查当前关联的宏:CheckSection

*更新:2008年2月26日
增加了打开方式字串的设置,只需要在你的代码加入:
!define Ass_Str "打开(&O)"
!define Ass_Str_Media "播放(&P)"
就能设置打开方式字串,如果不设置就默认设置为 "打开(&O)" "播放(&P)".

修正:2008年2月27日
修正了取消关联后恢复的BUG.

介绍:
由于写一个媒体播放器,需要关联大量文件,被重复的代码搞得心烦,所以花了一个下午
写了一个能实现文件关联的头文件,可以令NSIS编写关联文件代码更方便.
而且能完美解决各种重复关联,重复取消关联所引起的错误.

功能:
1. 关联多个文件为一个类型,如关联"*.rmvb"为"Real 媒体文件";
2. 同时关联多个文件为一个类型,如"*.rmvb;*.rm;*.ra;*.rv"为"Real 媒体文件";
3. 关联的文件可以分为(1)需要注册对象容器媒体文件(2)不需要注册对象容器普通文件;
4. 取消文件关联,支持同时取消上述的多个文件关联的操作.
5. 取消关联后可选择 恢复/不恢复 旧有关联.

****************************
用法:
* 必须认真阅读!如果你要用这东西的话:-p

1. 在你的脚本开头包含头文件
	!include "Assoc.nsh"
	
	定义你的工程名称,这是为了辨认是否关联以及赋予备份的主键值,不可空!
	!define Project 工程名称
	如
	!define Project MPlayerc
	
	如果需要回显每个关联的动作(即以DetailPrint显示)的,在脚本开头包含下面行:
	!define Echo ""
	
	如果需要回显每个取消关联的动作(即以DetailPrint显示)的,在脚本开头包含下面行:
	!define UnEcho ""

	增强功能:填写好关联代码后自动输出取消关联的代码,在脚本开头包含下面行:
	!define EchoUnSources ""

2. 在Section或者Function里面需要的地方插入:

	# 要关联普通文件用:
	!macro Assoc 文件扩展名列表 文件类型 描述 打开方式 默认图标 对象类型
	# 例如:
	!insertmacro Assoc "jpg" "jpgfile" "JPEG图像" "$INSTDIR\ACDSee.exe" "$INSTDIR\Icon.ico"
	!insertmacro Assoc "rar,zip,7z,gz" "rarfile" "WinRAR 压缩文件" "$INSTDIR\WinRAR.exe" "$INSTDIR\Icon.ico"

	# 要关联一个媒体文件用:
	!macro Assoc_Media 文件扩展名列表 文件类型 描述 打开方式 默认图标 对象类型 对象CLSID
	# 例如:
	!insertmacro Assoc_Media "rmvb" "rmvbfile" "Real 媒体文件 "$INSTDIR\KMPlayer.exe" "$INSTDIR\Icon.ico" "video/vnd.rn-realmedia" "{CFCDAA03-8BE4-11CF-B84B-0020AFBBCCFA}"
	!insertmacro Assoc_Media "rmvb,rm,ra,rv" "rmvbfile" "Real 媒体文件 "$INSTDIR\KMPlayer.exe" "$INSTDIR\Icon.ico" "video/vnd.rn-realmedia" "{CFCDAA03-8BE4-11CF-B84B-0020AFBBCCFA}"

	注:文件类型列表用逗号","分隔.

	# 取消关联文件用:
	!macro UnAssoc 文件扩展名列表
	# 例如:
	!insertmacro UnAssoc "jpg"
	!insertmacro UnAssoc "rmvb,rm,ra,rv"

	注:文件类型列表用逗号","分隔.

3.所有关联操作完毕后加一行刷屏函数:
	System::Call 'Shell32::SHChangeNotify(i 0x8000000, i 0, i 0, i 0)'
	以立即显示更改.

4.CheckSection:检查当前关联的
用法步骤:
	1.  看看开头有没!include "Assoc.nsh",没有就加上.

	2.	在你的代码开头加InstType加一行:
			InstType 当前关联
		以便计数,然后输出"InstType 当前关联的文件类型"这行是第几行(由1开始数),如
		    InstType 关联所有格式文件
			InstType 关联所有视频文件
			InstType 关联所有音频文件
			InstType 取消关联所有文件
			InstType 当前关联的文件类型-----这里是第5行

	3.  若"InstType 当前关联"是第3行,就将此头文件里面的!macro CheckSection 里的IntOp $0 $0 | 16这行改为"IntOp $0 $0 | 4",就是将$0的二进制值或4的二进制值100,就是将第三行InstType置1,选中它.
		若"InstType 当前关联"是第4行,就将此头文件里面的!macro CheckSection 里的IntOp $0 $0 | 16这行改为"IntOp $0 $0 | 8",8就是二进制1000,就是选中1000的第4行.
		若是第5行就是16(10000),第六行就是32(100000)....

		然后再改"IntOp $0 $0 & 31"这行,如果"InstType 当前关联"是第3行就改为"IntOp $0 $0 & 3",就是$0 &(逻辑与的符号) 011,就是其他InstType不变,当前关联那个设0取消选择
		是第4行就改为"IntOp $0 $0 & 7"(7就是0111);第5行就改为"IntOp $0 $0 & 15"(15就是01111);第6行就改为"IntOp $0 $0 & 31"

	4.  记下你要检查的Section所在开头的"Section "Real 视频" REAL_V"的第二参数REAL_V,改为${REAL_V}作为CheckSection里的第一个参数

	5.  然后将要检测的扩展名列表如(rmvb,rm,rmx,rm33j,rms,rv,rvx)作为第二参数,如果此程序关联了其中任何一个扩展名就会认为
		关联了这个Section,就会勾上这个Section.

	6.  然后在Function .onInit区段加入下面代码:
	*****************************
	ReadRegStr $0 HKCR "Back.${Project}" ""
	StrCmp $0 "" check_skip
	InstTypeSetText 4 "当前关联的文件类型"
	!insertmacro CheckSection ${REAL_V} rmvb,rm,rmx,rm33j,rms,rv,rvx    ;这里是检查文件rmvb,rm,rmx,rm33j,rms,rv,rvx,然后决定是否勾上 "Section "Real 视频" REAL_V"

	;....这里放更多的CheckSection

	SetCurInstType 4
	goto init_end
	check_skip:
	InstTypeSetText 4 ""
	SetCurInstType 0
	init_end:
	*****************************

闲聊:

本来只是想做一个关联媒体文件的头,就是多带"对象类型 对象CLSID"的!macro Assoc_Media,不过考虑到
很多普通文件都没有这两个参数,如果使用起来就要打
!insertmacro Assoc "jpg" "jpgfile" "JPEG图像" "$INSTDIR\ACDSee.exe" "$INSTDIR\Icon.ico" "" ""
要多打后面两对空字符串填满参数个数,很不方便.
于是将代码复制粘贴改了下,做了个没有参数的!macro Assoc,方便平时使用.^_^.

回想这个代码,关联部分比较简单,填满一堆ReadReg,WriteReg,DeleteReg就行.
后来突发奇想要搞个参数列表输入("rmvb,rm,ra,rv"),于是参照帮助文件里面的"Get command line parameters"写了
个参数列表分析的,不过出现了label,这个东西不能在一个程序里面重复使用,
于是痛苦地用将它们转换成logiclib格式.@_@.花了整个下午~终于试了出来了~唉~~~~

参考:

Engine的IMEfunc.nsh(输入法安装的)			-----logiclib思想.
Monica的KMPlayer.iss(KMPlayer汉化版)		-----注册表部分:如何关联一个文件.
Youth9999的Assoc.nsi(像暴风I的文件关联工具) -----用"!macro 参数表"实现模块化.
NSIS帮助文档的"Get command line parameters"	-----如何分离字符串.
*****************************

	希望大家用的顺手!
	 	 
	 	 
*****************************/

!ifndef Ass_Str
!define Ass_Str "打开(&O)"
!endif
!ifndef Ass_Str_Media
!define Ass_Str_Media "播放(&P)"
!endif

!include "logiclib.nsh"


/*********关联一般文件*********/
!macro Assoc EXT TYPE DESC OPENEXE ICO
Push $1
Push $2
!ifdef EchoUnSources
DetailPrint '!insertmacro UnAssoc ${ext}'
!endif
;*********分离","号各字串的函数*********
Push $R0  ;输入字符串
Push $R1  ;内循环计数
Push $R2  ;由此开始截取字符串
Push $R3  ;字符串长度
Push $R4  ;截出单个字符
Push $R5  ;截出字符串(结果)
StrCpy $R0 ${ext}
StrCpy $R1 1
StrCpy $R2 0
StrLen $R3 $R0
${Do}
    ${Do}
	StrCpy $R4 $R0 1 $R1
	${ifThen} $R1 > $R3 ${|} ${ExitDo} ${|}
	IntOp $R1 $R1 + 1
    ${LoopUntil} $R4 == ','
IntOp $R1 $R1 - 1
IntOp $R6 $R1 - $R2
StrCpy $R5 $R0 $R6 $R2

;截出字符串结果为$R5在此输出
ReadRegStr $1 HKCR "Back.${Project}" ".$R5"
${if} "$1" == ""
	ReadRegStr $2 HKCR ".$R5" ""
	${if} "$2" == ""
	WriteRegStr HKCR "Back.${Project}" ".$R5" "_Blank_"
	${Else}
	WriteRegStr HKCR "Back.${Project}" ".$R5" "$2"   ;备份该扩展名
	${EndIf}
${EndIf}
DeleteRegKey HKCU "Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.${ext}" ;删除旧关联
DeleteRegKey HKCR ".$R5" ;删除旧关联
!ifdef Echo
DetailPrint '正在关联*.$R5文件类型为"${desc}"...'
!endif
WriteRegStr HKCR ".$R5" "" "${Project}.${type}"
;截出字符串结果为$R5在此输出-完毕

IntOp $R1 $R1 + 2
IntOp $R2 $R1 - 1
${LoopUntil} $R1 > $R3

Pop $R5
Pop $R4
Pop $R3
Pop $R2
Pop $R1
Pop $R0
;*********分离","号各字串的函数完毕*********

WriteRegStr HKCR ".${ext}" "" "${Project}.${type}"
WriteRegStr HKCR "${Project}.${type}" "" "${desc}"
WriteRegStr HKCR "${Project}.${type}\shell" "" open
WriteRegStr HKCR "${Project}.${type}\shell\open" "" "${Ass_Str}"
WriteRegStr HKCR "${Project}.${type}\shell\open\command" "" '${openexe} "%1"'
${if} "${ico}" == "" ;如果不指定图标则使用默认图标
	WriteRegStr HKCR "${Project}.${type}\DefaultIcon" "" "${openexe}"
${Else}
	WriteRegStr HKCR "${Project}.${type}\DefaultIcon" "" "${ico}"
${EndIf}
WriteRegStr HKCR "Back.${Project}" "" "1"  ;标记有关联文件
Pop $1
Pop $2
!macroend

/*********关联媒体文件*********/
!macro Assoc_Media EXT TYPE DESC OPENEXE ICO CONTENTTYPE CLSID
Push $1
Push $2
!ifdef EchoUnSources
DetailPrint '!insertmacro UnAssoc ${ext}'
!endif
;*********分离","号各字串的函数*********
Push $R0  ;输入字符串
Push $R1  ;内循环计数
Push $R2  ;由此开始截取字符串
Push $R3  ;字符串长度
Push $R4  ;截出单个字符
Push $R5  ;截出字符串(结果)
StrCpy $R0 ${ext}
StrCpy $R1 1
StrCpy $R2 0
StrLen $R3 $R0
${Do}
    ${Do}
	StrCpy $R4 $R0 1 $R1
	${ifThen} $R1 > $R3 ${|} ${ExitDo} ${|}
	IntOp $R1 $R1 + 1
    ${LoopUntil} $R4 == ','
IntOp $R1 $R1 - 1
IntOp $R6 $R1 - $R2
StrCpy $R5 $R0 $R6 $R2

;截出字符串结果为$R5在此输出
ReadRegStr $1 HKCR "Back.${Project}" ".$R5"
${if} "$1" == ""
	ReadRegStr $2 HKCR ".$R5" ""
	${if} "$2" == ""
	WriteRegStr HKCR "Back.${Project}" ".$R5" "_Blank_"
	${Else}
	WriteRegStr HKCR "Back.${Project}" ".$R5" "$2"   ;备份该扩展名
	${EndIf}
${EndIf}
DeleteRegKey HKCU "Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.${ext}" ;删除旧关联
DeleteRegKey HKCR ".$R5" ;删除旧关联
!ifdef Echo
DetailPrint '正在关联*.$R5文件类型为"${desc}"...'
!endif
WriteRegStr HKCR ".$R5" "" "${Project}.${type}"
;截出字符串结果为$R5在此输出-完毕

IntOp $R1 $R1 + 2
IntOp $R2 $R1 - 1
${LoopUntil} $R1 > $R3

Pop $R5
Pop $R4
Pop $R3
Pop $R2
Pop $R1
Pop $R0
;*********分离","号各字串的函数完毕*********

WriteRegStr HKCR "${Project}.${type}" "" "${desc}"
WriteRegStr HKCR "${Project}.${type}\shell" "" open
WriteRegStr HKCR "${Project}.${type}\shell\open" "" "${Ass_Str_Media}"
WriteRegStr HKCR "${Project}.${type}\shell\open\command" "" '${openexe} "%1"'
${if} "${ico}" == "" ;如果不指定图标则使用默认图标
	WriteRegStr HKCR "${Project}.${type}\DefaultIcon" "" "${openexe}"
	${Else}
	WriteRegStr HKCR "${Project}.${type}\DefaultIcon" "" "${ico}"
${EndIf}

${if} "${ContentType}" != ""
	WriteRegStr HKCR "${Project}.${type}" "Content Type" "${ContentType}"
	WriteRegStr HKCR "MIME\Database\Content Type\${ContentType}" "Extension" ".${ext}"
	WriteRegStr HKCR "MIME\Database\Content Type\${ContentType}" "CLSID" "${CLSID}"
${EndIf}
WriteRegStr HKCR "Back.${Project}" "" "1"  ;标记有关联文件
Pop $1
Pop $2
!macroend

/*********删除文件关联*********/
!macro UnAssoc EXT

Push $1  ;${Project}.Back
Push $2  ;type
Push $3  ;Content Type
Push $4  ;${Project}的字长度
Push $5  ;type按$4截后

StrLen $4 ${Project}
;*********分离","号各字串的函数*********
Push $R0  ;输入字符串
Push $R1  ;内循环计数
Push $R2  ;由此开始截取字符串
Push $R3  ;字符串长度
Push $R4  ;截出单个字符
Push $R5  ;截出字符串(结果)
StrCpy $R0 ${ext}
StrCpy $R1 1
StrCpy $R2 0
StrLen $R3 $R0
${Do}
    ${Do}
	StrCpy $R4 $R0 1 $R1
	${ifThen} $R1 > $R3 ${|} ${ExitDo} ${|}
	IntOp $R1 $R1 + 1
    ${LoopUntil} $R4 == ','
IntOp $R1 $R1 - 1
IntOp $R6 $R1 - $R2
StrCpy $R5 $R0 $R6 $R2

;**********修改以下代码要谨慎!**********
;截出字符串结果为$R5在此输出
ReadRegStr $1 HKCR "Back.${Project}" ".$R5"  ;读备份
ReadRegStr $2 HKCR ".$R5" ""  ;读现在的
StrCpy $5 $2 $4
${if} "$1" == ""
	!ifdef UnEcho
	DetailPrint '此程序没有关联*.$R5,不需要取消...'
	!endif
${Else}
	!ifdef UnEcho
	DetailPrint '正在取消文件类型*.$R5的关联...'
	!endif
	ReadRegStr $3 HKCR "$2" "Content Type"  ;读有没对象类型
	${if} "$5" == ${Project}
		;这个${if}检测不可缺少,有一次我就是没有加它,所以将所有扩展名的注册表项都删除了,要重装才行,惨!好在重装容易-_-!
		DeleteRegValue HKCR ".$R5" "" ;删除扩展名关联(修改此处要谨慎!)
		DeleteRegKey /ifempty HKCR ".$R5" ;删除扩展名关联(修改此处要谨慎!)
		DeleteRegKey HKCU "Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.$R5" ;删除关联(修改此处要谨慎!)
		DeleteRegKey HKCR "$2" ;删除扩展类型关联(修改此处要谨慎!)
		DeleteRegKey HKCR "MIME\Database\Content Type\$3" ;删除MIME关联(修改此处要谨慎!)
	${EndIf}
	!ifdef Backup
		${if} "$1" == "_Blank_"  ;如果备份有"_Blank_",证明已经关联,但没有旧类型.
			WriteRegStr HKCR ".$R5" "" ""
		${Else}
			WriteRegStr HKCR ".$R5" "" "$1"
		${EndIf}
	!endif
	DeleteRegValue HKCR "Back.${Project}" ".$R5"



${EndIf}
;**********修改以上代码要谨慎!**********

;截出字符串结果为$R5在此输出-完毕

IntOp $R1 $R1 + 2
IntOp $R2 $R1 - 1
${LoopUntil} $R1 > $R3

Pop $R5
Pop $R4
Pop $R3
Pop $R2
Pop $R1
Pop $R0
;*********分离","号各字串的函数完毕*********
Pop $5
Pop $4
Pop $3
Pop $2
Pop $1

!macroend

!macro CheckSection SECTION_NAME EXT
Push $1  ;${Project}的字长度
Push $2  ;正确关联的次数
StrLen $1 ${Project}
StrCpy $2 0
;*********分离","号各字串的函数*********
Push $R0  ;输入字符串
Push $R1  ;内循环计数
Push $R2  ;由此开始截取字符串
Push $R3  ;字符串长度
Push $R4  ;截出单个字符
Push $R5  ;截出字符串(结果)
StrCpy $R0 ${ext}
StrCpy $R1 1
StrCpy $R2 0
StrLen $R3 $R0
${Do}
    ${Do}
	StrCpy $R4 $R0 1 $R1
	${ifThen} $R1 > $R3 ${|} ${ExitDo} ${|}
	IntOp $R1 $R1 + 1
    ${LoopUntil} $R4 == ','
IntOp $R1 $R1 - 1
IntOp $R6 $R1 - $R2
StrCpy $R5 $R0 $R6 $R2
;**********修改以下代码要谨慎!**********
;截出字符串结果为$R5在此输出
Push $0
ReadRegStr $0 HKCR ".$R5" ""
StrCpy $0 $0 $1    ;-----------是在.${EXT}截取${Project}字样的意思.
StrCmp $0 ${Project} +1 +2
IntOp $2 $2 + 1
;**********修改以上代码要谨慎!**********

;截出字符串结果为$R5在此输出-完毕

IntOp $R1 $R1 + 2
IntOp $R2 $R1 - 1
${LoopUntil} $R1 > $R3
Pop $R5
Pop $R4
Pop $R3
Pop $R2
Pop $R1
Pop $R0
;*********分离","号各字串的函数完毕*********
StrCmp $2 0 +5
SectionGetInstTypes "${SECTION_NAME}" $0
IntOp $0 $0 | 16    	 ;-------------------------要改这里,具体看说明
SectionSetInstTypes "${SECTION_NAME}" $0
Goto +4
SectionGetInstTypes "${SECTION_NAME}" $0
IntOp $0 $0 & 31    	 ;-------------------------要改这里,具体看说明
SectionSetInstTypes "${SECTION_NAME}" $0
Pop $2
Pop $1
Pop $0
!macroend

引用 Assoc例子.nsi 的内容:

/*
一个关联媒体文件的工具
编写:Ansifa
2008.2.14
注意,头代码区块顺序不能改变,否则会出现错误.

要关联的程序名在Function .onInit里面定义,对不同的需要不同的关联的程序名.请自行修改
*/
##### 基础部分 #######
SetCompressor /SOLID lzma
SetCompress force
XPStyle on
ShowInstDetails show
Name "Assoc"
OutFile "Assoc.EXE"
;!define MUI_ICON "图标.ico"
##### 变量定义 #######
Var Me  ;此程序名
Var exe ;要关联的播放软件
!define Project MyMPC					;工程名称,不同软件要更改

!define Ass_Str "打开(&O)"              ;定义关联普通文件的打开方式字串
!define Ass_Str_Media "播放(&P)"        ;定义关联媒体文件的打开方式字串
##### 头文件 #######
!include "Assoc.nsh"
!include "MUI.nsh"
##### 界面字串定义 #######
Caption "${Project} 文件关联向导"
BrandingText "${Project} 文件关联向导"
!define MUI_PAGE_HEADER_TEXT "文件关联"
!define MUI_PAGE_HEADER_SUBTEXT "请选择要关联到 ${Project} 的文件类型(如果去掉勾选会取消当前关联)."
!define MUI_COMPONENTSPAGE_TEXT_DESCRIPTION_TITLE "文件类型描述:"
!define MUI_COMPONENTSPAGE_TEXT_DESCRIPTION_INFO "移动你的鼠标指针到各文件类型选择框之上,便可见到它的描述。"
#####页面#######
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_INSTFILES
#####外观定义#######
SetFont "tahoma" 8
##### Assoc.nsh 开关定义 #######
!define Echo ""  ;回显关联动作
;!define UnEcho ""  ;回显取消关联动作(默认不需要)
##### 将icon文件夹下的图标嵌入生成的代码头 #######
##### 语言文件 #######
!insertmacro MUI_LANGUAGE "SimpChinese"
##### 类型 #######
InstType 关联所有格式文件
InstType 关联所有视频文件
InstType 关联所有音频文件
InstType 取消关联所有文件
InstType 当前关联的文件类型
##### 版本信息 #######
VIProductVersion "1.0.0.0"
VIAddVersionKey /LANG=2052 "ProductName" "${Project} 文件关联向导"
VIAddVersionKey /LANG=2052 "Comments" "编写:Ansifa(Ansifa@163.com)"
VIAddVersionKey /LANG=2052 "CompanyName" "AIR Studio"
VIAddVersionKey /LANG=2052 "LegalTrademarks" "AIR Studio"
VIAddVersionKey /LANG=2052 "LegalCopyright" "版权所有 2008 Ansifa"
VIAddVersionKey /LANG=2052 "FileDescription" "${Project} 文件关联向导"
VIAddVersionKey /LANG=2052 "OriginalFilename" "Assoc.EXE"
VIAddVersionKey /LANG=2052 "InternalName" "Assoc.EXE"
VIAddVersionKey /LANG=2052 "FileVersion" "1.0.0.0"

########################### Section 开始 ######
Section - ;此隐藏区段用于清零备份信息及识别信息
Call Restore
SectionEnd

;	下面语句的格式:
;	!macro Assoc_Media 文件扩展名列表 文件类型 描述 打开方式 默认图标 对象类型 对象CLSID
;	!macro Assoc 文件扩展名列表 文件类型 描述 打开方式 默认图标 对象类型

;"$Me,1";"$Me,2"...这些代表icon文件夹下的第1;2...个图标,它们将嵌入此代码输出的程序.


SectionGroup /e "Real 媒体"
	SectionGroup /e "Real 媒体" REAL
	Section "Real 视频" REAL_V
	SectionIn 1 2
	!insertmacro Assoc_Media rmvb "RMVB" "RealMedia 可变速率媒体文件" $exe "$Me" "video/vnd.rn-realmedia" "{CFCDAA03-8BE4-11CF-B84B-0020AFBBCCFA}"
	!insertmacro Assoc_Media "rm,rmx,rm33j,rms" "RM" "RealMedia 媒体文件" $exe "$Me" "video/vnd.rn-realmedia" "{CFCDAA03-8BE4-11CF-B84B-0020AFBBCCFA}"
	!insertmacro Assoc_Media rv,rvx "RV" "RealVideo 视频剪辑" $exe "$Me" "audio/vnd.rn-realmedia" "{CFCDAA03-8BE4-11CF-B84B-0020AFBBCCFA}"
	SectionEnd
	Section "Real 音频" REAL_A
	SectionIn 1 3
	!insertmacro Assoc_Media ram,rmm "RAM" "RealMedia RAM 元文件" $exe "$Me" "audio/vnd.rn-realaudio" "{CFCDAA03-8BE4-11CF-B84B-0020AFBBCCFA}"
	!insertmacro Assoc_Media ra,rax "RA" "RealMedia 音频文件" $exe "$Me" "audio/vnd.rn-realaudio" "{CFCDAA03-8BE4-11CF-B84B-0020AFBBCCFA}"
	SectionEnd
	Section "Real 脚本" REAL_S
	SectionIn 1 2 3
	!insertmacro Assoc_Media rp "RP" "RealPix 媒体文件" $exe "$Me" "image/vnd.rn-realpix" "{CFCDAA03-8BE4-11CF-B84B-0020AFBBCCFA}"
	!insertmacro Assoc_Media rt "RT" "RealText 脚本文件" $exe "$Me" "image/vnd.rn-realpix" "{CFCDAA03-8BE4-11CF-B84B-0020AFBBCCFA}"
	SectionEnd
	SectionGroupEnd
	
SectionGroupEnd

SectionGroup /e "MPEG 媒体"
	SectionGroup /e "MPEG 音频"
		Section "AAC-MPEG Layer 4 音频" AAC_A
		SectionIn 1 3
		!insertmacro Assoc aac,a4c,m4a "MP4" "AAC-MPEG Layer 4 音频" $exe "$Me"
		SectionEnd
		Section "MPEG Layer 3 音频" MP3_A
		SectionIn 1 3
		!insertmacro Assoc mp3,m3a,mpa "MP3" "MPEG Layer 3 音频文件" $exe "$Me"
		SectionEnd
		Section "MPEG Layer 2 音频" MP2_A
		SectionIn 1 3
		!insertmacro Assoc mp2,m2a "MP2" "MPEG Layer 2 音频文件" $exe "$Me"
		SectionEnd
		Section "MPEG Layer 1 音频" MP1_A
		SectionIn 1 3
		!insertmacro Assoc mp1,m1a "MP1" "MPEG Layer 1 音频文件" $exe "$Me"
		SectionEnd
		Section "AC3/DTS DVD 音频" AC3_A
		SectionIn 1 3
		!insertmacro Assoc ac3,dts "AC3" "DVD 音频文件" $exe "$Me"
		SectionEnd
	SectionGroupEnd
	SectionGroup /e "MPEG 视频"
		Section "MPEG-1 视频" MP1
		SectionIn 1 2
		!insertmacro Assoc mpg,mpeg,mpe "MPEG" "MPEG-1 视频文件" $exe "$Me"
		!insertmacro Assoc tpr,pva,pss,m1v "MPEG" "MPEG-1 视频文件" $exe "$Me"
		SectionEnd
		Section "MPEG-2 视频" MP2
		SectionIn 1 2
		!insertmacro Assoc ts,tp,mpv2,mp2v,m2v "MP2" "MPEG-2 视频文件" $exe "$Me"
		SectionEnd
		Section "MPEG-4 视频" MP4
		SectionIn 1 2
		!insertmacro Assoc m4v,m4p,m4b "MP4" "MPEG-4 视频文件" $exe "$Me"
		!insertmacro Assoc mp4,3gp,3gp2,3gpp,3g2 "MP4" "MPEG-4 视频文件" $exe "$Me"
		SectionEnd
		Section "VCD 视频" VCD
		SectionIn 1 2
		!insertmacro Assoc dat "VCD" "VCD 视频文件" $exe "$Me"
		SectionEnd
		Section "DVD 视频" DVD
		SectionIn 1 2
		!insertmacro Assoc vob "DVD" "DVD 视频文件" $exe "$Me"
		!insertmacro Assoc ifo "IFO" "DVD 字幕文件" $exe "$Me"
		SectionEnd
	SectionGroupEnd
SectionGroupEnd

Section -
System::Call 'Shell32::SHChangeNotify(i 0x8000000, i 0, i 0, i 0)'
SectionEnd

########################### Section结束 -> Function Restore 开始 ######

;文件关联恢复宏,用于恢复原有文件关联
Function Restore
!insertmacro UnAssoc rmvb
!insertmacro UnAssoc rm,rmx,rm33j,rms
!insertmacro UnAssoc ra,rax
!insertmacro UnAssoc rv,rvx
!insertmacro UnAssoc ram,rmm
!insertmacro UnAssoc rp
!insertmacro UnAssoc rt
!insertmacro UnAssoc smi,smil
!insertmacro UnAssoc ssm
!insertmacro UnAssoc sdp
!insertmacro UnAssoc aac,a4c,m4a
!insertmacro UnAssoc mp3,m3a,mpa
!insertmacro UnAssoc mp2,m2a
!insertmacro UnAssoc mp1,m1a
!insertmacro UnAssoc ac3,dts
!insertmacro UnAssoc mpg,mpeg,mpe
!insertmacro UnAssoc tpr,pva,pss,m1v
!insertmacro UnAssoc ts,tp,mpv2,mp2v,m2v
!insertmacro UnAssoc m4v,m4p,m4b
!insertmacro UnAssoc mp4,3gp,3gp2,3gpp,3g2
!insertmacro UnAssoc dat
!insertmacro UnAssoc vob
!insertmacro UnAssoc ifo
DeleteRegValue HKCR "Back.${Project}" ""
FunctionEnd

########################### Function Restore 结束 -> insertmacro 开始 ######

;在组件页的描述. 注意各文件扩展名间要适当加空格如*.aac ; *.a4c ; *.m4a,
;否则程序会认为是长单词而不换行的,那样就看不到长的内容了,汗...-_-!!!

!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
!insertmacro MUI_DESCRIPTION_TEXT ${REAL_V} "RealPlayer 视频文件 ; 关联扩展名  ( *.rmvb ; *.rm ; *.rmx ; *.rm33j ; *.rms ; *.rv ; *.rvx )."
!insertmacro MUI_DESCRIPTION_TEXT ${REAL_A} "RealPlayer 音频文件 ; 关联扩展名  ( *.ra ; *.rax ; *.ram ; *.rmm )."
!insertmacro MUI_DESCRIPTION_TEXT ${REAL_S} "RealPlayer 脚本文件 ; 关联扩展名  ( *.rp ; *.rt )."
!insertmacro MUI_DESCRIPTION_TEXT ${AAC_A} "AAC-MPEG Layer 4 音频文件,关联扩展名 ( *.aac ; *.a4c ; *.m4a )."
!insertmacro MUI_DESCRIPTION_TEXT ${MP3_A} "MPEG Layer 3 音频文件,关联扩展名 ( *.mp3 ; *.m3a ; *.mpa )."
!insertmacro MUI_DESCRIPTION_TEXT ${MP2_A} "MPEG Layer 2 音频文件,关联扩展名 ( *.mp2 ; *.m2a )."
!insertmacro MUI_DESCRIPTION_TEXT ${MP1_A} "MPEG Layer 1 音频文件,关联扩展名 ( *.mp1 ; *.m1a )."
!insertmacro MUI_DESCRIPTION_TEXT ${AC3_A} "DVD 音频文件,关联扩展名 ( *.ac3 ; *.dts )."
!insertmacro MUI_DESCRIPTION_TEXT ${MP1} "MPEG-1 视频文件,关联扩展名 ( *.mpg ; *.mpeg ; *.mpe ; *.tpr ; *.pva ; *.pss ; *.m1v )."
!insertmacro MUI_DESCRIPTION_TEXT ${MP2} "MPEG-2 视频文件,关联扩展名 ( *.ts ; *.tp ; *.mpv2 ; *.mp2v ; *.m2v )."
!insertmacro MUI_DESCRIPTION_TEXT ${MP4} "MPEG-4 视频文件,关联扩展名 ( *.m4v ; *.m4p ; *.m4b ; *.mp4 ; *.3gp ; *.3gp2 ; *.3gpp ; *.3g2 )."
!insertmacro MUI_DESCRIPTION_TEXT ${VCD} "VCD 视频文件,关联扩展名 ( *.dat )."
!insertmacro MUI_DESCRIPTION_TEXT ${DVD} "DVD 视频文件及 DVD 字幕,关联扩展名 ( *.vob ; *.ifo )."

!insertmacro MUI_FUNCTION_DESCRIPTION_END


############################################ Function .onInit 开始 ######
Function .onInit
System::Call 'kernel32::GetModuleFileNameA(i 0, t .R0, i 1024) i r1' ;获得此程序自身名称
StrCpy $Me $R0 ;获得此程序自身名称

;*********************************
;这句定义要关联的播放软件路径,大家自己改改.
StrCpy $exe '$EXEDIR\Assoc.EXE'
;*********************************

;检查是否在KMPlayer目录
	IfFileExists $exe Location_ok
	MessageBox MB_OK|MB_ICONSTOP "你未安装 ${Project} 或本程序未放置在 ${Project} 安装目录,不能运行此关联程序。"
	Abort
	Location_ok:

####################################################命令行处理块############
Call GetParameters ;获得命令行参数列表
Pop $R1
	###########在命令行参数列表寻找可用参数
	Push "$R1"      ;在命令行参数列表$R1找 h 或者 help ,有就显示帮助信息框
	Push "h"
	Call SearchString
	Pop $1
	Push "$R1"      ;在命令行参数列表$R1找 ?,有就显示帮助信息框
	Push "?"
	Call SearchString
	Pop $2
	Push "$R1"      ;在命令行参数列表$R1找 r,有就取消且恢复关联
	Push "r"
	Call SearchString
	Pop $3
	Push "$R1"      ;在命令行参数列表$R1找 f,有就关联所有支持文件
	Push "f"
	Call SearchString
	Pop $4
	Push "$R1"      ;在命令行参数列表$R1找 v,有就关联所有支持视频文件
	Push "v"
	Call SearchString
	Pop $5
	Push "$R1"      ;在命令行参数列表$R1找 a,有就关联所有支持音频文件
	Push "a"
	Call SearchString
	Pop $6
	###########在命令行参数列表寻找可用参数完毕,结果存于$1;$2;$3;$4;$5;$6

StrCmp $1$2$3$4$5$6 "" NoCMD_AND_CMDOver   ;如果$1;$2;$3;$4;$5;$6同时为空,则$1$2$3$4$5$6为空.所以当作没有命令行处理
SetSilent silent ;如果有命令行即进入无界面模式
;显示帮助信息
	StrCmp $1$2 "" NoHelp   ;如果$1;$2同时为空,则$1$2为空.所以当作没有Help命令行处理
	MessageBox MB_ICONINFORMATION|MB_OK '命令行用法提示:$\n$Me [参数列表]$\n$\n参数列表(支持多个参数同时使用,若下面的字符出现在参数任意位置,则认为有此参数):$\n$\nf$\t$\t关联所有支持的文件类型$\nv$\t$\t关联所有支持的视频文件$\na$\t$\t关联所有支持的音频文件$\nr$\t$\t取消所有支持类型文件关联$\nh help ?$\t显示命令行帮助(此信息框).$\n$\n参数相容性:$\n* "h help ?"帮助参数可以与任意其他参数连用.程序将先显示帮助再执行文件关联.$\n* 如果多个参数连用按照优先顺序挑选一个执行: h,r,f,v,a .其余参数将被忽略.$\n$\n用法示例:$\t$\t$\t等效功能:$\n$Me ?$\t显示命令行帮助(此信息框).$\n$Me r$\t取消文件关联$\n$Me hr$\t显示命令行帮助+取消文件关联$\n$Me va$\t关联视频文件(v参数优先于a)$\n$Me fr$\t取消文件关联(r参数优先于f)$\n$\n格式示例:$\t$\t$\t等效功能:$\n$Me rst $\t取消文件关联(检索到有字母r且没其他参数,所以执行取消关联)$\n$Me fr$\t取消文件关联(参数间可以连着写)$\n$Me f r$\t取消文件关联(参数间可以分开写)$\n$Me /f /r$\t取消文件关联(传统参数形式)$\n$Me -f -r$\t取消文件关联(传统参数形式)'
	NoHelp:
;取消并恢复旧关联
	StrCmp $3 "" NoRestore
	Call Restore
	System::Call 'Shell32::SHChangeNotify(i 0x8000000, i 0, i 0, i 0)'
	Quit
NoRestore:
;关联所有文件
	StrCmp $4 "" NoAll
	SetCurInstType 0  ;1:全部;2:视频;3:音频;4:取消
	Goto NoCMD_AND_CMDOver
	NoAll:
;关联所有视频文件
	StrCmp $5 "" NoVideo
	SetCurInstType 1  ;1:全部;2:视频;3:音频;4:取消
	NoVideo:
;关联所有音频文件
	StrCmp $6 "" NoAudio
	SetCurInstType 2  ;1:全部;2:视频;3:音频;4:取消
	Goto NoCMD_AND_CMDOver
	NoAudio:
NoCMD_AND_CMDOver:

####################################################命令行处理块完毕############
ReadRegStr $0 HKCR "Back.${Project}" ""
StrCmp $0 "" check_skip
InstTypeSetText 4 "当前关联的文件类型"
!insertmacro CheckSection ${REAL_V} rmvb,rm,rmx,rm33j,rms,rv,rvx
!insertmacro CheckSection ${REAL_A} ra,rax,ram,rmm
!insertmacro CheckSection ${REAL_S} rp,rt
!insertmacro CheckSection ${AAC_A} aac,a4c,m4a
!insertmacro CheckSection ${MP3_A} mp3,m3a,mpa
!insertmacro CheckSection ${MP2_A} mp2,m2a
!insertmacro CheckSection ${MP1_A} mp1,m1a
!insertmacro CheckSection ${AC3_A} ac3,dts
!insertmacro CheckSection ${MP1} mpg,mpeg,mpe,tpr,pva,pss,m1v
!insertmacro CheckSection ${MP2} ts,tp,mpv2,mp2v,m2v
!insertmacro CheckSection ${MP4} m4v,m4p,m4b,mp4,3gp,3gp2,3gpp,3g2
!insertmacro CheckSection ${VCD} dat
!insertmacro CheckSection ${DVD} vob,ifo
SetCurInstType 4
goto init_end
check_skip:
InstTypeSetText 4 ""
SetCurInstType 0
init_end:

FunctionEnd


;获取命令行参数
Function GetParameters
Push $R0
Push $R1
Push $R2
Push $R3
StrCpy $R2 1
StrLen $R3 $CMDLINE
StrCpy $R0 $CMDLINE $R2
StrCmp $R0 '"' 0 +3
StrCpy $R1 '"'
Goto loop
StrCpy $R1 " "
loop:
IntOp $R2 $R2 + 1
StrCpy $R0 $CMDLINE 1 $R2
StrCmp $R0 $R1 get
StrCmp $R2 $R3 get
Goto loop
get:
IntOp $R2 $R2 + 1
StrCpy $R0 $CMDLINE 1 $R2
StrCmp $R0 " " get
StrCpy $R0 $CMDLINE "" $R2
Pop $R3
Pop $R2
Pop $R1
Exch $R0
FunctionEnd
;寻找一个字符串是否存在于另一个字符串
Function SearchString
Exch $R1
Exch
Exch $R2
Push $R3
Push $R4
Push $R5
StrLen $R3 $R1
StrCpy $R4 0
loop:
StrCpy $R5 $R2 $R3 $R4
StrCmp $R5 $R1 done
StrCmp $R5 "" done
IntOp $R4 $R4 + 1
Goto loop
done:
StrCpy $R1 $R2 "" $R4
Pop $R5
Pop $R4
Pop $R3
Pop $R2
Exch $R1
FunctionEnd

命令行用法提示:
Assoc.EXE [参数列表]

参数列表(支持多个参数同时使用):

/f 关联所有支持的文件类型
/v 关联所有支持的视频文件
/a 关联所有支持的音频文件
/r 取消所有支持类型文件关联
/h /help /? 显示命令行帮助(此信息框).

参数相容性:
* "/h /help /?"帮助参数可以与任意其他参数连用.程序将先显示帮助再执行文件关联.
* 如果多个参数连用按照优先顺序挑选一个执行: /h,/r,/f,/v,/a .其余参数将被忽略.

示例: 等效功能:
Assoc.EXE /? 显示命令行帮助(此信息框).
Assoc.EXE /r 取消文件关联
Assoc.EXE /h /r 显示命令行帮助+取消文件关联
Assoc.EXE /v /a 关联视频文件
Assoc.EXE /f /r 取消文件关联