Autorun

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

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

Аватара пользователя
Orion9
Сообщения: 1283
Зарегистрирован: Пн янв 01, 2024 17:18

Сообщение Orion9 »

AkulaBig
Не ради спора или попыток что-то доказать, а исключительно из любви к Autorun )

[cut]Win+[ запуск exiftool для каждого файла. Win+] держит процесс открытым и взаимодействует с ним через файл аргументов. Win+[ взаимодействует с процессом через stdin и stdout. Во временном каталоге создаются файлы exif_0, exif_1 и exif_2 с выхлопами каждого режима. Выхлопы должны совпадать за исключением метки (тега) последнего времени доступа и маркера {ready} для последнего режима.

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

SetHotkeyAction /K:W /V:219 TestExiftoolSpeed 0
SetHotkeyAction /K:W /V:221 TestExiftoolSpeed 1
SetHotkeyAction /K:W /V:220 TestExiftoolSpeed 2

Static sExif = COMMANDER_PATH & "\Plugins\wlx\ExifToolView\exiftool.exe"
Static sExifOut = TEMP & "\exiftool_out.txt", sExifArgs = TEMP & "\exiftool_args.txt"

Static hChildStdInWr = 0
Static hChildStdOutRd = 0
Static hChildStdInRd = 0
Static hChildStdOutWr = 0

Static hProcess = 0
Static hThread = 0

#TestExiftoolSpeed(3)

Func TestExiftoolSpeed(StayOpen)
    Local sFile = "", j, files = 0, str
    Local sPath = RequestCopyDataInfo("SP")
    Local sName = RequestCopyDataInfo("SN")

    Static aSel = List()
    aSel.Count = 0    
    aSel.Text = GetSelectedItems(3, 0)
    If aSel.Count = 0 Then aSel.Add(sName)
    
    If StayOpen = 1 And Not ProcessExist("exiftool.exe") Then
       DllCall("kernel32.dll\DeleteFileW", "Wstr", sExifOut)       
       DllCall("kernel32.dll\DeleteFileW", "Wstr", sExifArgs)    
       FileWrite(sExifArgs, "", "UTF-8 NOBOM")       
       ShellExec /TT /SW_HIDE %sExif% "-stay_open True -@ ""%sExifArgs%"""
       ShowHint("Запуск exiftool.exe") 
       Sleep(1000)
       Local nPID = ProcessGetId("exiftool.exe") 
       If nPID = 0 Then Return MsgBox("Процесс ExifTool не запущен")
    EndIf
    
    If StayOpen = 2 Then 
       If Not StartExifProcess() Then Return ShowHint("Операция прервана")
    EndIf
    
    If StayOpen = 3 Then 
       If StartExifProcess() Then
          WriteLine("-G")  
          WriteLine("-S")  
          WriteLine("-lang")
          WriteLine("ru")        
          WriteLine("d:\Temp\Images\test.jpg")
          WriteLine("-execute")
          #MsgBox(hProcess & " " & hChildStdInWr  & " " & hChildStdOutRd  & " " & hChildStdInRd  & " " & hChildStdOutWr )
          MsgBox(ReadResponse())
          Return ExifClose()
       Else
          Return ShowHint("Операция прервана")
       EndIf
    EndIf
    
    T1 = GetUptime()
    
    ShowHint("Обработка выделенного Exiftool.exe")
    For j = 0 To aSel.Count - 1
    
        sFile = sPath & aSel[j]
        
        If FileExist(sFile) And Not StrPos(FileGetAttr(sFile), "D") Then 
           files += 1
           str &= ExiftoolInfo(sFile, StayOpen)
        EndIf   
        
    Next
    
    T2 = Round(GetUptime() - T1, 0) / 1000
    ShowHint("Выбрано: " & aSel.Count & auCRLF & _
             "Обработано: " & files & auCRLF & _
             "-stay_open: " & (StayOpen ? "Да" : "Нет") & auCRLF & _
             "stdin/stdout: " & (StayOpen = 2 ? "Да" : "Нет") & auCRLF & _             
             "Объем данных: " & SizeFormat(StrLen(str), 0, 'B', 2) & auCRLF & _             
             "Время операции: " &  StrFormat("%.3f", T2) & " sec")
    ClipPut(str)
    FileWrite(TEMP & "\_exif_" & StayOpen, str, "UTF-8")
    If StayOpen = 2 Then ExifClose()
    If StayOpen = 1 Then 
       ProcessTerminate("exiftool.exe")
       Sleep(100)
       DllCall("kernel32.dll\DeleteFileW", "Wstr", sExifOut)       
       DllCall("kernel32.dll\DeleteFileW", "Wstr", sExifArgs)
    EndIf   
EndFunc

Func ExiftoolInfo(FileName, StayOpen)
    If StayOpen = 2 Then
       #WriteLine("-G")
       #WriteLine("-S")
       #WriteLine("-lang")
       #WriteLine("ru")
       #WriteLine(FileName)       
       #WriteLine("-execute")
       WriteLine("-G" & auCRLF & _
                 "-S" & auCRLF & _
                 "-lang" & auCRLF & _
                 "ru"    & auCRLF & _
                 Filename & auCRLF & _                  
                 "-execute" & auCRLF)
       Return ReadResponse() & auCRLF
    EndIf
    If Not StayOpen Then
       ProcessExecGetOutput /C:65001 out %sExif% '-charset filename=Russian -lang ru -G -S "%FileName%"'
    Else   
       If FileExist(sExifOut) Then
          DllCall("kernel32.dll\DeleteFileW", "Wstr", sExifOut)
       EndIf
       Local sArgs = "-G"   & auCRLF & _ 
                     "-S"   & auCRLF & _             
                     "-lang" & auCRLF & _
                     "ru"    & auCRLF & _                     
                     "-W+!"  & auCRLF & sExifOut & auCRLF & FileName & auCRLF & "-execute" & auCRLF       
       Static obj = BinaryFile(sExifArgs, "a")    
       obj.WriteStr(sArgs, "", "UTF-8")
       out = "<time-out>"
       For i = 1 To 50
           If FileExist(sExifOut) Then
              out = FileRead(sExifOut, 0, "UTF-8")
              DllCall("kernel32.dll\DeleteFileW", "Wstr", sExifOut)
              Break
           EndIf
           Sleep(10)
       Next
    EndIf   
   Return out
EndFunc

Func StartExifProcess()
    # Настройка атрибутов безопасности для наследования дескрипторов
    Local Sec = Buffer(auX64 ? 24 : 12)
    Sec.Zero()
    Sec.SetNum(0, "UInt", Sec.size) # nLength
    If auX64 Then
       Sec.SetNum(8, "Ptr", 0)   # lpSecurityDescriptor
       Sec.SetNum(16, "Int", 1)  # bInheritHandle
    Else
       Sec.SetNum(4, "Ptr", 0)
       Sec.SetNum(8, "Int", 1)
    EndIf
    
    # Создаем Pipe для STDIN (Запись из Autorun -> Чтение в ExifTool)
    If Not DllCall("CreatePipe", "Ptr*", @hChildStdInRd, "Ptr*", @hChildStdInWr, "Ptr", Sec.Ptr, "UInt", 0) Then
       MsgBox("Error CreatePipe STDIN")
       Return 0
    EndIf   

    # Создаем Pipe для STDOUT (Запись из ExifTool -> Чтение в Autorun)
    if Not DllCall("CreatePipe", "Ptr*", @hChildStdOutRd, "Ptr*", @hChildStdOutWr, "Ptr", Sec.Ptr, "UInt", 0) Then
        DllCall("CloseHandle", "Ptr", hChildStdInRd)
        DllCall("CloseHandle", "Ptr", hChildStdInWr)
        MsgBox("Error CreatePipe")
        Return 0       
    EndIf

    # Запрещаем наследование нашей (записывающей/читающей) стороны каналов
    DllCall("SetHandleInformation", "Ptr", hChildStdInWr, "UInt", 1, "UInt", 0)
    DllCall("SetHandleInformation", "Ptr", hChildStdOutRd, "UInt", 1, "UInt", 0)

    # Настройка STARTUPINFO
    Local SI = Buffer(auPtrSize = 8 ? 104 : 68)
    SI.Zero()
    SI.SetNum(0, "UInt", SI.Size)
    SI.SetNum(auX64 ? 60 : 44, "UInt", 0x00000101) # STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW
    SI.SetNum(auX64 ? 64 : 48, "UShort", 0) # SW_HIDE (скрывает окно консоли)
    SI.SetNum(SI.Size - 3 * auPtrSize, "Ptr", hChildStdInRd)
    SI.SetNum(SI.Size - 2 * auPtrSize, "Ptr", hChildStdOutWr)
    SI.SetNum(SI.Size - auPtrSize, "Ptr", hChildStdOutWr) # Дублируем stdout в stderr

    # Настройка PROCESS_INFORMATION
    PI = Buffer(auPtrSize = 8 ? 24 : 16)
    PI.Zero()

    # Командная строка запуска
    Local cmdLine = '"' & sExif & '" -stay_open True -@ -'

    # Флаг CREATE_NO_WINDOW (0x08000000) полностью блокирует создание консольного окна
    If Not DllCall("CreateProcessW", "Ptr", 0, "WStr", cmdLine, _
                                     "Ptr", 0, "Ptr", 0, "Int", 1, "UInt", 0x08000000, _
                                     "Ptr", 0, "Ptr", 0, "Ptr", SI.Ptr, "Ptr", PI.Ptr) Then
        # Закрываем все открытые дескрипторы при ошибке
        DllCall("CloseHandle", "Ptr", hChildStdInRd)
        DllCall("CloseHandle", "Ptr", hChildStdInWr)
        DllCall("CloseHandle", "Ptr", hChildStdOutRd)
        DllCall("CloseHandle", "Ptr", hChildStdOutWr)
        MsgBox("Error CreateProcess")
        Return 0  
    EndIf

    # Сохраняем нужные дескрипторы
    hProcess = PI.GetNum(0, "Ptr")
    hThread = PI.GetNum(auPtrSize, "Ptr")

    # Закрываем дескрипторы, которые больше не нужны родительскому процессу
    DllCall("CloseHandle", "Ptr", hChildStdInRd)
    DllCall("CloseHandle", "Ptr", hChildStdOutWr)
    
    Return 1
EndFunc

Func WriteLine(text)    
    rawString = text & auCRLF
    # ExifTool ожидает UTF-8 или системную кодировку (зависит от настроек, UTF-8 наиболее универсален)
    bufLen = StrLen(rawString) * 2
    buf = Buffer(bufLen)
    buf.Zero()
    bufWr = buf.SetStr(rawString, 0, bufLen, "UTF-8")
    # Запись через WinAPI WriteFile
    Local bytesWritten = 0
    DllCall("WriteFile", "Ptr", hChildStdInWr, "Ptr", buf.ptr, "UInt", bufWr, "UInt*", @bytesWritten, "Ptr", 0)
    Free(buf)
EndFunc

Func ReadResponse()
    Local output = "", chunk = ""
    # Буфер для побайтового/посимвольного чтения из пайпа
    Static readBuf = Buffer(1024*2) 
    readBuf.Zero()
    While 1       
       Local bytesRead = 0
       If Not DllCall("ReadFile", _
                      "Ptr", hChildStdOutRd, _
                      "Ptr", readBuf.Ptr, "UInt", readBuf.Size, "UInt*", @bytesRead, "Ptr", 0) Then
          Break
       EndIf

       If bytesRead <= 0 Then Break

       chunk = readBuf.GetStr(0, bytesRead, "UTF-8") 
       output &= chunk              
       If StrPos(chunk, "{ready}") Then 
          Break       
       EndIf
    Wend
    Return StrTrim(output)
EndFunc

Func ExifClose()
    If hChildStdInWr Then
       WriteLine("-stay_open")
       WriteLine("False")
       DllCall("CloseHandle", "Ptr", hChildStdInWr)
       hChildStdInWr = 0
    EndIf
    If hChildStdOutRd Then 
       DllCall("CloseHandle", "Ptr", hChildStdOutRd)
       hChildStdOutRd = 0
    EndIf   
    if hProcess Then 
       DllCall("CloseHandle", "Ptr", hProcess)
       hProcess = 0
    EndIf   
    If hThread Then
       DllCall("CloseHandle", "Ptr", hThread)
       hThread = 0
    EndIf   
EndFunc
[/cut]
Пришлось целый вечер на это убить, но чего только не сделаешь ради любви :)
AkulaBig писал(а):Вот возьмите конкретный файл и протестируйте, за сколько по нему выведется инфа:
Этот файл шифрованный и обрабатывается медленно. Для таких файлов должен быть предусмотрен таймаут. В выхлопе об этом так и сказано

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

[ExifTool] ExifToolVersion: 13.52
[ExifTool] Warning: [minor] Decryption is very slow for encryption V5.6 or higher
[File] FileName: mwt-2021-proceedings.pdf
[File] Directory: D:/Temp
[File] FileSize: 70 MB
AkulaBig писал(а):А в действительности работает медленнее, чем с временными файлами.
Работать может медленнее, если буфер для чтения маленький. Я специально сделал на однобайтовом буфере сначала, чтобы посмотреть скорость. Работает в 3-4 раза медленнее, чем с файлами, но раз в 10 быстрее, чем если просто exiftool.exe вызывать. Увеличив буфер до 2Кб удалось по скорости обойти режим работы с файлами на 150-200% в зависимости числа и типов файлов.
AkulaBig писал(а): Почему не получится, если у меня получилось и результаты теста я привел?
Я не знаю, что у вас именно получилось. WinScriptAdv это костыль, который создает временный скрипт для каждого файла и с нуля его запускает. Это очень ограничивает действия. В частности не получится повторить код на Autohotkey, который сразу предлагал болван, и который я повторил на Autorun.
AkulaBig писал(а):Ни одного скрипта мне запустить не удалось.
Первый скрипт с ComObject рабочий, я только заменил теги на "-G" и указал свои пути

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

; Формируем пакет аргументов для текущего файла.
; Каждая опция и значение должны быть на новой строке.
;cmd := "-Artist=Автор " index "`n"
;cmd .= "-Copyright=2026 Студия`n"
cmd := "-G`n"        
cmd .= targetFile "`n" ; Путь к файлу передается в конце пакета команд
cmd .= "-execute"      ; ОБЯЗАТЕЛЬНО: сообщает ExifTool, что этот пакет команд пора выполнить
Второй скрипт тоже рабочий, но только для X64. Чтобы он заработал в Autohotkey32 пришлось подкорректировать буфер

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

; Настройка атрибутов безопасности для наследования дескрипторов
SA := Buffer(12, 0)
NumPut("UInt", 12, SA, 0) ; nLength
NumPut("Ptr", 0, SA, 4)   ; lpSecurityDescriptor
NumPut("Int", 1, SA, 8)  ; bInheritHandle

И еще я забыл приложить второе сообщение из чата с примером вызова. Не думал все же, что займусь переводом на Autorun

[cut]

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

; 1. Инициализация процесса через WinAPI
exiftoolPath := "c:\Portable\exiftool.exe"
et := ExifToolPipe(exiftoolPath)

; 2. Передача команды (как в вашем оригинальном коде)
; Важно: каждая команда и опция для -stay_open должны идти отдельной строкой, 
; а в конце блока обязательно передается параметр "-execute"
et.WriteLine("-ImageSize")
et.WriteLine("c:\Portable\Images\test.jpg")
et.WriteLine("-execute")

;MsgBox("1")
; 3. Считывание ответа через WinAPI ReadFile до строки {ready}
response := et.ReadResponse()

MsgBox(response)

; 4. По завершении работы скрипта закрываем дескрипторы
et.Close()
[/cut]
Файлы .ahk обязательно должны сохраняться как UTF-8, иначе они могут не работать.
AkulaBig
Сообщения: 639
Зарегистрирован: Ср дек 03, 2008 11:48

Сообщение AkulaBig »

Orion9 писал(а):WinScriptAdv это костыль, который создает временный скрипт для каждого файла и с нуля его запускает.
Так любой wdx-плагин работает.
Orion9 писал(а):Этот файл шифрованный и обрабатывается медленно. Для таких файлов должен быть предусмотрен таймаут.
Ну это понятно. Я вам и привожу время реальной обработки. Что не так?
Orion9 писал(а):Пришлось целый вечер на это убить, но чего только не сделаешь ради любви
Только ради любви, это точно. Так как Ауторан х64 на нынешний момент не работает с ET толком и не понятно, будет ли работать. А если и будет работать, ничего не изменится. Алгоритм работы пользовательских колонок не Ауторан задает.
Аватара пользователя
Orion9
Сообщения: 1283
Зарегистрирован: Пн янв 01, 2024 17:18

Сообщение Orion9 »

AkulaBig писал(а):Так любой wdx-плагин работает
Скорее наоборот. У других wdx руки ничем не связаны, а WinScriptAdv делает это из-за необходимости.
AkulaBig писал(а):Только ради любви, это точно.
В данном случае только ради этого. Но как показывает практика, созданный когда-то код рано или поздно находит себе применение. Если понадобится работать с приложением через stdin и stdout, шаблон уже готов. Времени он, конечно, отнял прилично. Жаль, что болван сразу не выкидывает готовый код на Autorun.
AkulaBig
Сообщения: 639
Зарегистрирован: Ср дек 03, 2008 11:48

Сообщение AkulaBig »

Orion9 писал(а): Но как показывает практика, созданный когда-то код рано или поздно находит себе применение.
Конечно если когда-то придет время для использования этого кода, будет нужно тщательное тестирование. Так как сейчас на au3 у меня код в три раза короче и без всяких временных файлов. Так что только при условии, если вдруг этот код будет работать быстрее, будет смысл им воспользоваться.
К сожалению мне уже ясно, что в пользовательских колонках код с -stay_open False быстро работать не будет. Это тоже самое, что я запускаю новую копию exiftool для каждого файла. По крайней мере с WinScriptsAdv так получается. Думаю и сама логика говорит о том-же. Вот с временными файлами да, скорость возрастает, так как не надо делать -stay_open False и работа реально идет с одной копией ET.
Orion9 писал(а):У других wdx руки ничем не связаны, а WinScriptAdv делает это из-за необходимости.
Не понял, что означает эта фраза. Можете чуть подробнее?
Аватара пользователя
Orion9
Сообщения: 1283
Зарегистрирован: Пн янв 01, 2024 17:18

Сообщение Orion9 »

AkulaBig
Я сразу был против чтения через stdout. Столько усилий и ради чего — выиграть полсекунды? :lol: Имхо, работа через временные файлы оптимальный вариант для связки WinScriptAdv + ExifTool или Autorun + ExifTool. И скорость возрастает прилично, и с бубном прыгать не нужно.
AkulaBig писал(а):Можете чуть подробнее?
Имелось в виду, что WinScriptAdv работает в контексте создаваемых собой временных файлов, другим плагинам это не требуется.
AkulaBig
Сообщения: 639
Зарегистрирован: Ср дек 03, 2008 11:48

Сообщение AkulaBig »

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

Сообщение Orion9 »

AkulaBig писал(а):Проверять, используют ли они временный файл никакого желания нет
Плагины похожие на WinScriptAdv (хотя я знаю только один такой) наверняка работают по тем же принципам — создают временный файл и выполняют его во внешней среде. Это накладывает ограничения. Вот если делать свой wdx, то руки подобными ограничениями связаны не будут, это прежде всего я имел в виду.
AkulaBig писал(а):Но варианты от ИИ выкладывали
Я думал, что если варианты окажутся несложными, то можно будет попробовать. И вариант с ComObject действительно несложный, но в Autorun этого объекта нет. Если открыть справку Autohotkey в разделе внешних библиотек (External Libraries), можно увидеть, что ComObject — пожалуй, единственный объект, который не сделал Loopback из всего раздела, остальное он закрыл :shock: Думаю, в последнее время он плотно сидел на ИИ — новые версии плагина слетали как с конвеера :lol:

[cut]Autorun ❤️[/cut]
FallenAngel
Сообщения: 47
Зарегистрирован: Вт дек 30, 2025 20:01

Сообщение FallenAngel »

SetEnv /A PATH ;%COMMANDER_PATH%\Utils
У меня эта конструкция "отпадает" все время. Приходится часто перезапускать ТС. Может можно добавить какой-то цикл чтобы он передобавлял раз в 5 минут этот путь?
Аватара пользователя
Orion9
Сообщения: 1283
Зарегистрирован: Пн янв 01, 2024 17:18

Сообщение Orion9 »

FallenAngel
Можно, но хотелось бы понять, что это за глюк.

В Autorun есть функция GetState, через которую можно получить состояние переменных окружения. Я сделал небольшой скрипт, который запускает описываемый вами цикл в фоне, но вместо добавления пропавшего пути назад к переменной PATH, он просто информирует о том, что путь пропал и копирует в буфер состояние всех переменных.

[cut]

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

RunThread("CheckEnvState")

Func CheckEnvState()
   Local interval = 10   # sec.  
   Local envname = ";" & COMMANDER_PATH & "\Utils"
   Local envs = GetState("envvars")
   If Not StrPos(envs, envname) Then
      MsgBox("Поток «CheckEnvState» не запущен." & auCRLF & auCRLF & _
             "Путь не найден в окружении ;%COMMANDER_PATH%\Utils", "Autorun", 0+48)
      Return
   EndIf 
   While 1
       Sleep(interval*1000)
       envs = GetState("envvars")
       If Not StrPos(envs, envname) Then
          MsgBox("Путь больше не доступен ;%COMMANDER_PATH%\Utils" & auCRLF & auCRLF & _
                 "Скопировать состояние переменных в буфер?", "Autorun", 4+48+4096)
          If EXTENDED = 6 Then 
             ClipPut(envs)
             MsgBox("Состояние переменных скопировано в буфер", "Autorun", 0+64)   
          EndIf
          Return
       EndIf
   WEnd
EndFunc
[/cut]
Если при старте ТС нужный путь в переменных отсутствует, поток с циклом не будет запущен.

Важно отловить момент, когда путь отваливается, чтобы понять, что вызывает проблему. Проверка происходит каждые 10 сек. Окно сообщения должно появиться поверх всех окон.

Можно изменить значение переменной Path в wfx плагине, чтобы долго не ждать и проверить работу функции.
FallenAngel
Сообщения: 47
Зарегистрирован: Вт дек 30, 2025 20:01

Сообщение FallenAngel »

Спасибо, буду наблюдать что да как.

Еще бы словить ВНЕЗАПНОЕ закрытие ТС. Происходит это нечасто, но дико раздражает.

При клике по 1) заголовку панелей или 2) меню (как правило Start) - ТС просто закрывается. В журналах пусто. В %PROGRAMDATA%\Microsoft\Windows\WER\ReportArchive - тоже.

Проявляется на разных ПК с разными ОС.
Аватара пользователя
SergM2026
Сообщения: 3
Зарегистрирован: Ср май 27, 2026 16:05

Сообщение SergM2026 »

FallenAngel писал(а): При клике по 1) заголовку панелей или 2) меню (как правило Start) - ТС просто закрывается. В журналах пусто.
А при этом в фоне какой-то процесс был запущен? У меня такое бывало, но только когда в фоне шло копирование больших файлов (фильмов на флешку).
Аватара пользователя
Orion9
Сообщения: 1283
Зарегистрирован: Пн янв 01, 2024 17:18

Сообщение Orion9 »

FallenAngel писал(а):Спасибо, буду наблюдать что да как.
Надеюсь, получится отловить. Если все переменные не нужны, а нужна только переменная %Path%, то вместо GetState("envvars") можно использовать GetEnv("path"). Возможно, так будет проще сравнить. Теперь в буфер попадает два снимка: %Path% при старте ТС + %Path% после появления проблемы.

[cut]

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

RunThread("CheckEnvState")

Func CheckEnvState()
   Local interval = 10   # sec.  
   Local envname = ";" & COMMANDER_PATH & "\Utils"
   #Local snap = GetState("envvars")
   Local snap = GetEnv("path")
   If Not StrPos(snap, envname) Then
      MsgBox("Поток «CheckEnvState» не запущен." & auCRLF & auCRLF & _
             "Путь не найден в окружении ;%COMMANDER_PATH%\Utils", "Autorun", 0+48)
      Return
   EndIf 
   While 1
       Sleep(interval*1000)
       #envs = GetState("envvars")
       envs = GetEnv("path")
       If Not StrPos(envs, envname) Then
          MsgBox("Путь больше не доступен ;%COMMANDER_PATH%\Utils" & auCRLF & auCRLF & _
                 "Скопировать состояние переменных в буфер?", "Autorun", 4+48+4096)
          If EXTENDED = 6 Then 
             ClipPut(snap & auCRLF & auCRLF & "-------------" & auCRLF & auCRLF & envs)
             MsgBox("Состояние переменных скопировано в буфер", "Autorun", 0+64)   
          EndIf
          Return
       EndIf
   WEnd
EndFunc
[/cut]
SergM2026 писал(а): У меня такое бывало
Это немного другая проблема, ранее она обсуждалась. Соответственно, самое простое решение избавится от этой проблемы — положить лицензию в корень ТС :)
FallenAngel
Сообщения: 47
Зарегистрирован: Вт дек 30, 2025 20:01

Сообщение FallenAngel »

Orion9 писал(а):Соответственно, самое простое решение избавится от этой проблемы — положить лицензию в корень ТС
Как это связано? После старта ТС может пройти пол дня.
Или есть зависимость не только сразу после старта?
Аватара пользователя
Orion9
Сообщения: 1283
Зарегистрирован: Пн янв 01, 2024 17:18

Сообщение Orion9 »

FallenAngel писал(а):Как это связано? После старта ТС может пройти пол дня.
Может и никак не связано. Но если в зарегистрированной версии такой проблемы нет, может как-то и связано.

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

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

FileAppend(COMMANDER_PATH & "\tc.log", StrFormat("%s %s %s запущен.\r\n", Date(), Time(), COMMANDER_EXE))

Pragma AutorunFinalizeSection

FileAppend(COMMANDER_PATH & "\tc.log", StrFormat("%s %s %s закрыт.\r\n\r\n", Date(), Time(), COMMANDER_EXE))
Если тотал действительно закрывается, а не вылетает, о чем это может говорить?

Кстати. Есть вариант при котором функция CheckEnvState может не сработать. Если к переменной %COMMANDER_PATH%\Utils приклеется другой путь без ";", то такой путь перестанет работать, но функция CheckEnvState проверяет только наличие подстроки, а подстрока %COMMANDER_PATH%\Utils останется без изменений. В результате функция не увидит проблем.

Лучше просто проверять любое изменение %Path%, которых после старта ТС не должно быть, если только по минимому.

[cut]

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

RunThread("CheckEnvState")

Func CheckEnvState()
   Local interval = 10   # sec.  
   Local envname = ";" & COMMANDER_PATH & "\Utils"
   #Local snap = GetState("envvars")
   Local snap = GetEnv("path")
   If Not StrPos(snap, envname) Then
      MsgBox("Поток «CheckEnvState» не запущен." & auCRLF & auCRLF & _
             "Путь не найден в окружении ;%COMMANDER_PATH%\Utils", "Autorun", 0+48)
      Return
   EndIf 
   While 1
       Sleep(interval*1000)
       #envs = GetState("envvars")
       envs = GetEnv("path")
       #If Not StrPos(envs, envname) Then
       #   MsgBox("Путь больше не доступен ;%COMMANDER_PATH%\Utils" & auCRLF & auCRLF & _
       If envs <> snap Then
          MsgBox("Переменная %Path% изменилась" & auCRLF & auCRLF & _       
                 "Скопировать состояние переменных в буфер?", "Autorun", 4+48+4096)                 
          If EXTENDED = 6 Then 
             ClipPut(snap & auCRLF & auCRLF & "-------------" & auCRLF & auCRLF & envs)
             MsgBox("Скопировано в буфер", "Autorun", 0+64)   
          EndIf
          #Return
          snap = envs
       EndIf
   WEnd
EndFunc
[/cut]
FallenAngel
Сообщения: 47
Зарегистрирован: Вт дек 30, 2025 20:01

Сообщение FallenAngel »

Orion9 писал(а):Может и никак не связано. Но если в зарегистрированной версии такой проблемы нет, может как-то и связано.
Ладно, я пока откатился на autoclick.dll. Понаблюдаю.
Orion9 писал(а):Лучше просто проверять любое изменение %Path%
Нашлась причина. При любом изменении PATH (удаление либо добавление) - переменная слетает о чем исправно сообщает CheckEnvState.

Прошу подтвердить такое поведение. Нужно понять, это глобальный баг или что-то частное.

Я часто работаю с PATH поэтому юзаю такой самописный скрипт
Ответить