Что нового

[Процессы]Перезапуск Total Commander разных версий (x64-x86)

Mancoffee

Свет проталкивает тьму ...
Сообщения
86
Репутация
1
Нужно перезапускать Total Commander с версии x64 в x86 и наоборот. То есть находишься в x64, тогда перезапустить в x64 (это работает у меня вот так)
Код:
if processexists("TOTALCMD64.EXE") then
processclose("TOTALCMD64.EXE")
Sleep(1000)
ShellExecute("d:\Programs\System\Total Commander\v8.0 Beta 19 Portable (x64-x86)\TOTALCMD64.exe")
else
msgbox(0, "Ошибка", "Total Commander x64 не запущен!")
endif

Как перезапустить, чтобы если в x86, то в x64.То есть, чтобы скрипт обнаруживал процесс и тот и тот. И почему, если вместо ShellExecute поставить Run, то запуск не происходит?

Возможно
Код:
Option Explicit
Dim TCS, WshShell, TCexe, Timeout, QuitByTimeOut
Set TCS = CreateObject("TCScript.Helper")
Set WshShell = WScript.CreateObject("WScript.Shell")
TCexe = """" & TCS.TCPath & "\totalcmd64.exe"""
'Завершаем работу ТС
TCS.SendCommand "cm_Exit", True
 
'Ожидание завершения работы ТС
Timeout = 2000 ' Сколько ждать выключения в мсек
Do
Timeout = Timeout - 100
If Timeout < 0 Then QuitByTimeOut = True: Exit Do
WScript.Sleep 100
Loop While TCS.IsRunningTC
 
'Запускаем новый экземпляр программы
If Not QuitByTimeOut Then WshShell.Run TCexe
 
Set TCS = Nothing
Set WshShell = Nothing
WScript.Quit
это как-то поможет мне помочь? :smile: Так у меня на VBScript с TCHelper-ом работает.
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Предупреждение За нарушение правил форума (пункт В.11):
Любые отрывки AutoIt кода необходимо заключать в тег [autoit]
autoit.gif
(подробнее), а обычный код соответственно в тег [code]
code.gif
(подробнее). Также большие выдержки текста помещайте под тег [spoiler]
spoiler.gif
(подробнее), там где это поддерживается естественно. Как в случае с названием темы, также короткое и эргономичное сообщение привлекает больше внимания, и шансы на получение конкретного ответа увеличиваются.


С уважением, ваш Модератор.
 

gora

Знающий
Сообщения
315
Репутация
19
Mancoffee [?]
То есть находишься в x64, тогда перезапустить в x64
Код:
if processexists("TOTALCMD64.EXE") then
	processclose("TOTALCMD64.EXE")
	Sleep(1000)
	ShellExecute("e:\totalcmd64\TOTALCMD64.exe")
elseIf processexists("TOTALCMD.EXE") then
	processclose("TOTALCMD.EXE")
	Sleep(1000)
	ShellExecute("e:\totalcmd86\TOTALCMD.exe")
Else
	msgbox(0, "Ошибка", "Total Commander не запущен!")
endif

Mancoffee [?]
Нужно перезапускать Total Commander с версии x64 в x86 и наоборот
Код:
if processexists("TOTALCMD64.EXE") then
	processclose("TOTALCMD64.EXE")
	Sleep(1000)
	ShellExecute("e:\totalcmd86\TOTALCMD.exe")
elseIf processexists("TOTALCMD.EXE") then
	processclose("TOTALCMD.EXE")
	Sleep(1000)
	ShellExecute("e:\totalcmd64\TOTALCMD64.exe")
Else
	msgbox(0, "Ошибка", "Total Commander не запущен!")
endif
 
Автор
Mancoffee

Mancoffee

Свет проталкивает тьму ...
Сообщения
86
Репутация
1
Спасибо, работает. :smile: А как сделать, чтобы скрипт не процесс закрывал, а завершал именно программу, потому как не сохраняются настройки в таком случае, как сейчас?
 

Medic84

Омега
Команда форума
Администратор
Сообщения
1,590
Репутация
341
Код:
WinClose()
 

Zaramot

I ♥ AutoIt
Сообщения
1,160
Репутация
660
ВОт:
Код:
func _Process2Win($pid)
    if isstring($pid) then $pid = processexists($pid)
    if $pid = 0 then return -1
    $list = WinList()
    for $i = 1 to $list[0][0]
        if $list[$i][0] <> "" AND BitAnd(WinGetState($list[$i][1]),2) then
            $wpid = WinGetProcess($list[$i][0])
            if $wpid = $pid then return $list[$i][0]
        EndIf
    next
    return -1
endfunc

Узнаем название окна по его процессу.

А дальше так:
Код:
$Title = _Process2Win('totalcmd.exe')
WinClose($Title)
 
Автор
Mancoffee

Mancoffee

Свет проталкивает тьму ...
Сообщения
86
Репутация
1
Zaramot
Немного я запутался. Получается первый вариант скрипта уже не подходит?
 

Zaramot

I ♥ AutoIt
Сообщения
1,160
Репутация
660
Zaramot
Немного я запутался. Получается первый вариант скрипта уже не подходит?
Подходит, просто в место:
Код:
ProcessClose('TOTALCMD64')

используй:
Код:
$Title = _Process2Win('TOTALCMD64')
WinClose($Title)

и.т.д.
 
Автор
Mancoffee

Mancoffee

Свет проталкивает тьму ...
Сообщения
86
Репутация
1
Zaramot
Если так
Код:
if $Title = _Process2Win('TOTALCMD64')
    WinClose($Title) Then
    ShellExecute("d:\Programs\System\Total Commander\v8.0 Beta 19 Portable (x64-x86)\TOTALCMD64.exe")
Elseif $Title = _Process2Win('TOTALCMD')
    WinClose($Title) Then
    ShellExecute("d:\Programs\System\Total Commander\v8.0 Beta 19 Portable (x64-x86)\TOTALCMD64.exe")
Else
	ShellExecute("d:\Programs\System\Total Commander\v8.0 Beta 19 Portable (x64-x86)\TOTALCMD64.exe")
endif
Пишет такое
Код:
D:\Desktop\Temp AutoIt\Total x64.au3 (1) : ==> "If" statements must have a "Then" keyword.:
if $Title = _Process2Win('TOTALCMD64')
Где не хватает "then"?

Ну да в принципе ладно. Сделал через WinExists - работает.
Код:
if WinExists("Total Commander (x64)") then
    WinClose("Total Commander (x64)")
    ShellExecute("d:\Programs\System\Total Commander\v8.0 Beta 19 Portable (x64-x86)\TOTALCMD64.exe")
elseif WinExists("Total Commander") then
    WinClose("Total Commander")
    ShellExecute("d:\Programs\System\Total Commander\v8.0 Beta 19 Portable (x64-x86)\TOTALCMD.exe")
Else
    msgbox(0, "Ошибка", "Total Commander не запущен!")
endif
Всем большое спасибо!
 

Zaramot

I ♥ AutoIt
Сообщения
1,160
Репутация
660
Попробуй так:
Код:
Global $title

if processexists("TOTALCMD64.EXE") then
    $title = _Process2Win("TOTALCMD64.EXE")
	WinClose($title)
	Sleep(1000)
    ShellExecute("e:\totalcmd64\TOTALCMD64.exe")
elseIf processexists("TOTALCMD.EXE") then
    $title = _Process2Win("TOTALCMD.EXE")
	WinClose($title)
    Sleep(1000)
    ShellExecute("e:\totalcmd86\TOTALCMD.exe")
Else
    msgbox(0, "Ошибка", "Total Commander не запущен!")
endif

func _Process2Win($pid)
    if isstring($pid) then $pid = processexists($pid)
    if $pid = 0 then return -1
    $list = WinList()
    for $i = 1 to $list[0][0]
        if $list[$i][0] <> "" AND BitAnd(WinGetState($list[$i][1]),2) then
            $wpid = WinGetProcess($list[$i][0])
            if $wpid = $pid then return $list[$i][0]
        EndIf
    next
    return -1
endfunc
 
Автор
Mancoffee

Mancoffee

Свет проталкивает тьму ...
Сообщения
86
Репутация
1
Zaramot is very Good! :smile:
Тогда ещё вопрос:
Почему не работает, если вместо ShellExecute поставить Run?
И зачем нужно вот это?
Код:
func _Process2Win($pid)
    if isstring($pid) then $pid = processexists($pid)
    if $pid = 0 then return -1
    $list = WinList()
    for $i = 1 to $list[0][0]
        if $list[$i][0] <> "" AND BitAnd(WinGetState($list[$i][1]),2) then
            $wpid = WinGetProcess($list[$i][0])
            if $wpid = $pid then return $list[$i][0]
        EndIf
    next
    return -1
endfunc
 
Автор
Mancoffee

Mancoffee

Свет проталкивает тьму ...
Сообщения
86
Репутация
1
Как совместить параметры? Допустим файл настроек задаётся вот так
Код:
'/l=C:\Windows /i=wincmd64.ini'
Если так, то "Незавершённая строка", если прописываю абсолютный путь, то как правильно прописать? (ни в двойных кавычках, ни в одинарных не получается, пишет Не удаётся найти ...путь... Проверьте, правильно ли указано имя и повторите попытку)
Нужно просто всё в одну сразу вместе с программой
Код:
Run("C:\Total\Totalcmd.exe /l=C:\Windows /i=wincmd64.ini")

Почему-то через параметры не работает
Код:
Run("C:\Total\Totalcmd.exe", "", "/l=C:\Windows /i=wincmd64.ini")
 

Skif_off

Знающий
Сообщения
173
Репутация
12
В случае запуска нескольких копий Total Commander скрипт лажает, минимум в половине случаев закрывает не то окно.

Есть отличный способ точно узнать родительский процесс: с помощью плагина Autorun можно добавить переменную окружения
Код:
SetEnv /EV TCPID %AUTORUN_TCPID%

Т.о., в скрипте, как дочернем процессе, будут известны имя процесса (TOTALCMD.EXE или TOTALCMD64.EXE) и его PID:
Код:
$COMMANDER_EXE = EnvGet("COMMANDER_EXE")
$TCPID = EnvGet("TCPID")


Как точно узнать окно? Не совсем понимаю, как работает функция _Process2Win(), но в текущем виде временами она лажает.


Добавлено:
Сообщение автоматически объединено:

Спасибо, что не успели откликнуться, напрягся и сумел разобраться :smile:
Изменил функцию, чтобы получать на выходе не заголовок окна, а уникальный Handle.
В конечном итоге, скрипт перезапуска целиком, без смены битности ТС:
Код:
Global $Title

$COMMANDER_EXE = EnvGet("COMMANDER_EXE")
$TCPID = EnvGet("TCPID")

$Title = _Process2Win($TCPID)
WinClose($Title)
Sleep(500)
Run($COMMANDER_EXE)

Func _Process2Win($Pid)
    If IsString($Pid) Then $Pid = ProcessExists($Pid)
    If $Pid = 0 Then Return -1
    $List = WinList()
    For $i = 1 To $List[0][0]
        If $List[$i][0] <> "" And BitAND(WinGetState($List[$i][1]), 2) Then
            $wPid = WinGetProcess($List[$i][1])
            If $wPid = $Pid Then Return $List[$i][1]
        EndIf
    Next
    Return -1
EndFunc



Добавлено:
Сообщение автоматически объединено:

Есть проблема при попытке перезапустить с админскими правами ("*" в начале команды или меню ПКМ на тулбаре), т.к. в таком случае дочерний процесс AutoIt с админскими правами не наследует переменные окружения.
Вариант решения: дописать в команду запуска %TCPID% "%COMMANDER_EXE%" через пробел, а EnvGet() заменить на
Код:
$TCPID = $CmdLine[1]
$COMMANDER_EXE = $CmdLine[2]
 

gora

Знающий
Сообщения
315
Репутация
19
Skif_off
Ваше решение заточено только для пользователей
Skif_off [?]
Остальным оно не подойдет, а "заставлять" пользователей устанавливать плагин ради работы скрипта не айс.
 

Skif_off

Знающий
Сообщения
173
Репутация
12
gora [?]
Слово "заставлять" совершенно неуместно :smile: Предложил вариант, если кто-то использует плагин Autorun - ему может быть интересно.
для TCFS2Tools, например, а еще, одной строкой в конфиге
Код:
SetEnv /EV OIT_DATA_PATH %COMMANDER_PATH%\Plugins\WLX\uLister
можно сделать uLister полностью портативным
Вообще, сначала думал искать родительский процесс.
Четко с несколькими копиями ТС работает Tinny TC Restarter, ЕМНИП, но у меня скрипт не только перезапускает.

Собственно, изменение функции _Process2Win() (замена Title на Handle) само по себе может оказаться интересным: т.к. скрипт запускается из ТС, то можно искать последнее активное окно и прибивать - правильный Handle гарантирует закрытие нужного окна.
 

Skif_off

Знающий
Сообщения
173
Репутация
12
+Небольшая (хотя как посмотреть) оптимизация, ведь скрипт для ТС: в функции _Process2Win()
Код:
;заменить
$List = WinList()
;на
$List = WinList("[CLASS:TTOTAL_CMD]")

Функция тратила ~2.10-2.25 мс на моем железе, с уточнением - 1.01-0.82.

Добавлено:
Наверное, лучше всё-таки копать в сторону
Код:
#include <WinAPIEx.au3>
$iParentPID = _WinAPI_GetParentProcess(@AutoItPID)

Проверил работу _WinAPI_GetParentProcess() в т.ч. в WinPE (использую в функции поиска и закрытия дочерних отдельных окон поиска и синхронизации). С %COMMANDER_EXE% - _WinAPI_GetProcessFileName().

В общем, еще вернусь :smile: Допиливаю _Close_TFindFile_And_TCmpForm() и еще пару мелочей.
 
Верх