1 (изменено: HA3APET, 2018-03-09 18:22:18)

Тема: AHK: ButtonBar eXtended помощь Total Commander-сообществу

Есть очень востребованная среди сборщиков Total Commander утилита:
ButtonBar eXtended

Утилита написана уже в далёком 2011 и имеет пару проблем с UAC:
1) Утилита не передаёт повышение прав программе которую запускает. То есть если ButtonBar eXtended запустить от Администратора, то программа которую запустит утилита не получает команду также запуститься от Администратора.
2) Утилита ищет Usercmd.ini в корневой папке Total Commander, но будучи запущенной с повышением прав, она его там не находит.

Обе эти проблемы решаются если запускать TC от имени администратора.

Просьба подправить исходный код утилиты:

+ открыть спойлер
; "ButtonBar eXtended" for Total Commander
; Version: 2.3
; Freeware by Samuel Plentz - www.SamuelPlentz.de.vu

; ### --------------------------------------------------------------------------
; ### get current keystates of Ctrl, Alt & Shift and read parameters

#NoTrayIcon
#SingleInstance off
SetBatchLines -1
AutoTrim,Off

Getkeystate,Keystate_Ctrl ,Ctrl
Getkeystate,Keystate_Alt  ,Alt
Getkeystate,Keystate_Shift,Shift

Quote="
Parameter_1=%1%
Parameter_2E=%2%
Parameter_3E=%3%
StringLower,Parameter_1L,1
transform,Parameter_2,deref,%Parameter_2E%
transform,Parameter_3,deref,%Parameter_3E%

; ##############################################################################
; ### convert "ButtonBar" to "ButtonBar eXtended"

if(Parameter_1L=="-c" || Parameter_1L=="-d"){
; # check if Parameter_2 is valid and get NewFilename --------------------------
 IniRead,ButtonCount,%Parameter_2%,Buttonbar,Buttoncount,0
	if(!RegExMatch(Parameter_2,"i)\.bar$") || !FileExist(Parameter_2) || ButtonCount==0){
		msgbox,16,Error: Wrong Parameters,A valid "ButtonBar" is needed to convert it to a "ButtonBar eXtended".`nParameter 1: "%Parameter_1%"`nParameter 2: "%Parameter_2E%"
		return
	}
 SplitPath,Parameter_2,Parameter_2Name,tFilePath,,UserCmdSection
 NewFilename=BBX_%Parameter_2Name%
 if(tFilePath!=""){
		NewFilename=%tFilePath%\%NewFilename%
	}
	NewFilenameCache=NewFilename
	StringTrimRight,NewFilenameCache,NewFilenameCache,3
	NewFilenameCache=%NewFilenameCache%br2
	FileDelete,%NewFilename%
	FileDelete,%NewFilenameCache%
	
; # delete all old user commands for this "ButtonBar eXtended" -----------------
 StringReplace,UserCmdSection,UserCmdSection,%A_Space%,_,1
 StringReplace,UserCmdSection,UserCmdSection,-,_,1
 StringReplace,UserCmdSection,UserCmdSection,=,_,1
 UserCmdSection=em_BBX_%UserCmdSection%>
	UserCmdFile := LocationUserCmdFile()
	WinCmdFile := LocationWinCmdFile()
	FileRead,UserCmdContent,%UserCmdFile%
	Loop,parse,UserCmdContent,`n,`r
	{
		if(1==InStr(A_LoopField,"[" . UserCmdSection) || (1==InStr(A_LoopField,"[em_BBX_") && 0==InStr(A_LoopField,">"))){
			StringTrimLeft,currentSection,A_LoopField,1
			StringTrimRight,currentSection,currentSection,1
			IniDelete,%UserCmdFile%,%currentSection%
		}
	}

; # read all commands from the "ButtonBar" -------------------------------------
 A_ScriptFullPathE=%A_ScriptFullPath%
 A_ScriptDirE=%A_ScriptDir%
 Loop,%ButtonCount%
 {
  ReadCommand(Parameter_2,A_Index)
  Command := cmd%A_Index%
  SplitPath,Command,tFilename
  StringReplace,tFilename,tFilename,",,All
  
; change convert button to edit button
  if(tFilename==A_ScriptName && InStr(param%A_Index%,Parameter_2Name) && (InStr(param%A_Index%,"-d") || InStr(param%A_Index%,"-c"))){
  	A_ScriptFullPathE := cmd%A_Index%
  	SplitPath,A_ScriptFullPathE,,A_ScriptDirE
  	A_ScriptDirE=%A_ScriptDirE%\
  	cmd%A_Index% := Parameter_2E
  	param%A_Index% := ""
  	path%A_Index% := ""
  	menu%A_Index% := "Edit this " . Quote . "ButtonBar eXtended" . Quote
  }
 }

; # convert all commands from the "ButtonBar" ----------------------------------
 OutputButtonbarCount=0
 OutputUserCmdCount=0
 Mode=0
 Loop,%ButtonCount%
 {
 	nextIndex := A_Index+1
 	if(RegExMatch(menu%nextIndex%,"i)(^[2-5]?(c|a|s|ca|cs|as|cas)$|^[2-5]$|^m$)")){

; start of an "eXtended command"
 		if(Mode==0){
  		Mode=1
 			OutputButtonbarCount++
 			OutputUserCmdCount++
    OutputUserCmdState=
   	OutputUserCmdStateCount=1
    WriteNewCommand(NewFilename,"Buttonbar",OutputButtonbarCount,A_ScriptFullPathE,A_ScriptDirE,UserCmdSection . OutputUserCmdCount,button%A_Index%,0,menu%A_Index%)
 			menu%A_Index% := ""
    WriteCommand(UserCmdFile,A_Index,UserCmdSection . OutputUserCmdCount . "_" . OutputUserCmdState . "_" . OutputUserCmdStateCount,"")
    continue
 		}
		}else{
			Mode=0
		}
	
; "eXtended command" continues
 	if(RegExMatch(menu%A_Index%,"i)(^[2-5]?(c|a|s|ca|cs|as|cas)$|^[2-5]$|^m$)")){
 		if(RegExMatch(menu%A_Index%,"i)^m$")){
 			OutputUserCmdStateCount++
 		 menu%A_Index% := ""
			}else{
 			StringLower,OutputUserCmdState,menu%A_Index%
 			if menu%A_Index% is not lower
 			 menu%A_Index% := "w"
 			else
 			 menu%A_Index% := ""
   	OutputUserCmdStateCount=1
 		}

   WriteCommand(UserCmdFile,A_Index,UserCmdSection . OutputUserCmdCount . "_" . OutputUserCmdState . "_" . OutputUserCmdStateCount,"")
   continue		
  }

; ahk command
  if(1==InStr(cmd%A_Index%,"ahk_")){
  	OutputButtonbarCount++
 		OutputUserCmdCount++
   WriteNewCommand(NewFilename,"Buttonbar",OutputButtonbarCount,A_ScriptFullPathE,A_ScriptDirE,UserCmdSection . OutputUserCmdCount,button%A_Index%,0,menu%A_Index%)
 		menu%A_Index% := ""
   WriteCommand(UserCmdFile,A_Index,UserCmdSection . OutputUserCmdCount . "__1","")
   continue
  }

; simple command
  OutputButtonbarCount++
  WriteCommand(NewFilename,A_Index,"Buttonbar",OutputButtonbarCount)
 }
 IniWrite,%OutputButtonbarCount%,%NewFilename%,Buttonbar,Buttoncount
 
; make the "ButtonBar eXtended" the default if "-d" was used
 if(Parameter_1L=="-d" && FileExist(WinCmdFile)){
 	IniWrite,%NewFilename%,%WinCmdFile%,Buttonbar,Buttonbar
 }
 OutputUserCmdCount++
 if(Parameter_3!=""){
  WriteNewCommand(UserCmdFile,UserCmdSection . OutputUserCmdCount,"","OPENBAR","",Parameter_3,"",0,"")
 }else{
  WriteNewCommand(UserCmdFile,UserCmdSection . OutputUserCmdCount,"","OPENBAR","",NewFilename,"",0,"")
 }
 Command=%UserCmdSection%%OutputUserCmdCount%
 EM_Command(Command)
 ExitApp
}



; ##############################################################################
; ### execute a command in the "ButtonBar eXtended"

if(Parameter_1!=""){
	UserCmdFile := LocationUserCmdFile()
	MouseState := GetMouseButton()
	Mode_CAS=%MouseState%
	if(Keystate_Ctrl=="D"){
	 Mode_CAS=%Mode_CAS%c
	}
	if(Keystate_Alt=="D"){
	 Mode_CAS=%Mode_CAS%a
	}
	if(Keystate_Shift=="D"){
	 Mode_CAS=%Mode_CAS%s
	}

; use default command if current keyboard modifiers are not available
 if(Mode_CAS!=""){
 	IniRead,value,%UserCmdFile%,%Parameter_1%_%Mode_CAS%_1,cmd,%A_Space%

; when there is no action defined for middlemousebutton it reacts like Ctrl
 	if(value==""){
 		if(Mode_CAS=="3"){
  		Mode_CAS=c
 		}else{
  		Mode_CAS=%MouseState%
 		}
 	}else{

; wait for modifier releases if necessary
  	IniRead,value,%UserCmdFile%,%Parameter_1%_%Mode_CAS%_1,menu,%A_Space%
	 	if(value=="w"){
    Loop{
     Getkeystate,Keystate_Ctrl ,Ctrl
     Getkeystate,Keystate_Alt  ,Alt
     Getkeystate,Keystate_Shift,Shift
     if(Keystate_Ctrl!="D" && Keystate_Alt!="D" && Keystate_Shift!="D"){
      break
     }
    }
   }
 	}
 }

; execute all according commands
 Loop
	{
 	IniRead,Command,%UserCmdFile%,%Parameter_1%_%Mode_CAS%_%A_Index%,cmd,%A_Space%
 	if(Command==""){
 		break
 	}

; run custom ahk commands
 	StringLower,Command,Command
  if(1==InStr(Command,"ahk_")){
  	IniRead,Parameter_ahk,%UserCmdFile%,%Parameter_1%_%Mode_CAS%_%A_Index%,param,%A_Space%
  	if(Command=="ahk_sleep"){
  		Sleep,%Parameter_ahk%
  		continue
  	}
  	if(Command=="ahk_sendinput"){
  		SendInput,%Parameter_ahk%
  		continue
  	}
  	continue
  }

; run normal em_commands
  Command=%Parameter_1%_%Mode_CAS%_%A_Index%
	 EM_Command(Command)
 }
 ExitApp
}

ExitApp

; ##############################################################################
; ##############################################################################
; ##############################################################################



; ### --------------------------------------------------------------------------
; ### get location of "usercmd.ini" (use CustomUsercmd if set in ini)

LocationUserCmdFile()
{
	IniRead,tFileName,ButtonBar eXtended.ini,ButtonBar eXtended,CustomUsercmd,-
	if(tFileName!="-"){
		transform,tFileName,deref,%tFileName%
	 return tFileName
	}
 EnvGet,LocationWinCmdFile,COMMANDER_INI
 SplitPath,LocationWinCmdFile,,tFilePath
 tFilename=usercmd.ini
 if(tFilePath!=""){
		tFilename=%tFilePath%\%tFilename%
	}
	return tFilename
}

LocationWinCmdFile()
{
 EnvGet,LocationWinCmdFile,COMMANDER_INI
	return LocationWinCmdFile
}

; ### --------------------------------------------------------------------------
; ### read command into an array

ReadCommand(Filename,ArrayNr)
{
	global
 IniRead,cmd%ArrayNr%   ,%Filename%,Buttonbar,cmd%ArrayNr%   ,%A_Space%
 cmd%ArrayNr%    := RegExReplace(cmd%ArrayNr%   ,"^" . Quote . ".*" . Quote . "$",Quote . "$0" . Quote,value,1)
 IniRead,path%ArrayNr%  ,%Filename%,Buttonbar,path%ArrayNr%  ,%A_Space%
 path%ArrayNr%   := RegExReplace(path%ArrayNr%  ,"^" . Quote . ".*" . Quote . "$",Quote . "$0" . Quote,value,1)
 IniRead,param%ArrayNr% ,%Filename%,Buttonbar,param%ArrayNr% ,%A_Space%
 param%ArrayNr%  := RegExReplace(param%ArrayNr% ,"^" . Quote . ".*" . Quote . "$",Quote . "$0" . Quote,value,1)
 IniRead,button%ArrayNr%,%Filename%,Buttonbar,button%ArrayNr%,%A_Space%
 button%ArrayNr% := RegExReplace(button%ArrayNr%,"^" . Quote . ".*" . Quote . "$",Quote . "$0" . Quote,value,1)
 IniRead,iconic%ArrayNr%,%Filename%,Buttonbar,iconic%ArrayNr%,%A_Space%
 iconic%ArrayNr% := RegExReplace(iconic%ArrayNr%,"^" . Quote . ".*" . Quote . "$",Quote . "$0" . Quote,value,1)
 IniRead,menu%ArrayNr%  ,%Filename%,Buttonbar,menu%ArrayNr%  ,%A_Space%
 menu%ArrayNr%   := RegExReplace(menu%ArrayNr%  ,"^" . Quote . ".*" . Quote . "$",Quote . "$0" . Quote,value,1)
}

; ### --------------------------------------------------------------------------
; ### write command in a file

WriteCommand(Filename,ArrayNr,FileSection,FileNr)
{
	global
	value := cmd%ArrayNr%
 IniWrite,%value%,%Filename%,%FileSection%,cmd%FileNr%
	value := path%ArrayNr%
	IniWrite,%value%,%Filename%,%FileSection%,path%FileNr%
	value := param%ArrayNr%
 IniWrite,%value%,%Filename%,%FileSection%,param%FileNr%
	value := button%ArrayNr%
 IniWrite,%value%,%Filename%,%FileSection%,button%FileNr%
	value := iconic%ArrayNr%
 IniWrite,%value%,%Filename%,%FileSection%,iconic%FileNr%
	value := menu%ArrayNr%
	IniWrite,%value%,%Filename%,%FileSection%,menu%FileNr%
}

; ### --------------------------------------------------------------------------
; ### create new command in a file

WriteNewCommand(Filename,FileSection,FileNr,v1,v2,v3,v4,v5,v6)
{
	global
	cmd0=%v1%
 path0=%v2%
 param0=%v3%
 button0=%v4%
 iconic0=%v5%
 menu0=%v6%
 WriteCommand(Filename,0,FileSection,FileNr)
}

; ### --------------------------------------------------------------------------
; ### execute em_commands

EM_Command(ByRef emCommand)
{
	Critical
	VarSetCapacity(CopyDataStruct, A_PtrSize * 3)
 VarSetCapacity(emCommandAnsi, StrPut(emCommand, "cp0"))
 Loop, % StrLen(emCommand)
 {
  NumPut(Asc(SubStr(emCommand, A_Index, 1)), emCommandAnsi, A_Index - 1, "Char")
 }
 NumPut(Asc("E") + 256 * Asc("M"), CopyDataStruct)
 NumPut(StrLen(emCommand) + 1, CopyDataStruct, A_PtrSize)
 NumPut(&emCommandAnsi, CopyDataStruct, A_PtrSize * 2)
 SendMessage, 0x4A,, &CopyDataStruct,, ahk_class TTOTAL_CMD
}

; ### --------------------------------------------------------------------------
; ### works together with MouseTool to detect which mouse button was pressed

GetMouseButton()
{
	MouseButton=
 Loop,5
 {
 	if(A_Index!=1){
  	Mutex := DllCall("CreateMutex","uint","0","int","1","str","BBX_" . A_Index)
   LastError := DllCall("GetLastError")
 	 DllCall("CloseHandle","uint",Mutex)
 	 if(LastError!=0){
 	 	MouseButton=%A_Index%
 	 	break
 	 }
 	}
 }
 return MouseButton
}