Autorun

Обсуждение только плагинов и утилит для Total Commander.

Модераторы: Avada, CaptainFlint, Nik, d-view, Моторокер

Аватара пользователя
Avada
Сообщения: 10541
Зарегистрирован: Пт авг 01, 2008 16:17
Откуда: Россия, Саратов

Сообщение Avada »

AkulaBig
Я это всё видел и знаю. Для полной поддержки многоязычности надо капитально переделывать интерфейс TC. Не наблюдаю ни энтузиазма со стороны автора, ни массовой поддержки этой идеи со стороны участников форумов. Тем более, что список отнюдь не исчерпывается пользовательскими меню. Как минимум, есть, например, заголовки вкладок. ИМХО, не будет он с этим связываться.
Даже самая богатая фантазия
Не представит себе наши безобразия.
AkulaBig
Сообщения: 639
Зарегистрирован: Ср дек 03, 2008 11:48

Сообщение AkulaBig »

Avada писал(а): ИМХО, не будет он с этим связываться.
Поэтому я все сам :) Потихоньку получается. Autorun очень сильно помогает.
Аватара пользователя
Orion9
Сообщения: 1283
Зарегистрирован: Пн янв 01, 2024 17:18

Сообщение Orion9 »

Avada писал(а):ИМХО, не будет он с этим связываться.
Не знаю на счет остального интерфейса (я не сильно в этой теме), но что касается секций [user] и [DirMenu], то не вижу здесь больших препятствий. Что мешает, например, создать еще один языковой файл, скажем WCMD_ENG.CFG [WCMD_RUS.CFG, WCMD_CHN.CFG, ...] и хранить в нем все, что было упущено, включая эти секции? И логики никакой менять не надо: если пользователь самостоятельно не создаст этот файл и не укажет в нем своих секций, они по-прежнему будут браться из wincmd.ini. Но как только пользователь создает этот файл, предподчение должно сразу отдаваться именно ему (этому файлу) и все изменения должны сораняться именно туда, а не в wincmd.ini или его редирект.
Аватара пользователя
Orion9
Сообщения: 1283
Зарегистрирован: Пн янв 01, 2024 17:18

Сообщение Orion9 »

AkulaBig
Ну вот, использовал ваш скрипт для переключения внутренних ассоциаций в Autorun :) Говорил же: добавьте названия секций в параметры и сделайте небольшую документацию в шапке - получится отличный универсальный скрипт для обмена секциями в ini.

[cut="ChangeAssoc.vbs"]

Код: Выделить всё

Dim objArgs
Dim objShell
Dim arrLang
	
arrLang = Array("[+Associations]", "[-Associations]")

Set objShell = WScript.CreateObject("WScript.Shell")

INI = objShell.ExpandEnvironmentStrings("%COMMANDER_PATH%\Ini\Associations.ini")
Text = CreateObject("Scripting.FileSystemObject").OpenTextFile(INI, 1).ReadAll

for i = 0 to UBound(arrLang)
	If InStr(1, Text, arrLang(i), 1) = 0 Then
		Text = Replace(Text, "[Associations]", arrLang(i), 1, 1, 1)
		exit for
	End If
next

Set objArgs = WScript.Arguments

If InStr(1, Text, objArgs(0), 1) Then
	Text = Replace(Text, objArgs(0), "[Associations]", 1, 1, 1)
	With CreateObject("Scripting.FileSystemObject")  
		.OpenTextFile(INI, 2).Write Text
		.OpenTextFile(INI, 1).Close
		End With 
End If

With CreateObject("Scripting.FileSystemObject")  
	.OpenTextFile(INI, 2).Write Text
	.OpenTextFile(INI, 1).Close
	End With 

Set objShell = Nothing 
WScript.Quit
[/cut]
[cut="autorun.cfg"]

Код: Выделить всё

RegisterCommand 61003 "SwitchAssocState"

# первое выполнение при запуске
AssocState()

Func AssocState()
   Local f1, res
   IniRead /R f1 %COMMANDER_INI% "Associations" "Filter1" ""
   # если в секции что-то есть, значит она включена
   If f1 <> "" Then
      SetEnv TEST_ICON "%COMMANDER_PATH%\Icons\Clsw\2.ico"
      res = true
   Else
      SetEnv TEST_ICON "%COMMANDER_PATH%\Icons\Clsw\6.ico"
      res = false
   Endif
   Return res
EndFunc

Func SwitchAssocState(lParam)
   Local script = %COMMANDER_PATH% & "\Scripts\Vbs\ChangeAssoc.vbs", sect   
   If AssocState() Then
      # отключение секции
      sect = '[-Associations]'
   Else
      # включение секции   
      sect = '[+Associations]' 
   Endif
   ShellExec /SW_HIDE /WAIT:3000 '%windir%\system32\cscript.exe' '"%script%" "%sect%"'
   AssocState()   
   SendMessage(AUTORUN_TCHANDLE, 11, 0, 0)
   CommandExec cm_ReloadFileIcons
   CommandExec cm_ReloadBarIcons 
   sleep(10)
   SendMessage(AUTORUN_TCHANDLE, 11, 1, 0)
   WinRedraw(1)
EndFunc
[/cut]
[cut]

Код: Выделить всё

TOTALCMD#BAR#DATA
61003

%TEST_ICON%
Внутренние ассоциации

1
-1
[/cut]
Все четко и гладко работает, но, блин... кажется, нашел баг в ТС (если это баг, конечно).

Жалею теперь, что потратил полчаса, пытаясь понять, где я накосячил, а оказывается в TCASwitcher.exe всё то же самое было.

Если при запуске ТС внутренние ассоциации включены, то никаких проблем нет - все работает как часы. Но если при запуске ассоциации выключены, то переключение не работает. Вернее оно работает с багом: значок переключается, а ассоциации нет. Только перезагрузка помогает. Как я понял, причина здесь в команде cm_ReloadFileIcons, которая не перечитывает значки (хотя должна), если при старте ТС секция ассоциаций была пустая. Но если секция была наполнена, то все работает.

Avada, вам вопрос (или, может быть, еще кто-то ответит, кто знает): как ТС определяет, что включены или выключены внутренние ассоциации? И баг ли это с cm_ReloadFileIcons, а то может Гислеру надо сообщить?
Аватара пользователя
Avada
Сообщения: 10541
Зарегистрирован: Пт авг 01, 2008 16:17
Откуда: Россия, Саратов

Сообщение Avada »

Orion9
Тотал определяет наличие внутренних ассоциаций по содержимому секции [Associations]. На чём и основана работа TCASwitcher. Но команда cm_ReloadFileIcons о трюке с подменой секций не имеет никакого понятия. Если у вас сторонним образом (потому что другого нет) выключены внутренние ассоциации, т.е. секция с ними снабжена таким заголовком, по которому Тотал не обращается, а секция с правильным именем пустая, то их значки для перечитывании этой команде взять неоткуда. Это не баг, а вполне естественное и предсказуемое поведение.
Даже самая богатая фантазия
Не представит себе наши безобразия.
AkulaBig
Сообщения: 639
Зарегистрирован: Ср дек 03, 2008 11:48

Сообщение AkulaBig »

Orion9 писал(а):AkulaBig
Ну вот, использовал ваш скрипт для переключения внутренних ассоциаций в Autorun :)
Дак мне переключение ассоциаций не надо, поэтому я и не делал :)
Для переключения ассоциаций есть готовые скрипты, программа. Вроде достаточно инструментов. А мой скрипт все-же для другого. Он заточен чтобы более двух названий переключать. И причем определяет, какой язык используется.
Аватара пользователя
Orion9
Сообщения: 1283
Зарегистрирован: Пн янв 01, 2024 17:18

Сообщение Orion9 »

Avada, Спасибо за ответ. В чём-то могу согласиться, но все-таки это больше похоже на недоработку. Возможно, Гислеру об этом не говорили, но команда cm_ReloadFileIcons должна перечитывать секцию прежде, чем перечитывать иконки, тогда она будет работать правильно. Вообще, давно заметил, что Тоталу не хватает команды, которая будет сохранять и перечитывать всю кофигурацию, как это происходит при начальной загрузке, это бы во многом облегчило жизнь. А что касается внутренних ассоциаций, то теперь остается только одно - вызывать окно командой cm_InternalAssociate и "прожимать" ОК, как это и было сделано в старых версиях TCASwitcher. Окно, конечно, мелькает, но зато работает все как надо.

В принципе, я так и сделал, но немного оптимизировал алгоритм: если при запуске ассоциации включены (секция наполнена), то cm_InternalAssociate не посылается, и все работает сверх-гладко, просто глаз радуется. Если же секция была пустой (ассоциации были отключены), то сначала вызывается окно внутренних ассоциаций, нажимается ОК, и только потом обновляется значок на панели. Окно при этом мелькает, но это мелочи.

[cut="autorun.cfg"]

Код: Выделить всё

Global IniAssocState
# первое выполнение при запуске
IniAssocState = AssocState()

Func AssocState()
   Local f1, res
   IniRead /R f1 %COMMANDER_INI% "Associations" "Filter1" ""
   # если в секции что-то есть, значит она включена
   If f1 <> "" Then
      SetEnv TEST_ICON "%COMMANDER_PATH%\Icons\Clsw\2.ico"
      res = true
   Else
      SetEnv TEST_ICON "%COMMANDER_PATH%\Icons\Clsw\6.ico"
      res = false
   Endif
   Return res
EndFunc

Func SwitchAssocState(lParam)
   Local script = %COMMANDER_PATH% & "\Scripts\Vbs\ChangeAssoc.vbs", sect   
   If AssocState() Then
      # отключение секции
      sect = '[-Associations]'
   Else
      # включение секции   
      sect = '[+Associations]' 
   Endif
   ShellExec /SW_HIDE /WAIT:3000 '%windir%\system32\cscript.exe' '"%script%" "%sect%"'
   AssocState()
   If IniAssocState Then
      AssocUpdateWin(true)
   Else
      RunThread AssocWinSynс
   EndIf   
EndFunc

Func AssocWinSynс()
   Local h = 0, i
   PostMessage(AUTORUN_TCHANDLE, 0x433, 519)
   # ожидание появления окна 
   For i = 1 To 75
       h = WinFind(0, "TDlgCustomColors")
       If h > 0 Then Break   
       Sleep(25)
       #OutputDebugString(h)
   Next
   If h > 0 Then   
      b = WinFind(h, "TButton", 3)
      SendMessage(b, 0xF5, 0, 0)
   Else
      ShowHint("Окно не найдено") 
      Return  
   Endif
   AssocUpdateWin(false)
EndFunc

Func AssocUpdateWin(lReload)
   SendMessage(AUTORUN_TCHANDLE, 11, 0, 0)
   If lReload Then SendCommand cm_ReloadFileIcons
   SendCommand cm_ReloadBarIcons 
   sleep(10)
   SendMessage(AUTORUN_TCHANDLE, 11, 1, 0)
   WinRedraw(1)   
EndFunc
[/cut]
AkulaBig писал(а):Дак мне переключение ассоциаций не надо, поэтому я и не делал
Так ведь дело не только в ассоциациях: ваш скрипт к чему угодно можно применить, вы только добавьте ему универсальности, чтобы можно было управлять именем файла и секциями через параметры, а не созданием повторных экземпляров. Вам же самому пригодится, если будете делать [DirMenu] по тому же принципу.
AkulaBig писал(а):Для переключения ассоциаций есть готовые скрипты, программа. Вроде достаточно инструментов.
Это да. Но на Autorun-то еще не было, да еще и в таком коллабе :lol:
AkulaBig
Сообщения: 639
Зарегистрирован: Ср дек 03, 2008 11:48

Сообщение AkulaBig »

Orion9 писал(а):чтобы можно было управлять именем файла и секциями через параметры, а не созданием повторных экземпляров.
Ну вы представляете, сколько параметров придется передавать. ТС поддерживает вроде 18 языков. Плюс внутренний. Плюс название устанавливаемого языка. Получается 20 параметров. А сейчас один параметр и понятный массив внутри с названиями языков. Ну а уж размер скрипта крошечный, можно и 100 копий сделать.

Добавлено спустя 1 час 30 минут:

Кстати, немного увеличить универсальность можно за счет изменения обозначения массива языков. Ведь по сути набор языков - это константа, которая будет в любой операции. Но тогда надо будет передавать наименование файла. Тоже не очень приятно, но осуществимо.
Аватара пользователя
Orion9
Сообщения: 1283
Зарегистрирован: Пн янв 01, 2024 17:18

Сообщение Orion9 »

AkulaBig
Согласен. Для вашей задачи такое вряд ли подойдет. Но как я писал выше, универсальность вашего скрипта хорошо может проявиться на ограниченном числе параметров, что и нужно большенству пользователей, имхо.

Да и вашей задаче большое число параметров не помеха :)

Попробуйте, например, кнопку:

Код: Выделить всё

RegisterCommand 63001 "TestVbsArgs"

Func TestVbsArgs(lParam)
    Local txt, pipe
    Local VbsPath = %COMMANDER_PATH% & "\Scripts\Vbs\"    
    Local LangPath = %COMMANDER_PATH% & "\LANGUAGE\"    
    ProcessExecGetOutput pipe %COMSPEC% "/c dir /b *.*" %LangPath%
    pipe = StrReplace(pipe, auCRLF, " ")
    ProcessExecGetOutput txt "cscript.exe" "/nologo Args.vbs %pipe%" %VbsPath%    
    ShowHint(txt)
EndFunc      
Args.vbs

Код: Выделить всё

Set objArgs = Wscript.Arguments

WScript.Echo objArgs.Count

For i = 0 to objArgs.Count -1
   Wscript.Echo "Arg" & i & " = " & objArgs.Item(i)
Next

Код: Выделить всё

TOTALCMD#BAR#DATA
63001

%COMMANDER_EXE%
Тест параметров Vbs

1
-1
Скрипт Autorun перечисляет все файлы в папке Language (которых по умолчанию 53) и передает их в качестве параметров vbs-скрипту. Скрипт принимает все параметры, перечисляет и возвращает результат в Autorun.

Но все-равно я думаю, вам не стоит таким заморачиваться. А если и нужен универсальный скрипт для смены языковых секций [user] и [DirMnu], то, наверно, лучше другой алгоритм для этого использовать.
AkulaBig
Сообщения: 639
Зарегистрирован: Ср дек 03, 2008 11:48

Сообщение AkulaBig »

Orion9 писал(а):

Код: Выделить всё

 ProcessExecGetOutput txt "cscript.exe" "/nologo Args.vbs %pipe%" %VbsPath%    
А вы с какой-то целью cscript.exe прописываете? Просто я попробовал, прекрасно без этого работает.

Добавлено спустя 1 час 8 минут:
Orion9 писал(а): Скрипт Autorun перечисляет все файлы в папке Language (которых по умолчанию 53) и передает их в качестве параметров vbs-скрипту. Скрипт принимает все параметры, перечисляет и возвращает результат в Autorun.
Но все-равно я думаю, вам не стоит таким заморачиваться.
Дак мой скрипт и не сможет обработать все языки. В моем скрипте очень важно, чтобы в файле User.ini были прописаны все секции, которые упоминаются в массиве. И берется первая, где не прописан язык. Иначе как я узнаю, какой язык используется перед подключением. Ведь ТС узнает только секцию User.
Аватара пользователя
Orion9
Сообщения: 1283
Зарегистрирован: Пн янв 01, 2024 17:18

Сообщение Orion9 »

AkulaBig писал(а):А вы с какой-то целью cscript.exe прописываете? Просто я попробовал, прекрасно без этого работает.
Как это работает? :? Для ProcessExecGetOutput имя исполняемого файла должно быть обязательно указано, разве нет?

Может быть, вы путаете с ShellExec? Там такой вызов вполне допустим:

Код: Выделить всё

ShellExec "Args.vbs" %params% %VbsPath%

Но тогда скрипт Args.vbs не сможет вернуть в Autorun данные через stdout.
AkulaBig писал(а):Дак мой скрипт и не сможет обработать все языки.
А ведь Тотал, похоже, в окне для смены языка просто считывает *.lng из каталога LANGUAGE и предлагает их пользователю для переключения. Если изменить команду на %COMSPEC% "/c dir /b *.lng" %LangPath%, то скрипт получит все 18 языков в качестве своих параметров (или другое количество из каталога), которые будут соответствовать макросу AUTORUN_TCLANGFILE - другие языки пользователь просто не может выбрать через интерфейс. Может быть, из этого что-то и получилось бы, но мне кажется:
AkulaBig писал(а):Иначе как я узнаю, какой язык используется перед подключением. Ведь ТС узнает только секцию User.
Вам, вероятно, нужен другой алгоритм, который будет запоминать с какого языка на какой происходило переключение и менять секции местами.
sa
Сообщения: 2758
Зарегистрирован: Ср апр 29, 2009 18:56

Сообщение sa »

Orion9 писал(а):Блин, я офигел, как гладко работает!
По-моему, тут всё дело в добавлении паузы sleep(10) после cm_ReloadBarIcons (2945) и WinRedraw(1).
Переделал подобным же образом обновление панели инструментов при изменении количества строк в ней:

Код: Выделить всё

SendMessage(AUTORUN_TCHANDLE, 11, 0, 0)
SendCommand 2901
SendCommand 2901
sleep(10)
SendMessage(AUTORUN_TCHANDLE, 11, 1, 0)
WinRedraw(1)
AkulaBig
Сообщения: 639
Зарегистрирован: Ср дек 03, 2008 11:48

Сообщение AkulaBig »

Orion9 писал(а): Может быть, вы путаете с ShellExec?
Ну да, у меня через него сделано.
Orion9 писал(а): Но тогда скрипт Args.vbs не сможет вернуть в Autorun данные через stdout.
Мне это и не надо, но вы немного по другому хотите сделать.
Orion9 писал(а): скрипт получит все 18 языков в качестве своих параметров
И как вы потом определите:
AkulaBig писал(а):Иначе как я узнаю, какой язык используется перед подключением. Ведь ТС узнает только секцию User.
У меня это решается просто. Все необходимые секции должны быть прописаны. И с помощью массива я узнаю, какой язык используется в настоящее время. Поэтому я не могу читать весь список языков. Тогда только нейросеть может определить текущий язык :lol:
Пытаюсь сейчас сделать скрипт несколько универсальнее. Когда у меня было прописано конкретно название секции InStr нормально отрабатывал.А сейчас склеенные данные не понимает. Сравнивает не по полному соответствию. Похоже вместо [User_lng] надо писать [lng_User]. Так как [User] считается подстрокой.
Аватара пользователя
Orion9
Сообщения: 1283
Зарегистрирован: Пн янв 01, 2024 17:18

Сообщение Orion9 »

sa писал(а):По-моему, тут всё дело в добавлении паузы sleep(10) после cm_ReloadBarIcons (2945) и WinRedraw(1).
Похоже, да. Иначе команда разрешения перерисовки окна выполняется раньше, чем панель перерисовывается. Но, видимо, это сейчас и самое слабое место, т.к. на разных машинах, особенно слабых, эта цифра наверняка будет разной, и sleep(10) может попросту не хватить. Но работает не хуже чем в TCFS2, хотя в справке написано, что функция WinRedraw находится в тестовой стадии и перерисовка методом RedrawWindow отключена по умолчанию, хотя только именно этот метод почему-то и работает.
AkulaBig писал(а):И как вы потом определите:
Не берите в голову, это просто были творческие изыскания: интересно же посмотреть на что способен Autorun и как он гоняет параметры туда-сюда через stdout :lol:
AkulaBig
Сообщения: 639
Зарегистрирован: Ср дек 03, 2008 11:48

Сообщение AkulaBig »

Вот, вроде и получился универсальный скрипт. Даже комменты написал :)
[cut="ChangeLang.vbs"]

Код: Выделить всё

' Смена текущей секции ini-файлов в зависимости от выбранного языка
Dim objShell
Dim arrLang
Dim ini, sect, lng

' Поддерживаемые языки. В ini-файле должны быть секции, название которых
' создано по шаблону [sect_lng]. Количество секций должно соответствовать
' количеству поддерживаемых языков
arrLang = Array("eng", "rus")

Set objShell = WScript.CreateObject("WScript.Shell")

' Имя ini-файла, в котором необходимо менять названия секций, в зависимости
' от выбранного языка
ini = objShell.ExpandEnvironmentStrings(WScript.Arguments(0))
' Название оригинальной секции, которая используется программой
sect = WScript.Arguments(1)
' Язык, который будет использоваться текущим. Оригинальная секция будет без
' дополнения названия языка и соответствовать шаблону [sect_lng]. Все остальные
' секции будут соответствовать шаблону  [sect_lng]
lng = WScript.Arguments(2)

Text = CreateObject("Scripting.FileSystemObject").OpenTextFile(ini, 1).ReadAll

' Переименовываем все секции по шаблону [sect_lng]
for i = 0 to UBound(arrLang)
	If InStr(1, Text, "[" & sect & "_" & arrLang(i) & "]", 1) = 0 Then
		Text = Replace(Text, "[" & sect & "]", "[" & sect & "_" & arrLang(i) & "]", 1, 1, 1)
		exit for
	End If
next

' Переименовываем оригинальную секции по шаблону [sect]
If InStr(1, Text, "[" & sect & "_" & lng & "]", 1) Then
	Text = Replace(Text, "[" & sect & "_" & lng & "]", "[" & sect & "]", 1, 1, 1)
End If

With CreateObject("Scripting.FileSystemObject")
	.OpenTextFile(ini, 2).Write Text
	.OpenTextFile(ini, 1).Close
End With

Set objShell = Nothing 
WScript.Quit
[/cut]
Ответить