Autorun
Модераторы: Avada, CaptainFlint, Nik, d-view, Моторокер
Orion9
Наконец-то дошли руки опробовать ваш вариант с type:
Да, файл в переменную считал. А вот как из переменной данные в файл записать, непонятно. Ну и данные в Win1251, а надо в юникоде.
Loopback
Для полноценной работы с файлом необходимо три команды:
FileOpen, FileWrite, FileClose. Ранее вы писали, что пока не планируете реализовывать работу с файлами, но может все-же дойдут у вас до этого руки. Ведь весь остальной функционал для работы с файлами есть.
Наконец-то дошли руки опробовать ваш вариант с type:
Код: Выделить всё
Func SwitchIniSect(sIni, sSect, sLng)
arrLang = List("eng", "rus")
Local TextFile, i
Local arrFile = List()
ProcessExecGetOutput TextFile %COMSPEC% '/c type "%sIni%"'
arrFile.Text = TextFile
For i = 0 To arrLang.Count-1
If StrPos(arrFile.Text, "[" & sSect & "_" & arrLang._Item[i] & "]") = 0 Then
arrFile.Text = StrReplace(arrFile.Text, "[" & sSect & "]", "[" & sSect & "_" & arrLang[i] & "]")
Break
EndIf
Next
Local ResTextFile = arrFile.Text
# ResTextFile должен быть файл
ShellExec /SW_HIDE /WAIT %COMSPEC% '/c type %ResTextFile% > %sIni%'
# ResTextFile какой синтаксис?
ShellExec /SW_HIDE /WAIT %COMSPEC% '/c call echo ResTextFile > %sIni%'
Free(arrLang)
Free(arrFile)
EndFunc
Loopback
Для полноценной работы с файлом необходимо три команды:
FileOpen, FileWrite, FileClose. Ранее вы писали, что пока не планируете реализовывать работу с файлами, но может все-же дойдут у вас до этого руки. Ведь весь остальной функционал для работы с файлами есть.
AkulaBig
Необходимость записи в файл средствами Autorun давно назревала, о чём я писал в топике. Если не ошибаюсь, Loopback тогда ответил, что с этим есть определенные сложности в реализации, но последние два сообщения добавляют оптимизма.
Раньше приходилось пользоваться жёстким костылем - записывать переменную в буфер обмена и сохранять содержимое на диск с помощью vbs-скрипта. Но это было до того, как в Autorun появилась функция DllCall. Сейчас, наверное, всё можно решить через Win API.
К сожалению, у меня сейчас не те возможности, чтобы во всём детально разобраться, но поскольку я давно хотел сделать такой вызов, то глянул буквально одним глазком:
https://learn.microsoft.com/en-us/windo ... g-to-files
В первой функции я эксперементировал с объектом buffer, но он здесь в принципе не нужен, если только не нужно сменить кодировку текста на UTF-8 или что-то такое же специфическое. Для ANSI работает такой вызов:
Если нужен UTF-16, то понадобится в 2 раза больше байт и тип данных 'wstr':
Вторая функция переключает секцию ассоциаций, но результат переключения пишет в другой файл, а не в Associations.ini. Опять же, если нужен Unicode, то должен быть "wstr" и удвоенное количество байт для записи.
Вообщем, можете попробовать, если срочно нужно. Но думаю, Loopback уже настроился на большой бонус в новой версии )
Необходимость записи в файл средствами Autorun давно назревала, о чём я писал в топике. Если не ошибаюсь, Loopback тогда ответил, что с этим есть определенные сложности в реализации, но последние два сообщения добавляют оптимизма.
Раньше приходилось пользоваться жёстким костылем - записывать переменную в буфер обмена и сохранять содержимое на диск с помощью vbs-скрипта. Но это было до того, как в Autorun появилась функция DllCall. Сейчас, наверное, всё можно решить через Win API.
К сожалению, у меня сейчас не те возможности, чтобы во всём детально разобраться, но поскольку я давно хотел сделать такой вызов, то глянул буквально одним глазком:
https://learn.microsoft.com/en-us/windo ... g-to-files
Код: Выделить всё
RegisterCommand 60017 "FileWriteTest"
RegisterCommand 60018 "AssocIniWriteTest"
Func FileWriteTest(lParam)
Local Const GENERIC_WRITE = 0x40000000, CREATE_ALWAYS = 2, FILE_ATTRIBUTE_NORMAL = 128
Local bytes = 0
Local file = COMMANDER_PATH & "\Ini\WriteTest.ini"
Local txt
txt = "Reading From and Writing to Files" & auCRLF & auCRLF & _
"An application reads from and writes to a file by using the ReadFile, ReadFileEx, WriteFile, and WriteFileEx functions." & auCRLF & auCRLF & _
"These functions require a handle to a file to be opened for reading and writing, respectively. They read and write a specified number of bytes at the location indicated by the file pointer. The data is read and written exactly as specified; the functions do not format the data."
Local buf = Buffer(StrLen(txt))
buf.SetStr(txt, 0,"","ANSI")
Local nBytes = StrLen(txt)
#Local nBytes = StrLen(txt) * 2
Local hFile = DllCall("CreateFileW", "wstr", file, "dword", GENERIC_WRITE, "dword", 0, "ptr", 0, "dword", 2, "dword", 128, "ptr", 0, "handle")
#MsgBox("Handle " & hFile)
DllCall("WriteFile", "handle", hFile, 'ptr', buf.ptr, 'dword', buf.size, "dword*", @bytes, 'ptr', 0)
#DllCall("WriteFile", "handle", hFile, 'wstr', txt, 'dword', nBytes, "dword*", @bytes, 'ptr', 0)
DllCall("CloseHandle", "handle", hFile)
MsgBox("Buffer size " & buf.size & auCRLF & "Bytes written " & bytes)
EndFunc
Func AssocIniWriteTest(lParam)
Local Const GENERIC_WRITE = 0x40000000, CREATE_ALWAYS = 2, FILE_ATTRIBUTE_NORMAL = 128
Local bytes = 0
Local ini = COMMANDER_PATH & "\Ini\Associations.ini"
Local file = COMMANDER_PATH & "\Ini\WriteTest.ini"
Local out
ProcessExecGetOutput out %COMSPEC% '/c type "%ini%"'
If StrPos(out, '[-Associations]') > 0 Then
out = StrReplace(out, '[-Associations]', '[Associations]')
Else
out = StrReplace(out, '[Associations]', '[-Associations]')
Endif
Local nBytes = StrLen(out)
Local hFile = DllCall("CreateFileW", "wstr", file, "dword", GENERIC_WRITE, "dword", 0, "ptr", 0, "dword", CREATE_ALWAYS, "dword", FILE_ATTRIBUTE_NORMAL, "ptr", 0, "handle")
DllCall("WriteFile", "handle", hFile, 'str', out, 'dword', nBytes, "dword*", @bytes, 'ptr', 0)
DllCall("CloseHandle", "handle", hFile)
MsgBox("Handle " & hFile & auCRLF & "Bytes written " & bytes)
EndFuncКод: Выделить всё
TOTALCMD#BAR#DATA
60017
%COMMANDER_EXE%
Тест записи текста в файл
1
-1
Код: Выделить всё
TOTALCMD#BAR#DATA
60018
%COMMANDER_EXE%
Тест переключения Associations.ini в WriteTest.ini
1
-1
Код: Выделить всё
DllCall("WriteFile", "handle", hFile, 'str', txt, 'dword', nBytes, "dword*", @bytes, 'ptr', 0)
Код: Выделить всё
Local nBytes = StrLen(txt) * 2
DllCall("WriteFile", "handle", hFile, 'wstr', txt, 'dword', nBytes, "dword*", @bytes, 'ptr', 0)
Вообщем, можете попробовать, если срочно нужно. Но думаю, Loopback уже настроился на большой бонус в новой версии )
AkulaBig
Если файл - обычный текстовый небольшой файл, то type хорошо подходит для считывания. Но DllCall - это ключ от всех дверей. Будь у меня возможность, я бы глубже изучил именно DllCall и Win API. Не так уж это и сложно, нужно просто всё пробовать и смотреть, как работают различные параметры вызова с различными флагами и аттрибутами. Единственный минус: это отнимает много времени и усилий, что, разумеется, не всегда можно себе позволить.
Если файл - обычный текстовый небольшой файл, то type хорошо подходит для считывания. Но DllCall - это ключ от всех дверей. Будь у меня возможность, я бы глубже изучил именно DllCall и Win API. Не так уж это и сложно, нужно просто всё пробовать и смотреть, как работают различные параметры вызова с различными флагами и аттрибутами. Единственный минус: это отнимает много времени и усилий, что, разумеется, не всегда можно себе позволить.
Так и есть. Теперь вся Windows у наших ног )AkulaBig писал(а):Офигеть!!!
Можно добавить, например, собственных звуковых событий в ТС через вызов функции PlaySound:
Код: Выделить всё
DllCall("Winmm.dll\PlaySoundW", "wstr", "C:\Windows\Media\tada.wav", "ptr", 0, "dword", 131072 + 1)
Код: Выделить всё
Set oFS = CreateObject("SAPI.SpFileStream")
oFS.Open "C:\Windows\Media\tada.wav"
oFS.CloseИ ведь это только простенький пример, а перечень возможностей действительно огромен.
Этот пример я уже выше видел. И в справке примеры видел. Но вот как прикрутить функции для работы с файлом. Пока не совсем понятно.Orion9 писал(а):Можно добавить, например, собственных звуковых событий в ТС через вызов функции PlaySound:
Добавлено спустя 1 час 40 минут:
Попробовал открыть файл:
hHandle = DllCall("CreateFile" , sIni, 511, 0, 0, 0, 0, 0)
Пустое значение возвращает. В AutiIt тоже есть функция DllCall. Попытаться к ней что-ли присер поискать.
Добавлено спустя 8 минут:
Надо ведь для значения тип писать. Попробую переделать.
Добавлено спустя 32 минуты:
А ведь получилось:
Код: Выделить всё
Local hHandle = DllCall("CreateFile", _
"wstr", sIni, _
"int", 0x80000000 Or 0x40000000, _
"int", 0, _
"ptr", 0, _
"int", 3, _
"int", 0x00000080, _
"int", 0)
Интересно, чем заменить в
Код: Выделить всё
DllCall("kernel32.dll", "int", "ReadFile", "hwnd", $hand, "ptr*", DllStructGetPtr($strData), "int", 32, "long_ptr", 0, "int", 0)
Orion9
Это на ahk. Можете DllStructGetPtr($strData) перевести на Autorun?
AkulaBig
Если завтра будет возможность, то посмотрю на счет ReadFile, но эта функция менее важна, т.к. сейчас считывать можно и через type. Именно поэтому, пока мне предоставилась возможность, я сосредоточился на WriteFile.
В принципе, все должно работать, если к вашему примеру добавить после строки:
Что-то вроде:
Но нужно проверить и посмотреть на практике. Хотя и другие проверки в коде не помешали бы, кроме проверки хэндла, а лучше бэкап файла перед записью.
Если завтра будет возможность, то посмотрю на счет ReadFile, но эта функция менее важна, т.к. сейчас считывать можно и через type. Именно поэтому, пока мне предоставилась возможность, я сосредоточился на WriteFile.
В принципе, все должно работать, если к вашему примеру добавить после строки:
Код: Выделить всё
Local ResTextFile = arrFile.TextКод: Выделить всё
Local nBytes = StrLen(ResTextFile)
Local Const GENERIC_WRITE = 0x40000000, CREATE_ALWAYS = 2, FILE_ATTRIBUTE_NORMAL = 128
Local bytes = 0
Local hFile = DllCall("CreateFileW", "wstr", sIni, "dword", GENERIC_WRITE, "dword", 0, "ptr", 0, "dword", CREATE_ALWAYS, "dword", FILE_ATTRIBUTE_NORMAL, "ptr", 0, "handle")
If hFile > 0 Then
DllCall("WriteFile", "handle", hFile, 'str', ResTextFile, 'dword', nBytes, "dword*", @bytes, 'ptr', 0)
DllCall("CloseHandle", "handle", hFile)
EndifНе катит совершенно. Ведь type считывает в ANSI, а надо в Юникод.Orion9 писал(а):сейчас считывать можно и через type
Код: Выделить всё
Local hFile = DllCall("CreateFileW", "wstr", sIni, "dword", GENERIC_WRITE, "dword", 0, "ptr", 0, "dword", CREATE_ALWAYS, "dword", FILE_ATTRIBUTE_NORMAL, "ptr", 0, "handle")А насчет ReadFile пришла идея. Надо примеры смотреть на win api, как буфер создавать. Понятно, что на autoit и ahk они применяют существующую функцию, но должен быть и другой вариант.
Интересно, что в TCIMG есть функция DllStructGetPtr.
'str', ResTextFile - как-раз это не работает. Здесь ссылка должна быть.
Да, совсем забыл, что нужен именно Юникод. Но обойти можно, если использовать ключ /u. Вот полный пример чтения и записи файла в юникоде с использованием type:Не катит совершенно. Ведь type считывает в ANSI, а надо в Юникод.
Код: Выделить всё
RegisterCommand 60018 "TypeUnicodeTest"
Func TypeUnicodeTest(lParam)
Local Const GENERIC_WRITE = 0x40000000, CREATE_ALWAYS = 2, FILE_ATTRIBUTE_NORMAL = 128
Local bytes = 0
Local sIni = COMMANDER_PATH & "\Ini\Start.ini"
Local out
ProcessExecGetOutput /C:1200 out %COMSPEC% '/u /c type "%sIni%"'
If StrPos(out, '[user_eng]') > 0 Then
out = StrReplace(out, '[user_eng]', '[user]')
Else
out = StrReplace(out, '[user]', '[user_eng]')
Endif
Local nBytes = StrLen(out) * 2
Local hFile = DllCall("CreateFileW", "wstr", sIni, "dword", GENERIC_WRITE, "dword", 0, "ptr", 0, "dword", CREATE_ALWAYS, "dword", FILE_ATTRIBUTE_NORMAL, "ptr", 0, "handle")
If hFile > 0 Then
Local bom = Chr(0xFEFF)
DllCall("WriteFile", "handle", hFile, 'wstr', bom, 'dword', 2, "dword*", @bytes, 'ptr', 0)
DllCall("WriteFile", "handle", hFile, 'wstr', out, 'dword', nBytes, "dword*", @bytes, 'ptr', 0)
DllCall("CloseHandle", "handle", hFile)
Endif
EndFunc
Не знаю, что может быть не так с моим хэндлом, но всё работаетУ вас пропущен параметр после "handle". Собственно рабочий CreateFile я выше привел.
Ini-файл с нашим многострадальным Майклом Тело )
[cut="Start.ini"][user]
menu1=-Помощь
menu2=Справка 9.51 (ru)
cmd2=%COMMANDER_PATH%\Help\Wcmd_rus.chm
menu3=Сочетания клавиш 10.52 (ru)
cmd3=%COMMANDER_PATH%\Help\TC.Hotkeys.chm
menu4=Все команды 10.52 (ru)
cmd4=%COMMANDER_PATH%\Help\TC.Commands.chm
menu5=История версий 3.00-9.51 (ru)
cmd5=%COMMANDER_PATH%\Help\Hist_rus.txt
menu6=RU.TCKB 1.7 (ru)
cmd6=%COMMANDER_PATH%\Help\RU.TCKB.chm
menu7=--
menu8=-Michel Teló - Ai Se Eu Te Pego.mp4
menu9=Официальный сайт
cmd9=https://www.ghisler.com/
menu10=Русский сайт
cmd10=http://wincmd.ru/
menu11=Русский форум
cmd11=http://forum.wincmd.ru/[/cut]
Специально туда вставил Michel Teló для теста. Файл на самом деле гораздо больше, это только его начальная часть. Код кнопки для теста:
Код: Выделить всё
TOTALCMD#BAR#DATA
60018
%COMMANDER_EXE%
Тест переключения секции
1
-1
Код: Выделить всё
RegisterCommand 60019 "ReadFileTest"
Func ReadFileTest(lParam)
Local Const GENERIC_READ = 0x80000000, FILE_SHARE_READ = 1, OPEN_EXISTING = 3, FILE_ATTRIBUTE_NORMAL = 128
Local bytes = 0
Local sIni = COMMANDER_PATH & "\Ini\Start.ini"
Local fs = FileGetSize(sIni)
Local buf = Buffer(fs)
buf.Zero()
Local hFile = DllCall("CreateFileW", "wstr", sIni, _
"dword", GENERIC_READ, _
"dword", FILE_SHARE_READ, _
"ptr", 0, _
"dword", OPEN_EXISTING, _
"dword", FILE_ATTRIBUTE_NORMAL, _
"ptr", 0, _
"handle")
If hFile > 0 Then
DllCall("ReadFile", "handle", hFile, 'ptr', buf.ptr, 'dword', fs, "dword*", @bytes, 'ptr', 0)
DllCall("CloseHandle", "handle", hFile)
Endif
Local out = buf.GetStr(0,"","")
MsgBox("bytes " & bytes & auCRLF & out)
EndFunc
Код: Выделить всё
TOTALCMD#BAR#DATA
60019
%COMMANDER_EXE%
Тест чтения
1
-1
Есть проблемы. Если читать файл через type, все работает отлично:Orion9 писал(а):Все работает
Код: Выделить всё
ProcessExecGetOutput /C:1200 out %COMSPEC% '/u /c type "%sIni%"'
......
Local bom = Chr(0xFEFF)
DllCall("WriteFile", "handle", hFile, 'wstr', bom, 'dword', 2, "dword*", @bytes, 'ptr', 0)
Код: Выделить всё
Func SwitchIniSect(sIni, sSect, sLng)
Local arrLang = List("eng", "rus")
Local i
Local Const GENERIC_READ = 0x80000000
Local Const FILE_SHARE_READ = 1
Local Const OPEN_EXISTING = 3
Local Const FILE_ATTRIBUTE_NORMAL = 128
Local bytes = 0
Local fs = FileGetSize(sIni)
Local buf = Buffer(fs)
buf.Zero()
# Local hFile = DllCall("CreateFileW", "wstr", sIni, _
# "dword", GENERIC_READ, _
# "dword", FILE_SHARE_READ, _
# "ptr", 0, _
# "dword", OPEN_EXISTING, _
# "dword", FILE_ATTRIBUTE_NORMAL, _
# "handle", 0)
# If hFile > 0 Then
# DllCall("ReadFile", "handle", hFile, _
# "ptr", buf.ptr, _
# "dword", fs, _
# "dword*", @bytes, _
# "ptr", 0)
# DllCall("CloseHandle", "handle", hFile)
# Endif
# Local out = buf.GetStr(0,"","")
# MsgBox(out)
ProcessExecGetOutput /C:1200 out %COMSPEC% '/u /c type "%sIni%"'
# Переименовываем все секции по шаблону [sect_lng]
# Rename all sections according to template [sect_lng]
For i = 0 To arrLang.Count-1
If StrPos(out, "[" & sSect & "_" & arrLang._Item[i] & "]") = 0 Then
out = StrReplace(out, "[" & sSect & "]", "[" & sSect & "_" & arrLang[i] & "]")
# MsgBox("[" & sSect & "]", "[" & sSect & "_" & arrLang[i] & "]")
Break
EndIf
Next
# Переименовываем оригинальную секции по шаблону [sect]
# Rename original section according to template [sect]
If StrPos(out, "[" & sSect & "_" & sLng & "]", 1) Then
out = StrReplace(out, "[" & sSect & "_" & sLng & "]", "[" & sSect & "]")
Endif
Local Const GENERIC_WRITE = 0x40000000
Local Const CREATE_ALWAYS = 2
bytes = 0
Local nBytes = StrLen(out) * 2
Local hFile = DllCall("CreateFileW", "wstr", sIni, _
"dword", GENERIC_WRITE, _
"dword", 0, _
"ptr", 0, _
"dword", CREATE_ALWAYS, _
"dword", FILE_ATTRIBUTE_NORMAL, _
"handle", 0)
If hFile > 0 Then
Local bom = Chr(0xFEFF)
DllCall("WriteFile", "handle", hFile, 'wstr', bom, 'dword', 2, "dword*", @bytes, 'ptr', 0)
DllCall("WriteFile", "handle", hFile, _
"wstr", out, _
"dword", nBytes, _
"dword*", @bytes, _
"ptr", 0)
DllCall("CloseHandle", "handle", hFile)
Endif
Free(arrLang)
EndFunc
Вот мусор: digit months." & auCRLF &
Кстати, я привел синтаксис функций к оригинальному. Но это никак не повлияло. Мусор все равно записывается.
Подключил все инишники, которые необходимо изменять. Мусор во всех файлах разный. А в некоторых его нет. Скорей всего проблемы с буфером.
Добавлено спустя 1 час 17 минут:
Устранил косячок:
Local fs = FileGetSize(sIni) + 1 или 2. Зависит от чего-то.
Видимо вариант с type лучше.
Добавлено спустя 1 час 17 минут:
Устранил косячок:
Local fs = FileGetSize(sIni) + 1 или 2. Зависит от чего-то.
Видимо вариант с type лучше.
Последний раз редактировалось AkulaBig Пн мар 31, 2025 11:14, всего редактировалось 1 раз.