Check existing file associations
Is there a way to check if a certain filetype is already associated with a program?
12 posts
!include Win\COM.nsh
!include LogicLib.nsh
!define ASSOCF_NOFIXUPS 0x0100
!define ASSOCF_IGNOREBASECLASS 0x0200
!define ASSOCSTR_COMMAND 1
!define ASSOCKEY_SHELLEXECCLASS 1
!define AT_FILEEXTENSION 0
!define AL_EFFECTIVE 1
StrCpy $2 ".txt"
; Choose one of these 3 methods, IApplicationAssociationRegistration is Vista+ and AssocQuery* is IE5/Win98SE/2000+
!insertmacro ComHlpr_CreateInProcInstance ${CLSID_ApplicationAssociationRegistration} ${IID_IApplicationAssociationRegistration} r1 ""
${If} $1 <> 0
${IApplicationAssociationRegistration::QueryCurrentDefault} $1 '("$2",${AT_FILEEXTENSION},${AL_EFFECTIVE},0r3).r0'
DetailPrint "HRESULT=$0,ProgId WStr pointer=$3"
${If} $0 = 0
System::Call *$3(&w1024.r0)
System::Call OLE32::CoTaskMemFree(ir3)
DetailPrint "SUCCESS: ProgId=$0"
${EndIf}
${IUnknown::Release} $1 ""
${EndIf}
System::Call 'SHLWAPI::AssocQueryString(i${ASSOCF_NOFIXUPS}|${ASSOCF_IGNOREBASECLASS},i${ASSOCSTR_COMMAND},t"$2",i0,t.r1,*i1024)i.r0'
DetailPrint "HRESULT=$0,Cmd=$1"
System::Call 'SHLWAPI::AssocQueryKey(i${ASSOCF_NOFIXUPS},i${ASSOCKEY_SHELLEXECCLASS},t"$2",i0,*i0r1)i.r0'
DetailPrint "HRESULT=$0"
${If} $0 = 0
System::Call 'ADVAPI32::RegCloseKey(i$1)'
DetailPrint "SUCCESS: $2 is registered"
${EndIf}
I believe that code should work on 2.46 but I only tested on 3.0, anyway, the AssocQueryString line is probably the method you want...Originally Posted by empezar View PostI can't get that code to work. What is COM.nsh?
And you used ASSOCF_IGNOREBASECLASS? Which extension are you checking and which OS is this?Originally Posted by empezar View PostHRESULT is always 0 even if the file is not associated, because it's always associated with either a program or the "Open with"-program.
!include LogicLib.nsh
Section
StrCpy $2 ".flac"
;BUGBUG: Should check HKLM\Software\Microsoft\Windows\CurrentVersion\Explorer\KindMap\.ext first?
ReadRegStr $0 HKCU "Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$2\UserChoice" "ProgId"
Push $0
Call Assoc_RedirectProgId
Pop $0
Push $0
Call Assoc_QueryHasKey
Pop $1
${If} $1 = 0 ; ProgId did not exist?
${OrIf} $0 == "" ;UserChoice did not exist?
ReadRegStr $0 HKCR $2 ""
Push $0
Call Assoc_RedirectProgId
Pop $0
${EndIf}
Push $0
Call Assoc_QueryProgIdDefVerb
Pop $1
${IfThen} "$0$1" != "$1$0" ${|} Goto assoc_done ${|}
StrCpy $0 "SystemFileAssociations\$2"
Push $0
Call Assoc_QueryProgIdDefVerb
Pop $1
${IfThen} "$0$1" != "$1$0" ${|} Goto assoc_done ${|}
ReadRegStr $0 HKCR $2 "PerceivedType"
${If} $0 != ""
StrCpy $0 "SystemFileAssociations\$0"
Push $0
Call Assoc_QueryProgIdDefVerb
Pop $1
${IfThen} "$0$1" != "$1$0" ${|} Goto assoc_done ${|}
${EndIf}
ReadRegStr $0 HKCR "SystemFileAssociations\$2" "PerceivedType"
${If} $0 != ""
StrCpy $0 "SystemFileAssociations\$0"
Push $0
Call Assoc_QueryProgIdDefVerb
Pop $1
${IfThen} "$0$1" != "$1$0" ${|} Goto assoc_done ${|}
${EndIf}
;BUGBUG: If we still have not found anything we are supposed to look under %ProgId/UserChoice%\Clsid\ for a GUID and its ShellFolder data, what to do after that I did not investigate
;NOTE: Last resort is to look under HKCR\*, HKCR\AllFilesystemObjects and finally HKCR\Unknown but that is not a good idea for what we are trying to detect, skipping
assoc_done:
${If} "$0$1" != "$1$0"
DetailPrint $2:PID=$0,Verb=$1
${EndIF}
SectionEnd
Function Assoc_QueryHasKey
Exch $0
Push $1
ClearErrors
EnumRegKey $1 HKCR $0 0
IfErrors 0 yes
EnumRegValue $1 HKCR $0 0
StrCpy $1 ""
IfErrors done
yes:
StrCpy $0 "1$1" ; <> 0 for checking and store subkey if found
done:
Pop $1
Exch $0
FunctionEnd
Function Assoc_QueryHasNamedValue
Exch $0 ;name
Exch
Exch $1 ;key
Push $2
Push $3
StrCpy $3 0
loop:
ClearErrors
EnumRegValue $2 HKCR $1 $3
IfErrors done
IntOp $3 $3 + 1
StrCmp $0 $2 0 loop
StrCpy $2 1
done:
StrCpy $0 $2
Pop $3
Pop $2
Pop $1
Exch $0
FunctionEnd
Function Assoc_RedirectProgId
Exch $0
Push $1
ReadRegStr $1 HKCR "$0\CurVer" ""
StrCmp $1 "" +2
StrCpy $0 $1
Pop $1
Exch $0
FunctionEnd
Function Assoc_QueryProgIdDefVerb
Exch $0
Push $1 ; save reg
Push $2
Push $0
Push "NoStaticDefaultVerb"
Call Assoc_QueryHasNamedValue
Pop $1
${If} $1 <> 0
StrCpy $0 ""
${Else}
StrCpy $1 $0
ReadRegStr $0 HKCR "$1\Shell" "" ; BUGBUG: The default verb string can contain space/comma separated verb names, parsing required
${IfThen} $0 == "" ${|} StrCpy $0 "open" ${|}
Push "$1\Shell\$0"
Call Assoc_QueryHasKey
Pop $2
${If} $2 = 0
Push "$1\Shell"
Call Assoc_QueryHasKey
Pop $2
StrCpy $0 $2 "" 1
${If} $2 <> 0
${AndIf} $0 != ""
Push "$1\Shell\$0"
Call Assoc_QueryHasKey
Pop $2
${IfThen} $2 = 0 ${|} StrCpy $0 "" ${|}
${EndIf}
${EndIf}
${EndIf}
Pop $2 ;restore reg
Pop $1
Exch $0
FunctionEnd
AssocQueryString and there is no API to Set/Remove, only query, not sure what you are looking at...Originally Posted by empezar View PostHow do I check for associations using the documented version? The Assoc* API you mentioned? I can only find information on how to SET and REMOVE associations using that thing.
OutFile "opens_by_default.exe"
; For example HTM files
Section
StrCpy $R1 htm
FileOpen $0 "$TEMP\opens_by_default.$R1" "w"
FileClose $0
System::Call "Shell32::FindExecutable(t '$TEMP\opens_by_default.$R1', i 0, t .r1)"
Delete "$TEMP\opens_by_default.$R1"
MessageBox MB_OK '$R1 files by default opens the program: : $1 '
SectionEnd