[AHK2] FileAssociate() - Works with Win10

Post your working scripts, libraries and tools
HakitoJin
Posts: 17
Joined: 02 Oct 2016, 17:20

[AHK2] FileAssociate() - Works with Win10

12 Sep 2018, 16:37

Change PlayerPath and EditorPath to paths of executables that can run mp3 files, and run the script.
Type "/useplayer" or "/useeditor" (anywhere) to change which program is associated with mp3 files.

Example usage is shown in the script, you can associate any extension with anything, but you can't associate directly to a path, paths must be stored in a label, and then you can associate an extension with that label (which can all be done in 1 line).
There is currently no way to automatically revert changes made, it has to be done manually, so use at your own risk.

I tested the script and it works fine... for me ...be my guinea pig.

Code: Select all

	PlayerPath:="C:\Program Files (x86)\The KMPlayer\KMPlayer.exe"
	EditorPath:="C:\Program Files (x86)\Audacity\audacity.exe"
	StarIcon:=A_WinDir "\System32\shell32.dll,-44"
	RecycleIcon:=A_WinDir "\System32\shell32.dll,-32"
return

:?*:/UsePlayer::
	iF FileExist(PlayerPath)
	{
		;Create a new label
		FileAssociate("CustomPlayerLabel",,PlayerPath)

		;Associate extension with an already existing label
		FileAssociate("CustomPlayerLabel",".mp3")

		;Changes icon of label (explorer requires restart)
		FileAssociate("CustomPlayerLabel",,,StarIcon)
		
		TrayTip("Using Player for mp3 files")
	}
return

:?*:/UseEditor::
	iF FileExist(EditorPath)
	{
		;Create a new label, associate the extension with it, and then change its icon
		FileAssociate("LabelForEditor",".mp3",EditorPath,RecycleIcon)
		
		TrayTip("Using Editor for mp3 files")
	}
return

/*
Associating extensions to uncompiled ahk scripts can be done like this:
FileAssociate("AutohotkeyScript",".mp3",'"C:\Program Files\AutoHotkey\AutoHotkey.exe" "C:\Script.ahk" "%1" %*')
*/

;#####################################################################################FileAssociate() -  Associates an extension with a program's registry label, which is created automatically by passing the Label and Cmd parameters, Icon being optional. 
FileAssociate(Label:="",Ext:="",Cmd:="",Icon:="") ;by Ħakito   -   https://autohotkey.com/boards/viewtopic.php?f=6&t=55638
{
	iF SubStr(Ext,1,1)!="." or StrLen(Ext)<=1 ;Weeds out faulty extensions, which must start with a period, and contain more than 1 character
		Ext:=""
	iF SubStr(Label,1,1)="." ;Weeds out faulty labels such as ".exe" which is an extension and not a label
		Label:=""
	iF Cmd!="" and RegRead("HKEY_CLASSES_ROOT\" Label,"FriendlyTypeName") ;Do not allow the modification of some important registry labels
		Cmd:=""
	SuccessLevel:=0
	iF Label
	{
		;Note that "HKEY_CLASSES_ROOT" actually writes to "HKEY_LOCAL_MACHINE\SOFTWARE\Classes"
		iF Cmd ;Path to executable
		{
			iF SubStr(Cmd,2,2)=":\" and FileExist(Cmd) ;If the command is just a simple path, then convert it into a proper run command
				Cmd:="`"" Cmd "`" `"" "%1`" %*"
			
			RegWrite Label,"REG_SZ","HKEY_CLASSES_ROOT\" Label
			RegWrite Cmd,"REG_SZ","HKEY_CLASSES_ROOT\" Label "\Shell\Open\Command"
			SuccessLevel+=1<<0 ;+1
		}
		
		iF Icon ;Path to icon
		{
			RegWrite Icon,"REG_SZ","HKEY_CLASSES_ROOT\" Label "\DefaultIcon"
			SuccessLevel+=1<<1 ;+2
		}
		
		iF Ext and RegRead("HKEY_CLASSES_ROOT\" Label "\Shell\Open\Command") ;Checks if "Label" is valid before associating the extension with it
		{
			;Backup HKEY_CLASSES_ROOT\.ext\OpenWithProgids, the function has no use for this backup currently, it's just there for peace of mind
			Loop Reg,"HKEY_CLASSES_ROOT\" Ext "\OpenWithProgids",V
				iF A_LoopRegName
					RegWrite "","REG_SZ","HKEY_CLASSES_ROOT\" Ext "\BackupOpenWithProgids",A_LoopRegName
		
			;Sets the default label for this extension
			RegWrite Label,"REG_SZ","HKEY_CLASSES_ROOT\" Ext
			RegDeleteKey "HKEY_CLASSES_ROOT\" Ext "\OpenWithProgids"
						
			;Delete "OpenWithProgids" to ensure that the default program will be used
			RegDeleteKey "HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FileExts\" Ext "\OpenWithProgids" ;The key will be automatically re-created when you open the appropriate extension
			
			;This next part deletes "UserChoice", which is harder to remove because it's protected (and it can only be created by using "Always use this app to open .ext files")
			FileDelete A_ScriptDir "\DeleteUserChoice.reg" ;Just in case the previous file didn't get deleted
			FileAppend "Windows Registry Editor Version 5.00`n[-HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FileExts\" Ext "\UserChoice]",A_ScriptDir "\DeleteUserChoice.reg"
			RunWait("Reg Import `"" A_ScriptDir "\DeleteUserChoice.reg`"",,"Hide") ;Applies the change, which deletes "UserChoice"
			FileDelete A_ScriptDir "\DeleteUserChoice.reg" ;We don't want the file laying around
			SuccessLevel+=1<<2 ;+4
		}
	}
	return SuccessLevel
	
	;You can register an application in "HKEY_CURRENT_USER\SOFTWARE\Classes\Applications", but it seems unnecessary
	;RegWrite Q ahk2File Q _ Q coreDirectory "\Glimpse.ahk2" Q _ Q "%1" Q _ "%*","REG_SZ","HKEY_CURRENT_USER\SOFTWARE\Classes\Applications\CodeFusionImage.exe\shell\open\command"

	;Other places where I found my label "CodeFusionImage":
	;HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\ApplicationAssociationToasts
	;HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.png\OpenWithProgids
	;HKEY_USERS\S-1-5-21-4017089542-160688567-4195577993-1001\SOFTWARE\Microsoft\Windows\CurrentVersion\ApplicationAssociationToasts ;These two are the same as the above I guess
	;HKEY_USERS\S-1-5-21-4017089542-160688567-4195577993-1001\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.png\OpenWithProgids

	;You can also write registry like this:
	;Run("Reg Add "  "HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.png\Key /v Name /t REG_SZ /d Data /f",,"Hide")
	;More information here   -    https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/reg-add

	;P.S. The Q is a variable that contains a quote, and _ contains space.
}
Here is what registry keys (folders) are deleted:
"HKEY_CLASSES_ROOT\.ext\OpenWithProgids"
"HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.ext\OpenWithProgids"
"HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.ext\UserChoice"

Registry values (variables) that are changed:
"HKEY_CLASSES_ROOT\.ext\(Default)"

Registry values (variables) that are created:
"HKEY_CLASSES_ROOT\Label\(Default)"
"HKEY_CLASSES_ROOT\Label\DefaultIcon\(Default)"
"HKEY_CLASSES_ROOT\Label\Shell\Open\Command\(Default)"
"HKEY_CLASSES_ROOT\.ext\BackupOpenWithProgids\*" this has no use, it's just a pointless backup

".ext" refers to the extension that you are changing, and "Label" is the label in which the run command is stored.
User avatar
mshall
Posts: 35
Joined: 13 Jul 2018, 16:42
GitHub: MattAHK

Re: [AHK2] FileAssociate() - Works with Win10

17 Oct 2018, 19:02

I tried compiling this script.
Used this as the function:
FileAssociate(Label:="AutohotkeyScript",Ext:=".ahk",Cmd:="%A_WorkingDir%\AutoHotkeyU64.exe",Icon:="")

Receiving an error. I'd like to do a 1 time install for a program that will automatically associate autohotkeys with AutoHotkeyU64.exe, but it gives a missing % error on a ton of lines, including the comments. I'm pretty sure this is a compiler error though.

Otherwise appears to work fine for non .ahk extensions.
robodesign
Posts: 714
Joined: 30 Sep 2017, 03:59
Facebook: marius.sucan
GitHub: mariussucan
Location: Romania
Contact:

Re: [AHK2] FileAssociate() - Works with Win10

25 Oct 2019, 10:26

Hello!

I made a spin-off for AHK v1.1.

Code: Select all

FileAssociate(Label:="",Ext:="",Cmd:="",Icon:="") {
; by Ħakito: https://autohotkey.com/boards/viewtopic.php?f=6&t=55638 
; modified by Marius Șucan to AHK v1.1

  ; Weeds out faulty extensions, which must start with a period, and contain more than 1 character
  iF (SubStr(Ext,1,1)!="." || StrLen(Ext)<=1)
     Ext := ""

  ; Weeds out faulty labels such as ".exe" which is an extension and not a label
  iF (SubStr(Label,1,1)=".")
     Label := ""

  If Label
     RegRead, CheckLabel, HKEY_CLASSES_ROOT\%Label%, FriendlyTypeName
  ; Do not allow the modification of some important registry labels

  iF (Cmd!="" && CheckLabel)
     Cmd := ""

  SuccessLevel:=0
  iF Label
  {
    ;Note that "HKEY_CLASSES_ROOT" actually writes to "HKEY_LOCAL_MACHINE\SOFTWARE\Classes"
    iF Cmd ;Path to executable
    {
      ; If the command is just a simple path, then convert it into a proper run command
      iF (SubStr(Cmd,2,2)=":\" && FileExist(Cmd))
         Cmd := """" Cmd """" A_Space """" "%1" """"

      RegWrite, REG_SZ, HKEY_CLASSES_ROOT\%Label%,, % Label
      RegWrite, REG_SZ, HKEY_CLASSES_ROOT\%Label%\Shell\Open\Command,, % Cmd
      SuccessLevel+=1<<0 ;+1
    }
    
    iF Icon ; Path to icon
    {
       RegWrite, REG_SZ, HKEY_CLASSES_ROOT\%Label%\DefaultIcon,, % Icon
       SuccessLevel+=1<<1 ;+2
    }

    If Label
       RegRead, CheckLabel2, HKEY_CLASSES_ROOT\%Label%\Shell\Open\Command

    ; Checks if "Label" is valid before associating the extension with it
    iF (Ext && CheckLabel2)
    {
      ; Sets the default label for this extension
      RegWrite, REG_SZ, HKEY_CLASSES_ROOT\%Ext%,, % Label
      RegDelete, HKEY_CLASSES_ROOT\%Ext%\OpenWithProgids
            
      ; Delete "OpenWithProgids" to ensure that the default program will be used
      ; The key will be automatically re-created when you open the appropriate extension
      RegDelete, HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FileExts\%Ext%\OpenWithProgids

      ; This next part deletes "UserChoice", which is harder to remove because it's protected (and it can only be created by using "Always use this app to open .ext files")
      ; Just in case the previous file didn't get deleted
      FileDelete, %A_ScriptDir%\DeleteUserChoice.reg
      regFile := "Windows Registry Editor Version 5.00`n[-HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FileExts\" Ext "\UserChoice]"
      FileAppend, % regFile, %A_ScriptDir%\DeleteUserChoice.reg
      runTarget := "Reg Import " """" A_ScriptDir "\DeleteUserChoice.reg"
      RunWait, % runTarget,, Hide
      FileDelete, %A_ScriptDir%\DeleteUserChoice.reg ; We don't want the file laying around
      SuccessLevel+=1<<2 ;+4
    }
  }
  return SuccessLevel
}


RunAdminMode() {
  If !A_IsAdmin
  {
      Try {
         If A_IsCompiled
            Run *RunAs "%A_ScriptFullPath%" /restart
         Else
            Run *RunAs "%A_AhkPath%" /restart "%A_ScriptFullPath%"

         ExitApp
      }
  }
}

Hope it works! Should be used with compiled scripts running in Admin mode.

Best regards, Marius.
-------------------------
KeyPress OSD v4: GitHub or forum. (presentation video)
Quick Picto Viewer: GitHub or forum.
AHK GDI+ expanded / compilation library (on GitHub)
My home page.
robodesign
Posts: 714
Joined: 30 Sep 2017, 03:59
Facebook: marius.sucan
GitHub: mariussucan
Location: Romania
Contact:

Re: [AHK2] FileAssociate() - Works with Win10

26 Oct 2019, 05:03

In the end, i discovered, this function is not enough. Windows 10 prevents using a security hash the change of certain file formats association solely by registry gimmicks.

Code: Select all

FileAssociate(Label,Ext,Cmd,Icon:="", batchMode:=0) {
; by Ħakito: https://autohotkey.com/boards/viewtopic.php?f=6&t=55638 
; modified by Marius Șucan to AHK v1.1

  ; Weeds out faulty extensions, which must start with a period, and contain more than 1 character
  iF (SubStr(Ext,1,1)!="." || StrLen(Ext)<=1)
     Return 0

  ; Weeds out faulty labels such as ".exe" which is an extension and not a label
  iF (SubStr(Label,1,1)=".")
     Return 0

  If Label
     RegRead, CheckLabel, HKEY_CLASSES_ROOT\%Label%, FriendlyTypeName

  ; Do not allow the modification of some important registry labels
  iF (Cmd!="" && CheckLabel)
     Return 0

  regFile := "Windows Registry Editor Version 5.00`n`n"
  ; Note that "HKEY_CLASSES_ROOT" actually writes to "HKEY_LOCAL_MACHINE\SOFTWARE\Classes"
  ; If the command is just a simple path, then convert it into a proper run command
  iF (SubStr(Cmd,2,2)=":\" && FileExist(Cmd))
     Cmd := """" Cmd """" A_Space """" "%1" """"
  Else
     Return 0

  Cmd := StrReplace(Cmd, "\", "\\")
  Cmd := StrReplace(Cmd, """", "\""")
  regFile .= "[HKEY_CLASSES_ROOT\" Ext "]`[email protected]=" """" Label """" "`n"
  regFile .= "`n[HKEY_CLASSES_ROOT\" Label "]`[email protected]=" """" Label """" "`n"
  regFile .= "`n[HKEY_CLASSES_ROOT\" Label "\Shell\Open\Command]`[email protected]=" """" Cmd """" "`n"
  regFile .= "`n[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\" Ext "\UserChoice]`n""ProgId""=" """" Label """" "`n"
  regFile .= "`n[-HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FileExts\" Ext "\OpenWithProgids]`n"
  regFile .= "`n[-HKEY_CLASSES_ROOT\" Ext "\OpenWithProgids]`n`n"

  If Icon
     regFile .= "`n[HKEY_CLASSES_ROOT\" QPVslideshow "\DefaultIcon]`[email protected]=" Icon "`n`n"

  If !InStr(FileExist(mainCompiledPath "\regFiles"), "D")
  {
     FileCreateDir, %mainCompiledPath%\regFiles
     Sleep, 1
  }

  iExt := StrReplace(Ext, ".")
  FileDelete, %mainCompiledPath%\regFiles\RegFormat%iExt%.reg
  Sleep, 1
  FileAppend, % regFile, %mainCompiledPath%\regFiles\RegFormat%iExt%.reg
  runTarget := "Reg Import """ mainCompiledPath "\regFiles\RegFormat" iExt ".reg" """" "`n"
  If !InStr("|WIN_7|WIN_8|WIN_8.1|WIN_VISTA|WIN_2003|WIN_XP|WIN_2000|", "|" A_OSVersion "|")
     runTarget .= """" mainCompiledPath "\SetUserFTA.exe""" A_Space Ext A_Space Label "`n"
  FileAppend, % runTarget, %mainCompiledPath%\regFiles\runThis.bat
  If (batchMode!=1)
  {
     Sleep, 1
     RunWait, *RunAs %mainCompiledPath%\regFiles\runThis.bat
     FileDelete, %mainCompiledPath%\regFiles\RegFormat%iExt%.reg
     FileDelete, %mainCompiledPath%\regFiles\runThis.bat
  }

  return 1
}

This is the function i ended up with. It makes use of SetUserFTA.exe developed by Christoph Kolbicz from http://kolbi.cz/blog/2017/10/25/setuserfta-userchoice-hash-defeated-set-file-type-associations-per-user/

Best regards, Marius.
-------------------------
KeyPress OSD v4: GitHub or forum. (presentation video)
Quick Picto Viewer: GitHub or forum.
AHK GDI+ expanded / compilation library (on GitHub)
My home page.

Return to “Scripts and Functions”

Who is online

Users browsing this forum: Eik and 15 guests