Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   AutoIt (http://forum.oszone.net/forumdisplay.php?f=103)
-   -   [Архив - Часть 1.3] AutoIt скрипты (http://forum.oszone.net/showthread.php?t=98823)

biork 03-12-2006 05:05 520126

[Архив - Часть 1.3] AutoIt скрипты
 
Внимание!
Тема переведена в архивное состояние





(настоятельно рекомендуется к прочтению/поиску)


Руководство к действию по работе c AutoIt.

Помогите пожалуйста. Нужен маленький скриптик для решения некоторых рутинных задачь.
Вот что нужно сделать последовательно:

1) в папке DIR1 находим и удаляем файлы в названии которых присутствует text_1
2) в папке DIR2 находим xxx.sif и удаляем строки, в которых присутствует text_1
3) в папке DIR3 находим xxx.inf и добавляем в его секцию [XXX] несколько строчкек (text_2, text_3, ..., text_n)
4) в папке DIR4 находим yyy.inf ищем в его секции [YYY] text_4 и заменяем его на text_5
5) сохраняем все изменения и выводим отчёт о проделанной работе :-)

Заранее благодарен.

amel27 03-12-2006 08:21 520141

biork
п.п.1-4, точно в соответствии с формулировкой (см. примечания):
Код:

#include <File.au3>
#include <Array.au3>

$DIR1 = 'C:\DIR1'
_FilesDelete ($DIR1, '*text_1*')
$DIR2 = 'C:\DIR2'
_FileLinesDelete ($DIR2 & '\' & 'xxx.sif', 'text_1')
$DIR3 = 'C:\DIR3'
Dim $Lines3 [3] = ['text_2', 'text_3', 'text_n']
_InfSectionAddLines ($DIR3 & '\' & 'xxx.inf', 'XXX', $Lines3)
$DIR4 = 'C:\DIR4'
_InfSectionReplaceText ($DIR4 & '\' & 'yyy.inf', 'YYY', 'text_4', 'text_5')

; Удаление файлов в заданном каталоге по маске.
; Возвращает количество удаленных файлов.
Func _FilesDelete ($sPath, $sFilter)
    Local $aFiles, $i
    $aFiles = _FileListToArray ($sPath, $sFilter, 1)
    If IsArray ($aFiles) Then
        For $i=1 To $aFiles [0]
            FileDelete ($sPath & '\' & $aFiles [$i])
        Next
        Return $i-1
    Else
        Return 0
    EndIf
EndFunc

; Удаление строк файла по условию вхождения заданного текста
; Возвращает: 1 - успех, 0 - ошибка. Коды ошибок:
;  1 - ошибка чтения файла;
;  2 - ошибка сохранения файла.
Func _FileLinesDelete ($sFilePath, $sEntry)
    Local $aFileLines, $i
    If _FileReadToArray ($sFilePath, $aFileLines) Then
        For $i = $aFileLines [0] To 1 Step -1
            If StringInStr ($aFileLines [$i], $sEntry) Then _ArrayDelete ($aFileLines, $i)
        Next
        If _FileWriteFromArray ($sFilePath, $aFileLines, 1) Then
            Return 1
        Else
            SetError (2)
            Return 0
        EndIf
    Else
        SetError (1)
        Return 0
    EndIf
EndFunc

; Добавление заданного массива строк в секцию INF-файла
; Возвращает: 1 - успех, 0 - ошибка. Коды ошибок:
;  1 - переданный параметр не является массивом;
;  2 - выход за границы индекса;
;  3 - ошибка чтения файла;
;  4 - не найдена секция;
;  5 - ошибка сохранения файла.
Func _InfSectionAddLines ($sFilePath, $sSectionName, ByRef $aNewLines, $iStartIndex=0)
    Local $aFileLines, $i
    If Not IsArray ($aNewLines) Then
        SetError (1)
        Return 0
    EndIf
    If $iStartIndex >= UBound($aNewLines) Then
        SetError (2)
        Return 0
    EndIf
    If _FileReadToArray ($sFilePath, $aFileLines) Then
        Local $iStart = _ArraySearch ($aFileLines, '[' & $sSectionName & ']', 1)
        If $iStart = -1 Then
            SetError (4)
            Return 0
        EndIf
        For $i = UBound ($aNewLines)-1 To $iStartIndex Step -1
            _ArrayInsert ($aFileLines, $iStart+1, $aNewLines [$i])
        Next
        If _FileWriteFromArray ($sFilePath, $aFileLines, 1) Then
            Return 1
        Else
            SetError (5)
            Return 0
        EndIf
    Else
        SetError (3)
        Return 0
    EndIf
EndFunc

; Замена текста в пределах заданной секции INF-файла
; Возвращает: 1 - успех, 0 - ошибка. Коды ошибок:
;  1 - ошибка чтения файла;
;  2 - не найдена секция;
;  3 - ошибка сохранения файла.
Func _InfSectionReplaceText ($sFilePath, $sSectionName, $sTextFrom, $sTextTo)
    Local $aFileLines, $i
    If _FileReadToArray ($sFilePath, $aFileLines) Then
        Local $iStart = _ArraySearch ($aFileLines, '[' & $sSectionName & ']', 1)
        If $iStart = -1 Then
            SetError (2)
            Return 0
        EndIf
        Local $iFinal = _ArraySearch ($aFileLines, '[', $iStart +1)
        If $iFinal = -1 Then $iFinal = $aFileLines [0]
        If $iFinal > $iStart Then
            For $i = $iStart+1 To $iFinal
                $aFileLines [$i] = StringReplace ($aFileLines [$i], $sTextFrom, $sTextTo)
            Next
            If _FileWriteFromArray ($sFilePath, $aFileLines, 1) Then
                Return 1
            Else
                SetError (3)
                Return 0
            EndIf
        EndIf
    Else
        SetError (1)
        Return 0
    EndIf
EndFunc

З.Ы. несколько замечаний по формулировке задачи:

- INF-файл не просто текст, поэтому корректней говорить о переопределении параметров секции, а не "замене текста";
- соответственно, по п.4 возможно имелась ввиду замена строк целиком, а не вхождений текста;
- секции могут не отличаться от INI-файлов, в этом случае можно задействовать встроенные ф-ции AutoIT INI*.

Michail77 04-12-2006 08:30 520502

2Creat0R
Не совсем так,точнее совсем не так :)
Дать ссылку на картинку(системную,т.е на ту которая находится в системе по умолчанию,например в папке system32) это легко.
Мне надо чтобы картинка интегрировалась внутрь скрипта,с расположением которое ей указано и всегда была там,независимо от того есть такая картинка в системе или нет.

biork 04-12-2006 10:24 520566

Вложений: 1
amel27

Большое спасибо.

Ошибочка выпадает (см. файл)

... и что такое?
Код:

#include <File.au3>
#include <Array.au3>


amel27 04-12-2006 12:47 520632

biork
Цитата:

и что такое?
Подключение дополнительных (пользовательских) функций, файлы расширений находятся в папке \Include установочного каталога. Так как файлы не загружены, то и функция (соответственно) неопознана.

biork 05-12-2006 08:50 520969

amel27

С пользовательскими функциями разобрался. Пришлось, всего-лишь, переустановить AutoIt...
Что касаеися самого скрипта:

1) Удаление файлов в заданном каталоге по маске - работает!
1.2) Возвращает количество удаленных файлов - где и как посмотреть?

2) Удаление строк файла по условию вхождения заданного текста - работает!
2.1) Возвращает: 1 - успех, 0 - ошибка. Коды ошибок - так же не знаю где их увидеть.

3) Добавление заданного массива строк в секцию INF-файла - не работает...
3.1) Возвращает: 1 - успех, 0 - ошибка. Коды ошибок - очень хотелось бы их посмотреть...

4) Замена текста в пределах заданной секции INF-файла - не работает...
4.1) В чём ошибка - так же не видно...

Я понимаю, что всё от криворукости... но всё же? :-)

Ещё вопрос: строки text_2, text_3, text_n, а так же text_4 и text_5 содержат всякие знаки припинания (запятаи, кавычки, скобки и пр.). Может, нужно принимать какие то дополнительные меры, что бы всё это правильно было интерпритировано?

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

Yozhegg 05-12-2006 09:41 520987

А нет ли для AutoIt какой-нибудь рисовалки форм?
А то очень долго координаты с "дизайн-макета" списывать..

amel27 05-12-2006 11:22 521030

biork
Цитата:

Возвращает: 1 - успех, 0 - ошибка. Коды ошибок - очень хотелось бы их посмотреть
Пример с выводом результата на экран:
Код:

; ...
$DIR3 = 'C:\DIR3'
Dim $Lines3 [3] = ['text_2', 'text_3', 'text_n']
$ret = _InfSectionAddLines ($DIR3 & '\' & 'xxx.inf', 'XXX', $Lines3)
If $ret Then
    MsgBox (64, 'Собщение', 'Операция завершена без ошибок.')
Else
    MsgBox (16, 'Ошибка', "Код ошибки: " & @error)
EndIf
; ...

Yozhegg
Цитата:

А нет ли для AutoIt какой-нибудь рисовалки форм?
А то очень долго координаты с "дизайн-макета" списывать..
Думаю если бы был, то за него пришлось бы платить...

biork 05-12-2006 12:38 521069

amel27

Код:

1 - переданный параметр не является массивом;
2 - выход за границы индекса;
3 - ошибка чтения файла;
4 - не найдена секция;
5 - ошибка сохранения файла.

Код ошибки - 0! :-)


amel27 05-12-2006 13:11 521080

biork
Извиняюсь, очепятку исправил...

Creat0R 05-12-2006 15:04 521125

amel27
Цитата:

Можно самому написать аналогичные функции
Приогромнейшее спасибо! и представить себе не мог что на аутоите это реально :)

В связи с этим есть вопрос:

Что в функции нужно поменять, чтобы вместо открытия фалов, был выбор каталога (FileSelectFolder), и также хотелось бы чтобы была функция сохранения файлов (FileSaveDialog) - Буду очень благодарен если поможешь с этими функциями...

И ещё (не принципиально) - при выборе файлов, возможно сделать массовый выбор? т.е чтобы можно было выбирать несколько файлов.
--------------------------------
По поводу самого гуи, я немогу понять одной вещи - чтобы создать гуи, необходимо построить цикл, но на сколько известно, безпрерывный цикл “заставляет” сильно загружать ЦП... т.е если мы сделаем такой цикл:

Код:

While 1

Wend

То загрузка ЦП будет 100% - Но если поставить задержку в этом цикле (Sleep(100)), то загрузки ЦП не будет. НО, в гуи ставить задержку нельзя, это портит функциональность нажатия кнопок и т.п.... но с другой стороны, даже если поставить подобную задержку в гуи, и при этом создать горячую клавишу (HotKeySet()), то по её вызову (по вызову её функции) всё нормально срабатывает... как сделать чтобы и функциональность сохранить (не используя клавиши), и предотвратить загрузку ЦП?
Просто дело в том, что хотел сворачивать скрипт в трей, затем в трее вывести меню, но если ставлю задержку в цикле скрипта (для трея), то пункты в трее не срабатывают, а если не ставить задержку, то процессор сильно грузится (бывает до 80-90%) - Как это решить?

Creat0R 05-12-2006 15:18 521136

Michail77
Цитата:

Мне надо чтобы картинка интегрировалась внутрь скрипта,с расположением которое ей указано и всегда была там,независимо от того есть такая картинка в системе или нет.
Для этого нужно установить файл в скрипте, чтобы перед запуском он расспаковывал изображение во временную папку, и затем считывал его оттуда (это при компилляции) - а вбить намертво изображение в скрипт, не получится.

Для установки файла исользуй такую команду:

Код:

FileInstall("Полный\путь\к\изображению\для\установки\image.png", "Путь\куда\будет расспаковано\изображение\image.png", 1)
А для использования просто указывай путь который ты прописал как назначения для помещения изображения...

Код:

GUICtrlCreatePic("Путь\куда\будет расспаковано\изображение\image.png",0,0, 300,40)

VelDmi 05-12-2006 16:21 521173

Creat0R
Цитата:

По поводу самого гуи, я немогу понять одной вещи - чтобы создать гуи, необходимо построить цикл,
Гуи не грузит проц, это даже в справке написано. Разве у тебя нет русской справки?

Насчет:

While 1
Sleep(100)
Wend

(применительно к другому случаю) сам бы хотел знать, какую оптимальную задержку выставлять.

Yozhegg
Цитата:

А нет ли для AutoIt какой-нибудь рисовалки форм?
А то очень долго координаты с "дизайн-макета" списывать..
Здрасте, а как же koda designer?

Michail77 05-12-2006 19:08 521232

2 Creat0R
Спасибо,всё получилось :)))

Vadikan 05-12-2006 23:44 521336

All
В теме уже свыше 500 сообщений и поиск нужной информации в ней усложняется. Есть предложение собрать все решения (скрипты) и разместить их на Wiki по принципу "один скрипт - одна статья wiki", добавляя статьи в категорию Autoit. Речь, в принципе, идет об общих решениях, а не о скриптах для установки конкретной программы. Название статьи, очевидно, должно отражать назначение скрипта. Затем можно в шапке просто разместить ссылки на статьи Wiki.

prokazzza 06-12-2006 00:43 521356

Sanja Alone

Слушай помнишь ты давал мне вот такой скрипт, я тут не нашел куда вставить имя rar архива и что будет если убрать из скрипта строчку ProcessWaitClose('INSTALL.exe') она мне не нужна.

Код:

If $CmdLine[0]=1 Then
        $sfx=$CmdLine[1]
Else
        MsgBox(16,'Ошибка',"Недопустимое содержимое командной строки",7)
        Exit
EndIf
;пароль (берется из 3-й строки)
$password=FileReadLine(@ScriptDir&'\пароль.ini',3)
$pid=Run('"'&$sfx&'" -s')
WinWait('Ввод пароля')
ControlSetText('Ввод пароля','','Edit1',$password)
ControlClick('Ввод пароля','','Button1')
ProcessWaitClose($pid)
ProcessWaitClose('INSTALL.exe')


amel27 06-12-2006 06:05 521401

Vadikan
Цитата:

Речь, в принципе, идет об общих решениях, а не о скриптах для установки конкретной программы
Вот-вот.... С категориями путаница получается - я в смятении. Во-первых, есть две принципиально разных версии AutoIT (причем старая v.2.64 совместима по синтаксису с AutoHotKey) - в названии категории это не указано, хотя иконка недвусмысленно указывает на 3-ю версию. Во-вторых, на данный момент эта категория подчинена автоустановке, т.е. содержание ограничено скриптами, решающими те или иные Unattend-задачи хотя сфера применения AutoIT гораздо шире. В третьих, именование категорий по алфавиту может и оправдано в пределах темы (как в автоустановке), но необосновано и неудобно в общем случае - ИМХО требуется тематическое деление по категориям (тут нужно подумать).

Далее - где-то надо обсудить какие сабжи и в какой форме нужно выносить на WIKI, все-таки выдернуть скрипт из контекста обсуждения не так просто - придется приводить его к более универсальному виду, добавить комментарии, поработать с именами переменных.

З.Ы. Либо я еще не понял WIKI либо одно из двух, но без древовидной структуры от категорий мало толку.

biork 06-12-2006 08:42 521432

amel27

Я извиняюсь, уже, наверное жутко надоел, но...

...скрипт ни как не может найти секцию...

может с синтаксисом чего?

Код:

$ret = _InfSectionAddLines ($DIR1 & '\' & 'HIVESYS.INF', 'AddReg', $Lines)
Код:

$ret = _InfSectionReplaceText ($DIR1 & '\' & 'HIVESFT.INF', 'Strings', $text_4, $text_5)

amel27 06-12-2006 10:12 521474

Creat0R
Цитата:

Что в функции нужно поменять, чтобы вместо открытия фалов, был выбор каталога (FileSelectFolder), и также хотелось бы чтобы была функция сохранения файлов (FileSaveDialog) - Буду очень благодарен если поможешь с этими функциями...
Вполне реально, но быстро не получится - соответствующие API-аналоги посложней будут...

Цитата:

безпрерывный цикл “заставляет” сильно загружать ЦП
Для этого в AutoIT есть метод "OnEvent" - альтернатива методу "MessageLoop". Смотри пример в HELP к GUICtrlSetOnEvent .

biork
файл и путь в личку

prokazzza 06-12-2006 15:40 521572

amel27

Можешь доделать вот такой скрипт, я тут не нашел куда вставить имя rar архива и что будет если убрать из скрипта строчку ProcessWaitClose('INSTALL.exe') она мне не нужна.

Код:

If $CmdLine[0]=1 Then
        $sfx=$CmdLine[1]
Else
        MsgBox(16,'Ошибка',"Недопустимое содержимое командной строки",7)
        Exit
EndIf
;пароль (берется из 3-й строки)
$password=FileReadLine(@ScriptDir&'\пароль.ini',3)
$pid=Run('"'&$sfx&'" -s')
WinWait('Ввод пароля')
ControlSetText('Ввод пароля','','Edit1',$password)
ControlClick('Ввод пароля','','Button1')
ProcessWaitClose($pid)
ProcessWaitClose('INSTALL.exe')


Yozhegg 06-12-2006 17:14 521615

VelDmi
Цитата:

Yozhegg
Цитата:
А нет ли для AutoIt какой-нибудь рисовалки форм?
А то очень долго координаты с "дизайн-макета" списывать..



Здрасте, а как же koda designer?
А что это такое ( koda designer? )? к AutoIt отношение имеет?

TERMINAL 06-12-2006 20:02 521641

1.Как сделать чтобы после 1 января нельзя было запускать, допустим, некий файл Test.exe?
2.Как следать чтобы выезжал диск из CD-Roma?

Creat0R 07-12-2006 02:57 521783

VelDmi
Цитата:

Гуи не грузит проц
А я и не писал что он грузит...

Цитата:

чтобы создать гуи, необходимо построить цикл, но на сколько известно, безпрерывный цикл “заставляет” сильно загружать ЦП
Цитата:

Разве у тебя нет русской справки?
Есть :) - Но я юзаю английскую, мне так легче.


amel27
Цитата:

Смотри пример в HELP к GUICtrlSetOnEvent .
“Даже у безвыходного положения, есть выход!” ©
Ещё раз Спасибо, очень выручил :)

TERMINAL
Цитата:

Как сделать чтобы после 1 января нельзя было запускать, допустим, некий файл Test.exe?
Примерно так:

Код:

$Proga = "test.exe"
If @MDAY >= 01 and @MON >= 01 and @YEAR >= 2007 Then
  MsgBox(16, "", "Невозможно запустить программу " & $Proga & @CR & " срок истёк ;) " & @MDAY&"/"&@MON&"/"&@YEAR)
  Exit
EndIf

Правда если поменять дату в настройках времени (Свойства: Дата и Время), то можно будет запустить программу (если перевести дату назад).

Но можно например в этот день, создать файл, и упрятать его куда нибудь подальше, а ещё лучше, запись в реестре, и тогда можно будет проверять уже не дату, а существование файла\записи в реестре... примерно так:

Код:

$Proga = "test.exe"
If (@MDAY >= 01 and @MON >= 01 and @YEAR >= 2007) or FileExists("~5luyubd.dy6") or RegRead("HKLM", "...") <> "" Then
  MsgBox(0, "", "Can not start the program " & $Proga & @CR & "today it's " & @MDAY&"/"&@MON&"/"&@YEAR)
  $Path = "C:\windows\system32\sytemf8qqe\765ujyuj\ytyyhj69wc\341jj3567jg\hufghfg7r568"
  If Not FileExists($Path & "\~5luyubd.dy6") Then
      DirCreate($Path)
      FileWrite($Path & "\~5luyubd.dy6", "")
      FileSetAttrib($Path & "\~5luyubd.dy6", "RSH")
  EndIf
  Exit
EndIf

Но и это тоже не очень надёжный способ.

prokazzza
Цитата:

я тут не нашел куда вставить имя rar архива
Я так понимаю, имя архива берётся из командной строки... т.е если запустить программу с ком. строкой ровняющейся имени архиву, то переменной $sfx будет присвоенно это значение (имя архива).

Цитата:

что будет если убрать из скрипта строчку ProcessWaitClose('INSTALL.exe')
Ничего :) - Просто скрипт не будет “ждать” завершения процесса Install.exe

amel27 07-12-2006 03:10 521788

Yozhegg
Цитата:

А что это такое ( koda designer? )? к AutoIt отношение имеет?
http://www.autoitscript.com/fileman/...ormdesign.html

prokazzza
Цитата:

Можешь доделать вот такой скрипт, я тут не нашел куда вставить имя rar архива и что будет если убрать из скрипта строчку ProcessWaitClose('INSTALL.exe') она мне не нужна.
Доделать не могу, так как не знаю цели мероприятия... Имя архива передается в командной строке и заносится в переменную $sfx, причем это SFX-архив. Убрать строчку можно, но тогда скрипт завершит работу раньше установщика.

TERMINAL1. 1 января какого года? При условии, что Test.exe это AU3-скрипт:
Код:

#Include <Date.au3>

$point = StringReplace(_NowCalcDate (), '/', '')
If $point > '20060101' Then
    MsgBox (16, 'Ошибка', 'Время пробной эксплуатации истекло!')
    Exit
EndIf
; ...

2. В "маленьких хитростях": http://forum.oszone.net/post-520629-95.html

VelDmi 07-12-2006 06:05 521799

Yozhegg
Цитата:

А что это такое ( koda designer? )? к AutoIt отношение имеет?
Для AutoIt есть отличный редактор, называется SciTe. В нем если полазить по меню найдешь несколько дизайнеров форм, в том числе и koda.

Sanja Alone 07-12-2006 11:30 521897

VelDmi
Цитата:

Для этого в AutoIT есть метод "OnEvent" - альтернатива методу "MessageLoop".
Кстати, весьма полезная вещь. Именно этим методом реализован ГУИ в OEsr

prokazzza
Цитата:

что будет если убрать из скрипта строчку ProcessWaitClose('INSTALL.exe') она мне не нужна.
В той задаче, к-рую ты мне формулировал, это приведет к завершению скрипта раньше окончания процесса установки. Если тебя это устроит, то можешь убрать...

Dentel 07-12-2006 14:57 521987

Всем здравствуйте!

amel27

Спасибо за помощь, только теперь, соотвественно, вопрос, а как удаленно разблокировать рабочий стол?
(Это к вопросу о работе скрипта, если к ПК не подключен монитор)

desperate 08-12-2006 02:18 522210

Вопрос для настоящих знатаков:
создаю AutoIT скрипт, который автоматически создает VPN подключение (эта часть поддалась без проблем) и потом его настраивает(прописывает IP,DNS и прочие настройки в свойства адаптера). Вопрос: Как открыть свойства конкретного сетевого подключения(в моем случае это VPN) и как связать это с autoIT.
заранее всем спасибо.

VelDmi 08-12-2006 07:43 522238

desperate
У меня сделано через netsh interface, если нужно подробнее попозже напишу.

desperate 08-12-2006 10:03 522286

VelDmi
буду очень благодарен и думаю другим это тоже будет интересно.

desperate 08-12-2006 10:20 522297

Да забыл указать самое главное, мне надо не только вкладку Сеть -> свойства TCP/IP настроить, но и другие параметры, шифрование, WINS и проче.... вообщем пройтись по всем вклдкам свойств определенного адаптера (т.к. VPN создается для работы с провайдером спутникового интернета)

amel27 09-12-2006 07:11 522609

Creat0R
Цитата:

Что в функции нужно поменять, чтобы вместо открытия фалов, был выбор каталога (FileSelectFolder), и также хотелось бы чтобы была функция сохранения файлов (FileSaveDialog) - Буду очень благодарен если поможешь с этими функциями... И ещё (не принципиально) - при выборе файлов, возможно сделать массовый выбор? т.е чтобы можно было выбирать несколько файлов.
Все что касается FileOpenDialog и FileSaveDialog удалось осуществить... и даже чуть больше - новые UDF полностью совместимы с AutoIT-овскими, плюс новые возможности:

- новый флаг: 32 = Hide places bar (не отображать панель с иконками);
- новый параметр: Default Extension (если пользователь не вбил расширение, то автоматом добавляет указанный);
- новый параметр: HWND головного окна GUI (из-за чего собственно весь сыр-бор).
Код:

Func _FileOpenDialog ($sTitle, $sInitDir, $sFilter = 'All (*.*)', $iOpt = 0, $sDefaultFile = "", $sDefaultExt = "", $mainGUI = 0)
    Local $iFileLen = 65536 ; Max chars in returned string
    ; API flags prepare
    Local $iFlag = BitOR ( _
        BitShift (BitAND ($iOpt, 1),-12), BitShift (BitAND ($iOpt, 2),-10), BitShift (BitAND ($iOpt, 4),-7 ), _
        BitShift (BitAND ($iOpt, 8),-10), BitShift (BitAND ($iOpt, 4),-17) )
    ; Filter string to array convertion
    Local $asFLines = StringSplit ( $sFilter, '|'), $asFilter [$asFLines [0] *2+1]
    Local $i, $iStart, $iFinal, $suFilter = ''
    $asFilter [0] = $asFLines [0] *2
    For $i=1 To $asFLines [0]
        $iStart = StringInStr ($asFLines [$i], '(', 0, 1)
        $iFinal = StringInStr ($asFLines [$i], ')', 0,-1)
        $asFilter [$i*2-1] = StringStripWS (StringLeft ($asFLines [$i], $iStart-1), 3)
        $asFilter [$i*2] = StringStripWS (StringTrimRight (StringTrimLeft ($asFLines [$i], $iStart), StringLen ($asFLines [$i]) -$iFinal+1), 3)
        $suFilter = $suFilter & 'byte[' & StringLen ($asFilter [$i*2-1])+1 & '];byte[' & StringLen ($asFilter [$i*2])+1 & '];'
    Next
    ; Create API structures
    Local $uOFN = DllStructCreate ('dword;int;int;ptr;ptr;dword;dword;ptr;dword' & _
        ';ptr;int;ptr;ptr;dword;short;short;ptr;ptr;ptr;ptr;ptr;dword;dword' )
    Local $usTitle  = DllStructCreate ('byte[' & StringLen ($sTitle) +1 & ']')
    Local $usInitDir= DllStructCreate ('byte[' & StringLen ($sInitDir) +1 & ']')
    Local $usFilter = DllStructCreate ($suFilter & 'byte')
    Local $usFile  = DllStructCreate ('byte[' & $iFileLen & ']')
    Local $usExtn  = DllStructCreate ('byte[' & StringLen ($sDefaultExt) +1 & ']')
    For $i=1 To $asFilter [0]
        DllStructSetData ($usFilter, $i, $asFilter [$i])
    Next
    ; Set Data of API structures
    DllStructSetData ($usTitle, 1, $sTitle)
    DllStructSetData ($usInitDir, 1, $sInitDir)
    DllStructSetData ($usFile, 1, $sDefaultFile)
    DllStructSetData ($usExtn, 1, $sDefaultExt)
    DllStructSetData ($uOFN,  1, DllStructGetSize($uOFN))
    DllStructSetData ($uOFN,  2, $mainGUI)
    DllStructSetData ($uOFN,  4, DllStructGetPtr ($usFilter))
    DllStructSetData ($uOFN,  7, 1)
    DllStructSetData ($uOFN,  8, DllStructGetPtr ($usFile))
    DllStructSetData ($uOFN,  9, $iFileLen)
    DllStructSetData ($uOFN, 12, DllStructGetPtr ($usInitDir))
    DllStructSetData ($uOFN, 13, DllStructGetPtr ($usTitle))
    DllStructSetData ($uOFN, 14, $iFlag)
    DllStructSetData ($uOFN, 17, DllStructGetPtr ($usExtn))
    DllStructSetData ($uOFN, 23, BitShift (BitAND ($iOpt, 32), 5))
    ; Call API function
    $ret = DllCall ('comdlg32.dll', 'int', 'GetOpenFileName', _
            'ptr', DllStructGetPtr ($uOFN) )
    If $ret [0] Then
        If BitAND ($iOpt, 4) Then
            $i = 1
            While 1
                If DllStructGetData ($usFile, 1, $i) =0 Then
                    If DllStructGetData ($usFile, 1, $i+1) Then
                        DllStructSetData ($usFile, 1, 124, $i)
                    Else
                        ExitLoop
                    EndIf
                EndIf
                $i += 1
            Wend
        EndIf
        Return DllStructGetData ($usFile, 1)
    Else
        SetError (1)
        Return ""
    EndIf
EndFunc

Func _FileSaveDialog ($sTitle, $sInitDir, $sFilter = 'All (*.*)', $iOpt = 0, $sDefaultFile = "", $sDefaultExt = "", $mainGUI = 0)
    Local $iFileLen = 65536 ; Max chars in returned string
    ; API flags prepare
    Local $iFlag = BitOR (BitShift (BitAND ($iOpt, 2),-10), BitShift (BitAND ($iOpt,16), 3 ))
    ; Filter string to array convertion
    Local $asFLines = StringSplit ( $sFilter, '|'), $asFilter [$asFLines [0] *2+1]
    Local $i, $iStart, $iFinal, $suFilter = ''
    $asFilter [0] = $asFLines [0] *2
    For $i=1 To $asFLines [0]
        $iStart = StringInStr ($asFLines [$i], '(', 0, 1)
        $iFinal = StringInStr ($asFLines [$i], ')', 0,-1)
        $asFilter [$i*2-1] = StringStripWS (StringLeft ($asFLines [$i], $iStart-1), 3)
        $asFilter [$i*2] = StringStripWS (StringTrimRight (StringTrimLeft ($asFLines [$i], $iStart), StringLen ($asFLines [$i]) -$iFinal+1), 3)
        $suFilter = $suFilter & 'byte[' & StringLen ($asFilter [$i*2-1])+1 & '];byte[' & StringLen ($asFilter [$i*2])+1 & '];'
    Next
    ; Create API structures
    Local $uOFN = DllStructCreate ('dword;int;int;ptr;ptr;dword;dword;ptr;dword' & _
        ';ptr;int;ptr;ptr;dword;short;short;ptr;ptr;ptr;ptr;ptr;dword;dword' )
    Local $usTitle  = DllStructCreate ('byte[' & StringLen ($sTitle) +1 & ']')
    Local $usInitDir= DllStructCreate ('byte[' & StringLen ($sInitDir) +1 & ']')
    Local $usFilter = DllStructCreate ($suFilter & 'byte')
    Local $usFile  = DllStructCreate ('byte[' & $iFileLen & ']')
    Local $usExtn  = DllStructCreate ('byte[' & StringLen ($sDefaultExt) +1 & ']')
    For $i=1 To $asFilter [0]
        DllStructSetData ($usFilter, $i, $asFilter [$i])
    Next
    ; Set Data of API structures
    DllStructSetData ($usTitle, 1, $sTitle)
    DllStructSetData ($usInitDir, 1, $sInitDir)
    DllStructSetData ($usFile, 1, $sDefaultFile)
    DllStructSetData ($usExtn, 1, $sDefaultExt)
    DllStructSetData ($uOFN,  1, DllStructGetSize($uOFN))
    DllStructSetData ($uOFN,  2, $mainGUI)
    DllStructSetData ($uOFN,  4, DllStructGetPtr ($usFilter))
    DllStructSetData ($uOFN,  7, 1)
    DllStructSetData ($uOFN,  8, DllStructGetPtr ($usFile))
    DllStructSetData ($uOFN,  9, $iFileLen)
    DllStructSetData ($uOFN, 12, DllStructGetPtr ($usInitDir))
    DllStructSetData ($uOFN, 13, DllStructGetPtr ($usTitle))
    DllStructSetData ($uOFN, 14, $iFlag)
    DllStructSetData ($uOFN, 17, DllStructGetPtr ($usExtn))
    DllStructSetData ($uOFN, 23, BitShift (BitAND ($iOpt, 32), 5))
    ; Call API function
    $ret = DllCall ('comdlg32.dll', 'int', 'GetSaveFileName', _
            'ptr', DllStructGetPtr ($uOFN) )
    If $ret [0] Then
        Return DllStructGetData ($usFile, 1)
    Else
        SetError (1)
        Return ""
    EndIf
EndFunc

З.Ы. Из-за превышения лимита на количество символов оформление пришлось отключить

VelDmi 09-12-2006 12:20 522672

Код:

$ip = '192.168.100.' & $ComputerNumber
If @IPAddress1 <> $ip Then
        RunWait (@COMSPEC & ' /c chcp 1251 && ' & @SystemDir & '\netsh.exe interface ip dump > netsh.cfg', @ScriptDir, @SW_HIDE)
        FileWriteLine(@ScriptDir & "\error.log", StringFormat("%s:%s:%s %s-%s-%s  Старый IP %s, надо менять", @HOUR, @MIN, @SEC, @MDAY, @MON, @YEAR, @IPAddress1))
        $file = FileOpen(@ScriptDir & '\netsh.cfg', 0)

        ; Check if file opened for reading OK
        If $file = -1 Then
                FileWriteLine(@ScriptDir & "\error.log", StringFormat("%s:%s:%s %s-%s-%s  Не могу открыть файл netsh.cfg", @HOUR, @MIN, @SEC, @MDAY, @MON, @YEAR))
                Exit
        EndIf

        ; Read in lines of text until the EOF is reached
        For $i = 1 To 60
                $line = FileReadLine($file)
                If StringInStr($line, 'set address name="') = 1 Then ExitLoop
                If $i = 60 Then Shutdown (6)
                Sleep (1000)
        Next

        $line = StringTrimLeft( $line, 17 )       
        $line = StringTrimRight( $line, StringLen($line) - StringInStr($line, 'source') + 2)
       
        FileClose($file)
       
        RunWait (@SystemDir & '\netsh.exe interface ip set address name=' & $line & ' source=static addr=' & $ip & ' mask=255.255.255.0 gateway=none', @SystemDir, @SW_HIDE)
        FileWriteLine(@ScriptDir & "\error.log", StringFormat("%s:%s:%s %s-%s-%s  Сменили IP на: %s", @HOUR, @MIN, @SEC, @MDAY, @MON, @YEAR, $ip))
        $Restart = 'Yes'  ; требуется перезагрузка
EndIf


VelDmi 09-12-2006 12:44 522689

Первый запуск netsh.exe нужен для того, чтобы выяснить имя сетевого интерфейса, т.к. оно может изменяться.
Второй запуск уже устанавливает для подключения необходимый мне ИП, gateway и проч.

desperate 09-12-2006 15:36 522740

VelDmi
хороший скрипт, спасибо, но как настроить остальные параметры шифрования,Wins и прочих на других вкладках окна свойств???

amel27 09-12-2006 19:40 522817

biork
Цитата:

скрипт ни как не может найти секцию
Файл получил, все ясно - у тебя INF-файлы из локализованной Windows, а значит в Unicode-кодировке... я подправил пару функций для поддержки файлов в юникоде. Добавь в конец скрипта прилагаемый текст функций и замени по тексту FileReadToArray и FileWriteFromArray на _FileReadUnicodeToArray и _FileWriteUnicodeFromArray соответственно:
Код:

Func _FileReadUnicodeToArray ($sFilePath, ByRef $aArray)
    Local $hFile = FileOpen ($sFilePath, 0)
    If $hFile = -1 Then
        SetError (1)
        Return 0
    EndIf
    Local $uData = FileRead ($hFile, FileGetSize($sFilePath))
    Local $sData = _WCStrToString ($uData)
    If @error Then
        SetError (2)
        Return 0
    EndIf
    $aArray = StringSplit (StringStripCR ($sData), @LF)
    FileClose ($hFile)
    Return 1
EndFunc

Func _FileWriteUnicodeFromArray ($sFilePath, ByRef $a_Array, $i_Base = 0, $i_UBound = 0)
    Local $hFile
    If Not IsArray ($a_Array) Then
        SetError (2)
        Return 0
    EndIf
    Local $last = UBound ($a_Array) - 1
    If $i_UBound < 1 Or $i_UBound > $last Then $i_UBound = $last
    If $i_Base < 0 Or $i_Base > $last Then $i_Base = 0
    $hFile = FileOpen ($sFilePath, 2)
    If $hFile = -1 Then
        SetError (1)
        Return 0
    EndIf
    FileWrite ($hFile, _StringToWCStr ($a_Array [$i_Base], 1))
    For $x = $i_Base +1 To $i_UBound
        $a_Array [$x] = @CRLF & $a_Array [$x]
        FileWrite ($hFile, _StringToWCStr ($a_Array [$x]))
    Next
    FileClose($hFile)
    Return 1
EndFunc

Func _StringToWCStr (ByRef $sString, $mark = 0)
    Local $len = StringLen ($sString), $wcl= BitShift ($len, -1)
    Local $buf, $ptr
    If $len =0 Then
        If $mark Then Return Chr(0xFF) & Chr(0xFE)
        Return ''
    EndIf
    If $mark Then
        $buf = DllStructCreate ("byte[" & $wcl +2 & "]")
        DllStructSetData ($buf, 1, Chr(0xFF) & Chr(0xFE))
        $ptr = DllStructGetPtr ($buf) +2
    Else
        $buf = DllStructCreate ("byte[" & $wcl & "]")
        $ptr = DllStructGetPtr ($buf)
    EndIf
    Local $ret = DllCall ("Kernel32.dll", "int", "MultiByteToWideChar", _
        "int", 0, _
        "int", 0, _
        "str", $sString, _
        "int", $len,  _
        "ptr", $ptr,  _
        "int", $wcl )
    If $ret [0] Then
        Return DllStructGetData ($buf, 1)
    Else
        $ret = DllCall ("Kernel32.dll", "int", "GetLastError")
        SetError ($ret [0])
    EndIf
EndFunc

Func _WCStrToString (ByRef $wcString)
    Local $wcl = StringLen ($wcString), $len = BitShift ($wcl, 1)
    If $wcl =0 Then Return ''
    Local $out = DllStructCreate ("char[" & $len & "]")
    Local $buf = DllStructCreate ("byte[" & $wcl  & "]")
    Local $ptr = DllStructGetPtr ($buf)
    DllStructSetData ($buf, 1, $wcString)
    If DllStructGetData ($buf, 1, 1) =-1 AND DllStructGetData ($buf, 1, 2) =-2 Then
        $ptr +=2
        $len -=1
    EndIf
    Local $ret = DllCall ("Kernel32.dll", "int", "WideCharToMultiByte", _
        "int", 0, _
        "int", 0, _
        "ptr", $ptr, _
        "int", $len, _
        "ptr", DllStructGetPtr ($out), _
        "int", $len, _
        "int", 0, _
        "int", 0 )
      If $ret [0] Then
        Return DllStructGetData ($out, 1)
    Else
        $ret = DllCall ("Kernel32.dll", "int", "GetLastError")
        SetError ($ret [0])
    EndIf
EndFunc


VelDmi 10-12-2006 08:06 522943

desperate
Цитата:

хороший скрипт, спасибо, но как настроить остальные параметры шифрования,Wins и прочих на других вкладках окна свойств???
А ты посмотри хелп к netsh.exe, наверняка он много чего еще может.
Код:

Чтобы получить справку по команде, введите эту команду,
затем пробел и "?"

netsh>interface ip show

Применимы следующие команды:

Команды в этом контексте:
show address  - Отображение конфигурации IP-адресов.
show config    - Отображение IP-адреса и дополнительных сведений.
show dns      - Отображение адресов DNS-сервера.
show icmp      - Отображение статистики ICMP.
show interface - Отображение статистики IP-интерфейса.
show ipaddress - Отображение текущих IP-адресов.
show ipnet    - Отображение сопоставления сетей IP и физических носителей.
show ipstats  - Отображение статистики IP.
show joins    - Отображение присоединенных многоадресных групп.
show offload  - Отображает информацию разгрузки.
show tcpconn  - Отображение TCP-подключений.
show tcpstats  - Отображение статистики TCP.
show udpconn  - Отображение UDP-подключений.
show udpstats  - Отображение статистики UDP.
show wins      - Отображение адресов WINS-сервера.


desperate 10-12-2006 19:46 523093

VelDmi
без вариантов, не получилось с помощью netsh настроить все параметры.
Поэтому мой вопрос по поводу автоматического открытия Properties определенного сетевого подключения остается открытым.

amel27 11-12-2006 12:17 523386

desperate
Цитата:

не получилось с помощью netsh настроить все параметры
CMAK пробовал?

desperate 11-12-2006 14:49 523443

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

Sanja Alone 11-12-2006 17:43 523498

desperate
Цитата:

тогда создам отдельный топик
Думаю, что лучше дополнить уже существующую тему Соединение по dial-up автоматом.

biork 12-12-2006 10:59 523758

amel27
Огромное спасибище! Всё работает!

Heaven 14-12-2006 09:09 524503

Извините пожалуйста, а существует ли такая команда с помощью которой можно было бы закрыть определенное окно!

Например я сделал так что при открытии моего диска(autorun)он сначало записывает мой шрифт в директорию %windir%\Fonts и
Я сделал так
поместил explorer.exe в директорию диска и написал в cmd файле
%CDROM%\Autoplay\explorer.exe %windir%\Fonts
Это мне нужно чтобы он открывался
А как сделать так чтобы она вслед за этим закрывалась автоматически
Пожалуйста напишите мне

DenchikK 14-12-2006 18:00 524747

А можно ли средствами AutoIT (навеоняка можно, только придумать не
могу как) удалить файл с фиксированным именем во всех неопределенных
деррикториях - имена, количество, уровни которых заранее неизвестны?

Допустим имеем файл который надо удалить - 1.txt
Имеем каталог в котором его надо удалять - 2

И вот в этом то каталоге может быть любое количество каталогов,
подкаталогов, подподкаталогов - какие - не понятно, имена их - не
известно, количество - то же, уровней вложения - тем более.

Мозг опухают - в хелпе пока ничего не смог отыскать.

Creat0R 14-12-2006 20:59 524813

amel27
Цитата:

Все что касается FileOpenDialog и FileSaveDialog удалось осуществить... и даже чуть больше - новые UDF полностью совместимы с AutoIT-овскими, плюс новые возможности:
Абалдеть!!! Спасибо! осталось только для FileSelectFolder придумать функцию, и будет суперь счастье :)

Есть вопрос - а можно чтобы вместо (как опция) прикрепления гуи, можно было также прикреплять любое другое окно (по его заголовку)?

P.S
При разукрашивании скрипта, если поставить Send("{...}") то скрипт ругается на неопознанные стили, а точнее, это если только есть кривые круглые ораньжевые скобки :)

Heaven
Цитата:

существует ли такая команда с помощью которой можно было бы закрыть определенное окно!
WinClose("Заголовок окна", "Текст окна")
Цитата:

как сделать так чтобы она вслед за этим закрывалась автоматически
Ты имеешь в виду папка Fonts? - WinClose("Fonts")

DenchikK
Цитата:

А можно ли средствами AutoIT (навеоняка можно, только придумать не
могу как) удалить файл с фиксированным именем во всех неопределенных
деррикториях - имена, количество, уровни которых заранее неизвестны?
Можно (использовал функцию by amel27) :

Код:


#include <File.au3>
#include <Array.au3>

$Path = @ScriptDir & "\2"
$FileName = "1.txt"

$DirsList = _DirListToArray ($Path)
For $i = 1 to $DirsList[0]
    FileDelete($DirsList[$i] & "\" & $FileName)
Next
FileDelete($Path & "\" & $FileName)

Func _DirListToArray ($sPath)
    Local $i, $j, $rlist[1]=[0], $blist, $alist=_FileListToArray ($sPath, '*', 2)
    If IsArray ($alist) Then
        For $i=1 To $alist [0]
            _ArrayAdd ($rlist, $sPath & "\" & $alist [$i])
            $blist = _DirListToArray ($sPath & "\" & $alist [$i])
            If $blist[0]>0 Then
                For $j=1 To $blist [0]
                    _ArrayAdd ($rlist, $blist [$j])
                Next
            EndIf
        Next
    EndIf
    $rlist [0] = UBound ($rlist) - 1
    Return $rlist
EndFunc


DenchikK 16-12-2006 04:15 525316

Creat0R
Извините пожалуйста за глупый вопрос - скопировал скрипт в файл au3,
переписал в тот каталог откуда запускаю - 2 файла include. Запускаю -
а мне выдается ошибка - Error: Unknown function name. на строчке
Local $i, $j, $rlist[1]=[0], $blist, $alist=_FileListToArray ($sPath, '*', 2)

amel27 16-12-2006 11:01 525375

DenchikK
проверь наличие в заголовке скрипта строчек:
Код:

#include <File.au3>
#include <Array.au3>

Creat0R
Цитата:

Есть вопрос - а можно чтобы вместо (как опция) прикрепления гуи, можно было также прикреплять любое другое окно (по его заголовку)?
я не спец в ГУИ, но думаю в общем случае это неосуществимо
Цитата:

скрипт ругается на неопознанные стили
стиль для скобок добавил

DenchikK 16-12-2006 11:41 525389

amel27
Есть эти строчки - один в один все как указано у Creat0R

amel27 16-12-2006 12:11 525403

DenchikK
Цитата:

переписал в тот каталог откуда запускаю - 2 файла include
а разве со штатного INCLUDE эти файлы не подтягиваются?... Из справки по Include - если AutoIT установлен штатным установщиком то файлы берутся из установочного каталога\Include, в противном случае в каталоге скрипта нужно создавать папку с именем Include и туда пихать UDF-файлы или править реестр (хотя последние варианты не пробовал).

DenchikK 17-12-2006 03:44 525694

Цитата:

а разве со штатного INCLUDE эти файлы не подтягиваются?
Это я уже от безысходности. Варианты пробую. AutoIT версий 3.1.0 и 3.1.1 ставил. В
Цитата:

установочного каталога\Include
они существуют, пихал эти файлы и рядом со скриптом, и рядом со скриптом каталогом - не работает! Что такое может быть?
Добавлено:
Нашел в скрипте Sanja Alone функцию _FileListToArray и поместил
её в файл \Include\Array.au3 (ибо этой функции ни в одно файле
каталога \Include не было), вот код:
Код:

Func _FileListToArray($sPath, $sFilter = "*", $iFlag = 0)
        Local $hSearch, $sFile, $asFileList[1]
        If Not FileExists($sPath) Then
                SetError(1)
                Return ""
        EndIf
        If (StringInStr($sFilter, "\")) or (StringInStr($sFilter, "/")) or (StringInStr($sFilter, ":")) or (StringInStr($sFilter, ">")) or (StringInStr($sFilter, "<")) or (StringInStr($sFilter, "|")) or (StringStripWS($sFilter, 8) = "") Then
                SetError(2)
                Return 0
        EndIf
        If Not ($iFlag = 0 Or $iFlag = 1 Or $iFlag = 2) Then
                SetError(3)
                Return ""
        EndIf
        $asFileList[0] = 0
        $hSearch = FileFindFirstFile($sPath & "\" & $sFilter)
        If $hSearch = -1 Then
                SetError(0)
                Return 0
        EndIf
        While 1
                $sFile = FileFindNextFile($hSearch)
                If @error Then ExitLoop
                If $iFlag = 1 Then
                        If StringInStr(FileGetAttrib($sPath & "\" & $sFile), "D") <> 0 Then ContinueLoop
                EndIf
                If $iFlag = 2 Then
                        If StringInStr(FileGetAttrib($sPath & "\" & $sFile), "D") = 0 Then ContinueLoop
                EndIf
                ReDim $asFileList[UBound($asFileList) + 1]
                $asFileList[0] = $asFileList[0] + 1
                $asFileList[UBound($asFileList) - 1] = $sFile
        WEnd
        FileClose($hSearch)
        SetError(0)
        If $asFileList[0] = 0 Then Return ""
        Return $asFileList
EndFunc  ;==>_FileListToArray

теперь ошибка выдается такая:
Local $i, $j, $rlist[1]=[0], $blist, $alist=_FileListToArray ($sPath, '*', 2)
Local $i, $j, $rlist[1] ERROR
Error: No virriable given for "Dim", "Local", "Global" or "Const" statement.

mpn 17-12-2006 09:30 525725

Всем привет!
Поможите, кто может.
Задача простая. Необходимо периодически на удаленном компьютере (под Unix) выполнять ряд команд с дальнейшей обработкой выводимой в консоль информации. Хочу использовать для этого строку $t=Run("telnet","",@SW_HIDE,3) и далее при помощи StdinWrite, StdoutRead работать с открытой консолью. Но почему-то процесс telnet.exe закрывается сразу же после запуска. Где ошибка?

Creat0R 17-12-2006 10:16 525733

amel27
Цитата:

думаю в общем случае это неосуществимо
Да, я тоже так предположил сразу, но всё равно спасибо за то что есть (с гуи) - я вообще то предпологал что и это будет не реализуемо, но к огромному счастью, оказалось что это не так - надеюсь что когда нибудь и с этим делом вяснится что мы ошибаемся :).

Цитата:

стиль для скобок добавил
Thnx! ;)

mpn
Цитата:

почему-то процесс telnet.exe закрывается сразу же после запуска. Где ошибка?
Может этот процесс требует чтобы рабочий каталог был тот в котором он находится?
Попробуй перед запускам сменить рабочий каталог FileChangeDir("путь\к telnet.exe\"), или указать путь в самой сроке запуска...

Код:

$t=Run("telnet.exe","путь\к telnet.exe\",@SW_HIDE,3)
Или просто с полным путём запустить...

Код:

$t=Run("путь\к telnet.exe\telnet.exe","",@SW_HIDE,3)
DenchikK

Пиши скрипт так, и ненужно никаких Include ;) :

Код:

$Path = @ScriptDir & "\2"
$FileName = "1.txt"

$DirsList = _DirListToArray ($Path)
For $i = 1 to $DirsList[0]
    FileDelete($DirsList[$i] & "\" & $FileName)
Next
FileDelete($Path & "\" & $FileName)

Func _DirListToArray ($sPath)
    Local $i, $j, $rlist[1]=[0], $blist, $alist=_FileListToArray ($sPath, '*', 2)
    If IsArray ($alist) Then
        For $i=1 To $alist [0]
            _ArrayAdd ($rlist, $sPath & "\" & $alist [$i])
            $blist = _DirListToArray ($sPath & "\" & $alist [$i])
            If $blist[0]>0 Then
                For $j=1 To $blist [0]
                    _ArrayAdd ($rlist, $blist [$j])
                Next
            EndIf
        Next
    EndIf
    $rlist [0] = UBound ($rlist) - 1
    Return $rlist
EndFunc

Func _FileListToArray($sPath, $sFilter = "*", $iFlag = 0)
    Local $hSearch, $sFile, $asFileList[1]
    If Not FileExists($sPath) Then Return SetError(1,1,"")
    If (StringInStr($sFilter, "\")) or (StringInStr($sFilter, "/")) or (StringInStr($sFilter, ":")) or (StringInStr($sFilter, ">")) or (StringInStr($sFilter, "<")) or (StringInStr($sFilter, "|")) or (StringStripWS($sFilter, 8) = "") Then Return SetError(2,2,"")
    If Not ($iFlag = 0 Or $iFlag = 1 Or $iFlag = 2) Then Return SetError(3,3,"")
    $hSearch = FileFindFirstFile($sPath & "\" & $sFilter)
    If $hSearch = -1 Then Return SetError(4,4,"")
    While 1
        $sFile = FileFindNextFile($hSearch)
        If @error Then
            SetError(0)
            ExitLoop
        EndIf
        If $iFlag = 1 And StringInStr(FileGetAttrib($sPath & "\" & $sFile), "D") <> 0 Then ContinueLoop
        If $iFlag = 2 And StringInStr(FileGetAttrib($sPath & "\" & $sFile), "D") = 0 Then ContinueLoop
        ReDim $asFileList[UBound($asFileList) + 1]
        $asFileList[0] = $asFileList[0] + 1
        $asFileList[UBound($asFileList) - 1] = $sFile
    WEnd
    FileClose($hSearch)
    Return $asFileList
EndFunc

Func _ArrayAdd(ByRef $avArray, $sValue)
    If IsArray($avArray) Then
        ReDim $avArray[UBound($avArray) + 1]
        $avArray[UBound($avArray) - 1] = $sValue
        SetError(0)
        Return 1
    Else
        SetError(1)
        Return 0
    EndIf
EndFunc


Creat0R 17-12-2006 10:26 525734

amel27
Цитата:

стиль для скобок добавил
По прикреплённому файлу...
Цитата:

Архив повреждён или имеет неизвестный формат
По ссылке в посте...

Цитата:

Sorry, the file you requested is not available.


:(

mpn 17-12-2006 10:52 525736

Creat0R

Уже перепробовал все варианты. При этом, если если вместо telnet поставить, например, cmd - все работает.

DenchikK 17-12-2006 12:23 525755

Creat0R
Спасибо большое, но всё равно ошибка выдается:
Local $i, $j, $rlist[1]=[0], $blist, $alist=_FileListToArray ($sPath, '*', 2)
Local $i, $j, $rlist[1] ERROR
Error: No virriable given for "Dim", "Local", "Global" or "Const" statement.

Creat0R 17-12-2006 16:06 525817

mpn
Цитата:

Уже перепробовал все варианты
Используя ком. строку пробовал?
Код:

FileChangeDir("Путь к проге")
Run(@ComSpec, " /c start telnet.exe", "", @SW_HIDE)

DenchikK
Цитата:

ошибка выдается
Какая у тебя версия AutoIt?

DenchikK 17-12-2006 19:16 525877

Creat0R
Цитата:

Какая у тебя версия AutoIt?
Цитата:

AutoIT версий 3.1.0 и 3.1.1 ставил.
Добавлено:
Всё, спасибо! Заработало! Зашел на сайт - а там версия новее. Скачал - всё замечательно! Ещё раз спасибо!

mpn 18-12-2006 05:50 526024

Creat0R
Пробовал и с командной строкой. При этом первым запускается процесс cmd.exe, именно он становится доступным для ввода/вывода (последний параметр в команде run =3). Запускающийся следом telnet.exe не принимает команды, отправленные при помощи StdinWrite, даже при правильно указанном PID.
Поясню еще. Программу необходимо запускать в т.ч. и ночью на заблокированном компьютере. Поэтому использование send, отправляющей символы в активное DOS-окно, отпадает. Различные Control.. не работают с такими окнами. Пробовал вместо telnet запускать hyperterm.exe, но при его закрытии (на заблокированном ПК) Windows ругается: "...неизвестная ошибка...", и больше его запускать не хочет. Использование экзотических терминальных программ ограничивает мобильность скрипта.
Выход где-то должен быть!

DenchikK 18-12-2006 08:34 526057

Creat0R
А можно Вас ещё побеспокоить? Никак не могу изменить скрипт так, чтоб
удалялись несколько файлов, и с нескольких путей. Приходится для
каждого файла и каждого пути писать отдельный скрипт, при компиляции
каждый скрипт начинает весить 180 kb, и несколько - уже весят за 2
мегабайта!
Заранее спасибо!

Creat0R 18-12-2006 14:16 526188

mpn
А утилиту telnet пробовал ставить в тот же каталог вместе со скриптом? (или наоборот, скрипт в ту папку в которой telnet) - может что-то блокирует запуск программы? файрвол? какие то другие ограничители доступа в сеть?

DenchikK
Цитата:

изменить скрипт так, чтоб
удалялись несколько файлов, и с нескольких путей.
Для каждого файла, добавляй соответственно такой блок кода:

Код:

$Path = @ScriptDir & "\имя другого каталога"
$FileName = "имя другого файла.txt"

$DirsList = _DirListToArray ($Path)
For $i = 1 to $DirsList[0]
    FileDelete($DirsList[$i] & "\" & $FileName)
Next
FileDelete($Path & "\" & $FileName)

А ещё лучше, если действительно много таких "процедур" нужно делать, создать для этого процесса отдельно функцию:

Код:

Func _DeleteFileInFolders($FileName, $Path)
    $DirsList = _DirListToArray ($Path)
    For $i = 1 to $DirsList[0]
        FileDelete($DirsList[$i] & "\" & $FileName)
    Next
    FileDelete($Path & "\" & $FileName)
EndFunc

И тогда можно использовать её каждый раз при необходимости....


Код:

_DeleteFileInFolders("File1.txt", "C:\Dir1")

_DeleteFileInFolders("File2.txt", "C:\Dir2")

_DeleteFileInFolders("File3.txt", "C:\Dir3")

И т.д.


P.S
Функцию поместить в конец скрипта (после трёх существующих функции - _FileListToArray, _ArrayAdd и _DirListToArray).

Creat0R 19-12-2006 02:50 526467

Переделал немного функцию для удаления файлов из подкаталогов, чтобы она ещё возвращала значения...
если все файлы были найдены, то возвращается сообщение о том что всё прошло успешно, если какого-то файла не удалось удалить, то возвращается список тех файлов которых не удалось удалить :) - если каталоги небыли найдены, или сам путь не сущестсвует, то также возвращается сообщение об ошибке.

P.S.

Хотелось бы узнать, как можно построить функцию так, чтобы возвращалось значение в массиве (через _ArrayAdd полагаю), я пробовал сделать, но у меня почему то возвращается только первое значение (из $Results[1]) - если кто-то может показать как правильно строить массив на примере с этой функцией (для удаления), то буду очень признателен.

Код:

$Results = _DeleteFileInFolders($FileName, $Path)

MsgBox(64, "Results", "Results of deleting:" & @CR & $Results)

Func _DeleteFileInFolders($FileName, $Path)
    Local $ErrDelList
    If Not FileExists($Path) Then Return "The destination folder <" & $Path & "> was not found"
    $ErrDelete1 = FileDelete($Path & "\" & $FileName)
    $DirsList = _DirListToArray($Path)
    If IsArray($DirsList) Then
        If $DirsList[0] = 0 And $ErrDelete1 = 0 Then Return "There is no file <" & $FileName & "> in the destination folders, and  in there is no folders in the destination path <" & $Path & ">"
        For $i = 1 to $DirsList[0]
            $ErrDelete2 = FileDelete($DirsList[$i] & "\" & $FileName)
            If $ErrDelete2 = 0 And FileExists($DirsList[$i] & "\" & $FileName) Then
                If $ErrDelete1 = 0 And FileExists($Path & "\" & $FileName) And StringInStr($ErrDelList, $Path & "\" & $FileName) = 0 Then $ErrDelList = $ErrDelList & @CR & "Can not delete the file <" & $Path & "\" & $FileName & ">"
                $ErrDelList = $ErrDelList & @CR & "Can not delete the file <" & $DirsList[$i] & "\" & $FileName & ">"
            ElseIf $ErrDelete2 = 0 And Not FileExists($DirsList[$i] & "\" & $FileName) Then
                If $ErrDelete1 = 0 And Not FileExists($Path & "\" & $FileName) And StringInStr($ErrDelList, $Path & "\" & $FileName) = 0 Then $ErrDelList = $ErrDelList & @CR & "File <" & $Path & "\" & $FileName & "> not found"
                $ErrDelList = $ErrDelList & @CR & "File <" & $DirsList[$i] & "\" & $FileName & "> not found"
            EndIf
        Next
        If $ErrDelList <> "" Then
            Return $ErrDelList
        ElseIf $ErrDelete1 = 0 Then
            Return "There is no file <" & $FileName & "> in the destination path <" & $Path & ">"
        Else
            Return "All files in the destination folder (and in his subfolders) was secceseful deleted!"
        EndIf
    Else
        Return ""
    EndIf
EndFunc


Sla8ak 19-12-2006 16:45 526694

Доброго времени суток!

Интересует следующее - можно ли при помощи AutoIt скрипта сделать следуюющее.
Пользователь входит в систему, появляэтся переменная окружения %USERNAME%=zzz_aaa, где zzz - группа пользователя, aaa - инициалы пользователя.
Нужно получить только группу пользователя, и ввести в систему новую переменную set USERGROUP=zzz.
Вопрос каким образом можно взять из имени пользоваетля только группу.

Спасибо.
З.Ы. Имя пользователя находится в актив директори.

Creat0R 19-12-2006 17:56 526730

Sla8ak
Цитата:

каким образом можно взять из имени пользоваетля только группу
Нужно разделить значение переменной по разделителю _, и взять первое значение из массива - а прописать новую переменную, думаю можно через EnvSet()...


Код:

$SplitUserName = StringSplit(@UserName, "_")

If IsArray($SplitUserName) Then
    $UserGroup = $SplitUserName[1]
Else
    $UserGroup = @UserName
EndIf

EnvSet("USERGROUP", $UserGroup)
EnvUpdate()


sattva 20-12-2006 20:30 527223

С помощью какой команды можно переименовывать файлы!!? Например wgatray.exe в wgatray.exe.old.

Creat0R 21-12-2006 13:41 527512

sattva
Цитата:

С помощью какой команды можно переименовывать файлы!!?
Как таковой, команды для переименования нет. Но для этой цели используется команда перемещения файла (FileMove()) в том же каталоге...

Код:

FileMove("wgatray.exe", "wgatray.exe.old")

-----------------------------------------
У меня есть такой вопрос:

-Возможно ли в GUI, построить реальную ссылку, на которую можно было бы нажать, и она открывалась в браузере (желательно чтобы был выбор с каким браузером запускать)?

Sla8ak 22-12-2006 13:37 527932

Доброго времени суток.

Интересует следуюющий вопрос: каким образом при помощи AutoIt-скрипта можно перенаправить (переназначить) папку "Мои документы" в другое место, например на сетевой ресурс.

Заранее спасибо.

Djons 23-12-2006 17:38 528326

Vadikan

Как конвертировать в код AutoIt v3 вот такой CMD скрипт?
Будь добр, приведи код готового скрипта.
Код:

FOR %%I IN (C D E F G H I J K L M N O P Q R S T U V W X Y Z) DO IF EXIST %%I:\PROG.EXE SET path=%%I:\;%path%
reg add "HKLM\SYSTEM\ControlSet001\Control\Session Manager\Environment" /v Path /t REG_SZ /d %path% /f
reg add "HKCU\Environment" /v Path /t REG_SZ /d %path% /f


Creat0R 23-12-2006 22:54 528385

Sla8ak
Цитата:

каким образом при помощи AutoIt-скрипта можно перенаправить (переназначить) папку "Мои документы" в другое место
Можно через реестер...

Код:

$NewMyDocsPath = "C:\MyDocs"
RegWrite("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\DocFolderPaths", @UserName, "REG_SZ", $NewMyDocsPath)

Djons
Цитата:

Как конвертировать в код AutoIt v3 вот такой CMD скрипт?
Конвертировать, как мне самому недавно выяснилось (тут я тоже задавал подобный ворос), нет возможности, но можно написать что-то подобное...

Код:

$AllDrivesVar = DriveGetDrive("all")

For $i = 1 to $AllDrivesVar[0]
    If $AllDrivesVar[$i] <> "a:" And $AllDrivesVar[$i] <> "b:" And FileExists($AllDrivesVar[$i] & "\PROG.EXE") Then EnvSet("PATH", $AllDrivesVar[$i] & "\;" & EnvGet("PATH"))
Next

Если PROG.EXE будет существовать в нескольких дисках, то и эти диски будут добавлены в переменную PATH.

bes1de 23-12-2006 23:06 528390

есть скрипт autoit_KIS.exe .для запуска нужен еще и AutoIt3.exe ? или скрипт сам по себе?

Creat0R 24-12-2006 00:02 528416

bes1de
Цитата:

.для запуска нужен еще и AutoIt3.exe ? или скрипт сам по себе?
Закомпелированный скрипт не нуждается ни в каких компонентах со стороны AutoIT.

Djons 24-12-2006 00:13 528420

Creat0R

Спасибо, буду пробовать.

Djons 24-12-2006 08:46 528476

Creat0R

Код:

$AllDrivesVar = DriveGetDrive("all")

For $i = 1 to $AllDrivesVar[0]
    If $AllDrivesVar[$i] <> "a:" And $AllDrivesVar[$i] <> "b:" And FileExists($AllDrivesVar[$i] & "\PROGPE.WIM") Then EnvSet("PATH", $AllDrivesVar[$i] & "\;" & EnvGet("PATH"))
Next

Эта конструкция ничего не дала. В реестре запись диск не добавлен.
Подскажи как точно нужно написать скрипт.
Я то в этих скриптах ни бум-бум.

Creat0R 24-12-2006 15:13 528552

Djons
Цитата:

Эта конструкция ничего не дала
Странно, должна была прописаться переменная... вот вроде рабочий вариант:

Код:

$AllDrivesVar = DriveGetDrive("all")

For $i = 1 to $AllDrivesVar[0]
    If $AllDrivesVar[$i] <> "a:" And $AllDrivesVar[$i] <> "b:" And FileExists($AllDrivesVar[$i] & "\PROGPE.WIM") Then
        RegWrite("HKLM\SYSTEM\ControlSet001\Control\Session Manager\Environment", "Path", "REG_EXPAND_SZ", $AllDrivesVar[$i] & "\;" & EnvGet("Path"))
        RegWrite("HKCU\Environment", "Path", "REG_SZ", $AllDrivesVar[$i] & "\;" & EnvGet("Path"))
    EndIf
Next
EnvUpdate()


Последняя строка предназначена для обновления переменных сред.

S377 25-12-2006 14:12 528905

помогите, пожалуйста такая проблема автоит версия 3,2
пытаюсь эмулировать клики мыши по касперскому 5
Код:

WinWaitActive("Антивирус Касперского Personal", "Настройка")
ControlClick("Антивирус Касперского Personal", "Настройка", "Обновления")

и тишина...

Creat0R 25-12-2006 17:14 528971

S377
Используй AutoIt Window Information Tool (Aut3info.exe) чтобы определить заголовок окна, его текст, и класс кнопки ( ClassNameNN: ) на которую нужно нажать. Также учти, заголовок окна (и, наверное текст), чувствителен к регистру, попробуй ставить в начале скрипта Opt("WinTitleMatchMode", 4) .

S377 27-12-2006 09:24 529617

использую AutoIt Window Information Tool (Aut3info.exe)
но она чтото часто гонит может изза того что в виртуальном компе отлаживаю скрипты
видимо в виртуальном компе и добром ControlClick не работает?
что скажете по этому?
и еще можно сделать клик мыши (координаты мыши ОТНОСИТЕЛЬНО ОКНА) ?

Creat0R 27-12-2006 09:51 529634

S377
Цитата:

можно сделать клик мыши (координаты мыши ОТНОСИТЕЛЬНО ОКНА) ?
Для относительных координатов, поставь в Aut3info.exe опцию Options - Coord mode - Client - и тогда при наведении курсора координаты будут отображаться относительно границам активного окна.

А в начало скрипта такую строку нужно ставить:

Код:

Opt("MouseCoordMode", 0) ;или вместо 0 -> 2 - тога будет относительно клиентским участкам окна

S377 27-12-2006 11:19 529675

Благодарствую за совет!
не знал про: Opt("MouseCoordMode", 0) ;или вместо 0 -> 2
это очень удобно

DenchikK 28-12-2006 23:39 530271

Хотел спросить, можно ли такое осуществить на примере установки
соединения и настройки модема. А именно - список установленных модемов
как я поонимаю, сортируется по алфавиту. Предугадать заранее, на каком
месте он окажется, разумеется не возможно. Можно всё таки как то
установить курсор на нужный мне модем (тот, который заранее знаешь как
называется)?
Список модемов в "Телефонах и Модемах" определяется как
SysListView322, при установке соединения - SysListView321

Djons 29-12-2006 00:54 530281

Creat0R

Вот так работает:

Код:

For $i = 1 to $AllDrivesVar[0]
    If $AllDrivesVar[$i] <> "a:" And $AllDrivesVar[$i] <> "b:" And FileExists($AllDrivesVar[$i] & "\GEB.CD") Then
    RegWrite("HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Session Manager\Environment", "Path", "REG_SZ", $AllDrivesVar[$i] & "\;" & EnvGet("PATH"))
    RegWrite("HKEY_CURRENT_USER\Environment", "Path", "REG_SZ", $AllDrivesVar[$i] & "\;" & EnvGet("PATH"))
EndIf
Next


TERMINAL 29-12-2006 11:48 530399

1.У меня вопрос такой...
Можно ли в скрипте написать такую прогу которая будет определять дату записи диска (например, дата записи диска 30.12.2006 программой НЕРО) и если дата не соответствует то выполняется например перезагрузка машины а если дата соответствует, то выполняется к примеру старт файла SETUP.exe?

Creat0R 30-12-2006 04:28 530668

Кто нибудь сталкивался с _GuiCtrlStatusBarGetText? оно не работает в GUI :(

Берём тот же пример из справки:


Код:

opt("MustDeclareVars", 1)

#include <GUIConstants.au3>
#Include <GuiStatusBar.au3>

Local $gui, $StatusBar1, $msg, $lbl_Info
Local $a_PartsRightEdge[3] = [100, 350, -1]
Local $a_PartsText[3] = ["New Text", "More Text", "Even More Text"]

$gui = GUICreate("Status Bar Get Text", 500, -1, -1, -1, $WS_SIZEBOX)
$lbl_Info = GUICtrlCreateLabel("", 10, 10, 150, 50, $SS_SUNKEN)
$StatusBar1 = _GUICtrlStatusBarCreate ($gui, $a_PartsRightEdge, $a_PartsText)

GUICtrlSetData($lbl_Info, "1st Part: " & _GUICtrlStatusBarGetText ($StatusBar1, 0) & @LF & _
        "2nd Part: " & _GUICtrlStatusBarGetText ($StatusBar1, 1) & @LF & _
        "3rd Part: " & _GUICtrlStatusBarGetText ($StatusBar1, 2))

GUISetState(@SW_SHOW)


While 1
    $msg = GUIGetMsg()
    Select
        Case $msg = $GUI_EVENT_RESIZED
            _GUICtrlStatusBarResize ($StatusBar1)
        Case $msg = $GUI_EVENT_CLOSE
            ExitLoop
        Case Else
            ;;;;;
    EndSelect
   
WEnd

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

Как получить текст из статус-бара?

Diamond 30-12-2006 14:17 530741

Поздравляю Всех С Наступающим Новым Годом!
Я тут написал небольшую функцию, возможно кому ни-будь она пригодится...
Код:

; Преобразовывает десятичное число в другие системы счисления
; Использование:    encode($val,$type)
; $val - конвертируемое десятичное число
; $type - система счисления в которую требуется преобразовать число
Global Const $Heh=16
Global Const $Oct=8
Global Const $Bin=2

$num=987
msgbox(0,"",encode($num,$Heh))

Func encode($val,$type)
$string=""
While $val
        $MB=_Mod($val,$type)
        Select
                Case $MB=10
                $MB="A"
                Case $MB=11
                $MB="B"
                Case $MB=12
                $MB="C"
                Case $MB=13
                $MB="D"
                Case $MB=14
                $MB="E"
                Case $MB=15
                $MB="F"
        EndSelect
        $val=Int($val/$type)
        $string=$MB & $string
WEnd
Return $string
EndFunc

; Альтернатива функции Mod():
; $A - Делимое
; $B - Делитель
Func _Mod($A,$B)
        $Q=$A/$B
        $ret=($Q-Int($Q))*$B
        Return $ret
EndFunc


Diamond 31-12-2006 05:22 530883

Обратное преобразование в десятичное число.
Код:

; Преобразовывает числа из различных систем счисления в привычные нам десятичные
; Использование:    decode($val,$type)
; $val - конвертируемое число
; $type - система счисления из которой требуется преобразовать число
Global Const $Heh=16
Global Const $Oct=8
Global Const $Bin=2

$num="11111111"
MsgBox(0,"",decode($num,$Bin))

Func decode($val,$type)
$string=0
$step=StringLen($val)
While $step
$MB=StringLeft($val,1)
        Select
                Case $MB="A"
                $MB=10
                Case $MB="B"
                $MB=11
                Case $MB="C"
                $MB=12
                Case $MB="D"
                $MB=13
                Case $MB="E"
                $MB=14
                Case $MB="F"
                $MB=15
        EndSelect
        For $i=2 To $step
                $MB=$MB*$type
        Next
        $string=$string+$MB
        $val=StringRight($val,StringLen($val)-1)
        $step=$step-1
WEnd
Return $string
EndFunc


Creat0R 31-12-2006 07:30 530890

Всех с новым годом!

Вопрос опять по гуи (непомню задавал ли уже, по поиску вроде не нашел)...

Возможно ли внедрить ссылку в гуи? т.е чтобы был подчёркнуты текст как ссылка, и при нажатии выполнялось какое то действие (запуск браузера с ссылкой - но это я знаю как сделать).

Diamond 31-12-2006 13:18 530935

Creat0R
Можно внедрить целую HTML страницу:
Код:

#include <GUIConstants.au3>
Opt("GUIOnEventMode", 1)
$oIE = ObjCreate("Shell.Explorer.2")
GUICreate( "Внедренная HTML-страница",640,480)
$GUIActiveX=GUICtrlCreateObj( $oIE,0,0,640,480 )
GUISetOnEvent($GUI_EVENT_CLOSE,"closed")
GUISetState ()
$oIE.navigate("C:\Моя страничка.html")
While 1
Sleep(1000)
Wend
Func closed()
        Exit
EndFunc

Или сделать имитацию ссылки, вроде этой:
Код:

#include <GUIConstants.au3>
Opt("GUIOnEventMode", 1)
$title="Имитация ссылки"
$test= GUICreate($title,"320","240")
GUISetOnEvent($GUI_EVENT_CLOSE,"closed")
$label=GUICtrlCreateLabel("Ссылка",10,10,80,20)
GUICtrlSetCursor (-1,0 )
GUICtrlSetColor(-1,0x0000ff)
GUICtrlSetFont(-1,14,400,6)
GUICtrlSetOnEvent(-1,"event")
GUISetState()
While 1
        Sleep(1000)
WEnd
Func closed()
        Exit
EndFunc
Func event()
        GUICtrlSetColor($label,0xAC00A9)
        Run("explorer.exe http://forum.oszone.net/")
EndFunc


Creat0R 31-12-2006 23:16 531020

Diamond_m
Цитата:

сделать имитацию ссылки
Гинеально!!! я и не думал что это так просто! С новым Годом тебя и всех всех всех!!!

biggreeder 01-01-2007 22:38 531138

Вопрос знатокам AutoIt:
как при помощи этой программы изменить права доступа NTFS к отдельному файлу (в WinXP естесственно)?

Sanja Alone 02-01-2007 01:46 531159

biggreeder
Цитата:

изменить права доступа NTFS к отдельному файлу
%SystemRoot%\system32\cacls.exe + RunWait

biggreeder 02-01-2007 22:47 531356

Sanja Alone
А можно "по-пензенски"?
Как конкретно команду прописать, чтобы запретить запись "C:\Путь_к_файлу\Имя_файла" для групп SYSTEM и администраторы?

Sanja Alone 03-01-2007 16:30 531533

biggreeder
Цитата:

А можно "по-пензенски"?
cmd:
Код:

cacls "C:\Путь_к_файлу\Имя_файла" /E /G SYSTEM:R Администраторы:R
AutoIt:
Код:

RunWait(@comspec & ' /c cacls "C:\Путь_к_файлу\Имя_файла" /E /G SYSTEM:R Администраторы:R','',@SW_HIDE)

biggreeder 03-01-2007 22:09 531617

Sanja Alone
Спасибо, думал я не так что-то делаю. Но именно такие команды на срабатывают. В смысле права доступа остаются прежними.
И разные варианты команд пробовал и разные файлы. Ничего не помогает... :(

Creat0R 04-01-2007 03:32 531690

Как можно деактивировать гуи (GuiSetState(@SW_DISABLE)), но чтобы можно было перетаскивать окно (через заголовок)? или хотябы как деактивировать элементы гуи (кнопки, поля ввода и т.д.), но чтобы они не затемнялись, а в обычном их виде были недоступны для использования?

Diamond 04-01-2007 10:09 531718

Creat0R
Цитата:

Как можно деактивировать гуи
Тебе нужно блокировать не само GUI а скорее обработку событий...
Ведь если запретить обработку событий ВСЕХ кнопок и элементов то это и будет по сути заблокированное GUI.
В функции которая обрабатывает событие кнопки надо поставить условие:
Код:

Dim $zapret=False
; Пока функция MainEvent() работает кнопка не среагирует
Func MainEvent()
        $zapret=True
                Sleep(3000)
        $zapret=False
EndFunc
; функция кнопки:
Func PressButton()
        If $zapret=False Then
                Msgbox(0,"","Функция кнопки Выполнена")
        Endif
EndFunc

Например оставить $zapret=True пока пользователь не введёт верный пароль и т.п.

Creat0R 04-01-2007 10:39 531731

Diamond_m
Цитата:

Тебе нужно блокировать не само GUI а скорее обработку событий...
Нет, именно гуи (или кнопки - т.е элементы), мне нужно чтобы небыло возможности нажать на кнопку, ввести текст в поле ввода, или зажать чекбокс... т.е другими словами - заблокировать с точки зрения интерфейса а не функциональности... и, кстати, хотелось бы также блокировать не только гуи, но и внешние окна, т.е блокировать то можно, но нужно так, чтобы была при этом возможность перетаскивать окно, сворачивать его, или (если есть возможность) разворачивать.

И даже если и подойдёт такой ввариант, у меня слишком много чекбоксов в гуи (более 30-ти), и ставить их всех на условия не очень практичное решение... хотелось бы просто заблокировать элемент (чекбокс к примеру), и чтобы небыло возможности зажать галку, но и вид чтобы оригинальный оставался. Я думал что может есть какой то стиль который это делает, но в справке уже замучался искать :(

Спасибо за попытку помочь... но мне кажется моей задумке (как и многим другим моим задумкам :) ), в AutoIt'е просто нет решения :(

Diamond 04-01-2007 15:13 531822

Creat0R
Цитата:

чтобы небыло возможности зажать галку, но и вид чтобы оригинальный оставался.
Могу предложить такое решение.
Код:

#include <GUIConstants.au3>
Opt("GUIOnEventMode", 1)
$test= GUICreate("TestCover","400","300")
GUISetOnEvent($GUI_EVENT_CLOSE,"closed")
$cover=GUICtrlCreateLabel("",0, 0, 400,300)
GUICtrlSetState($cover,$GUI_DISABLE)
Dim $status=0
$CTRL_btn1 = GUICtrlCreateButton ("Заблокировать GUI", 180, 130, 120, 22,$BS_DEFPUSHBUTTON)
GUICtrlSetOnEvent($CTRL_btn1,"CoverGui")
$CTRL_Checkbox = GUICtrlCreateCheckbox ("Checkbox",80,5,66,15)
GUICtrlCreateGroup ("RadioGroup", 5, 5, 70, 60)
$radio0 = GUICtrlCreateRadio ("radio1", 10, 20, 50, 15)
$radio1 = GUICtrlCreateRadio ("radio2", 10, 40, 50, 15)
GUICtrlSetState ($radio0,$GUI_CHECKED)
GUICtrlCreateGroup ("",-99,-99,1,1)
$CTRL_edit = GUICtrlCreateEdit ("0", 10, 80, 34, 18,$ES_NUMBER)
GUISetState()
While 1
        Sleep(1000)
WEnd
Func closed()
        Exit(0)
EndFunc
Func CoverGui()
        If $status=1 Then
                GUICtrlSetState($cover,$GUI_DISABLE)
                $status=0
        Else
                GUICtrlSetState($cover,$GUI_ENABLE)
                $status=1
        EndIf
EndFunc


Creat0R 04-01-2007 22:01 531922

Diamond_m
Цитата:

Могу предложить такое решение
Решение отличное :yes: - но нет "защиты от дурака" :no: - нажимаем пробел (или перед этим таб), и кнопка снова нажимается... :(

Может можно как то блокировать доступ клавиатуры именно в гуи (BlockInput() не предлагать :) )?

Diamond 05-01-2007 10:12 532005

Creat0R
Сначала я решил что дело только в стиле кнопки $BS_DEFPUSHBUTTON, который я вставил умышленно для удобства тестирования. К сожалению о пробеле и TAB я не подумал. :sorry: А что если в функцию CoverGui() после условия Else добавить строчку: ControlFocus("TestCover","",$cover) а в шапке добавить: HotKeySet("{TAB}","nul") где nul() это пустая функция которая ничего ни делает (её так-же придётся дописать). Это сработает! Минус только в том что мы получаем неработающую клавишу {TAB} в системе. Ну и конечно убрать стиль: $BS_DEFPUSHBUTTON с кнопки, чтобы ее нельзя было нажать с помощью ENTER.

Diamond 05-01-2007 11:47 532030

Creat0R
Ещё проще... Ничего в шапке писать не надо, потребуется только изменить функцию.
Это хотя бы позволит отключить {TAB} только на момент блокировки GUI.
Код:

Func CoverGui()
        If $status=1 Then
                GUICtrlSetState($cover,$GUI_DISABLE)
                $status=0
                HotKeySet("{TAB}") ;снимаю блокировку {TAB}
                HotKeySet("^{TAB}")
                HotKeySet("+{TAB}")
        Else
                GUICtrlSetState($cover,$GUI_ENABLE)
                $status=1
                ControlFocus("TestCover","",$cover)
                HotKeySet("{TAB}","nul") ; блокирую возможные комбинации {TAB}
                HotKeySet("^{TAB}","nul")
                HotKeySet("+{TAB}","nul")
        EndIf
EndFunc
Func nul()
EndFunc


Creat0R 05-01-2007 13:03 532062

Diamond_m
Цитата:

Минус только в том что мы получаем неработающую клавишу {TAB} в системе
И Space (если и её таким образом "отключить")....

Ладно, ничего не поделать, придётся деактивировать "некрасиво" ;) ($GUI_DISABLE - или 128).

Есть у меня друга задумка, но она тоже не работает :( - нужно поставить прогресс бар, и потом отменить его... вот гуи, и не пойму почему не работает такая конструкция:

Код:

Opt("GuiOnEventMode", 1)
#include <GUIConstants.au3>

Global $ExitLoop
$gui = GUICreate("Abort GUI", 420, 140, -1, -1, $WS_SIZEBOX)
$Button = GUICtrlCreateButton("Start", 180, 20, 70)
GUICtrlSetOnEvent($Button, "Button")
GUISetOnEvent(-3, "ExitScript")

$Progress = GUICtrlCreateProgress(60, 60, 300, 15)

GUISetState(@SW_SHOW)

While 1
  Sleep(100)
WEnd

Func Button()
    GUICtrlSetData($Button, "Abort")
    GUICtrlSetOnEvent($Button, "SetExitLoop")
    While $ExitLoop = 0
        For $i = 10 To 100
            Sleep(10)
            GUICtrlSetData($Progress, $i)
        Next
    WEnd
    GUICtrlSetData($Button, "Start")
EndFunc

Func SetExitLoop()
    $ExitLoop = 1
EndFunc

Func ExitScript()
    Exit
EndFunc


kalikanzaros 05-01-2007 16:03 532118

есть ли у кого нибудь красивое решение установки alcohol120 а потом сразу lingvo11?
так как пока что у меня все это выглядит достаточно сложно и некрасиво... :(

запускаю autoit скрипты из wpi 5.6, который в свое очередь стартует из RunOnceEx.cmd который стартует с CD...
надеюсь про запуск строчка будет понятна :)

вот как сейчас это работает у меня: скрипт alcohol120 отрабатывает, а потом команда %reboot%, wpi перезагружает комп, я наивный думал что потом продолжится установка alcohol120, и только затем стартанет lingvo11, но нет, wpi запускается раньше и не дает закончить установку....
конечно можно сделать в 3 строки, что-то типа:
alcoho120.exe (без добавления в автозагрузку скрипта после перезагрузки)
%reboot%
alchol120.exe (скрипт закончит установку)

и потом начнется установка lingvo11, скрипт lingvo11 первым делом запустит установленный alcohol и даст ему секунд 5-10 для создания виртуального CD, после чего alcohol будет закрыт, а установка lingvo11 продолжена...

но мне кажется есть решение проще и красивее, нет ни у кого идей?

Diamond 05-01-2007 17:24 532147

Creat0R
Ты наверное заметил что во время работы цикла также недоступна обработка системного события (т.е. Выход из GUI). Я думаю, единственный путь привязать функцию к основному циклу. Может кто-то считает по другому? :)
Код:

Opt("GuiOnEventMode", 1)
#include <GUIConstants.au3>
Global $StartProgress=0, $i=0
$gui = GUICreate("Abort GUI", 420, 140, -1, -1, $WS_SIZEBOX)
$Button = GUICtrlCreateButton("Start", 180, 20, 70)
GUICtrlSetOnEvent($Button, "SetExitLoop")
GUISetOnEvent(-3, "ExitScript")
$Progress = GUICtrlCreateProgress(60, 60, 300, 15)
GUISetState(@SW_SHOW)

While 1
  Sleep(10)
If $StartProgress = 1 Then
        Button()
EndIf
WEnd

Func Button()
$i=$i+1
If $i=101 Then
        $i=0
EndIf
GUICtrlSetData($Progress, $i)
EndFunc

Func SetExitLoop()
If $StartProgress=1 Then
        $StartProgress = 0
    GUICtrlSetData($Button, "Start")
Else
        $StartProgress = 1
        GUICtrlSetData($Button, "Abort")
EndIf
EndFunc

Func ExitScript()
    Exit
EndFunc


Creat0R 06-01-2007 00:06 532286

Diamond_m
Цитата:

привязать функцию к основному циклу.
Это в каком то роде решает проблему, спасибо!

НО!, ах это "но"...

Проблема в том, что основной цикл не удобно использовать, у меня на кнопку старта, повешаны многие операции (функции, и статус бар ещё). Т.е запускается скрипт, нажимаем кнопку Старт, пускается по событию функция кнопки, в этой функции существует цикл, т.е в самом конце цикла происходит выход с него ExitLoop (обязательно), и мне нужно сделать так, чтобы в процессе выполнения всего этого цикла (показа статус бара, прогресс бара, выполнения разных функции и т.п), можно было нажать на кнопку "Аборт", и тогда должен происходить выход из цикла (не закрывая программу) - а точнее, должно выводиться сообщение с вопросом, мол хочет ли юзерь прервать операцию, и если ответить положительно, то выходим из цикла, если отрецательно, ничего не делаем, продолжаем с того же места на котором была нажата кнопка "Аборт" (тот же "Старт" переименованный)...

Нужно каким то образом, заставить вызвать событие (функцию) из самого цикла, преостановив этот самый цикл...

В приведённом тобой примере, функция которая вызывается по нажатию кнопки, как бы вызывается без прерывно, т.e постоянно начинается с начала, а мне нужно чтобы начало функции не происходило, при нажатии на "Аборт" просто приостанавливалось её (функции) выполнение.

Кстати, вот если не убирать иконку в трее, и оставить её функциональность по умолчанию, то при нажатии на неё появяется меню, там можно выбрать пункт Script Paused, и скрипт полностью преостанавливается - вот может можно как то точно также имитировать подобную паузу (вызвать функцию во время паузы)?

P.S
Надеюсь не запутался в объяснениях, просто уже голова пухнет от того что не могу никак сообразить, как решить эту, кажется простую задачку.
:wacko:

Creat0R 06-01-2007 01:59 532316

ВО! такой вариант работает по нажатию на горячую клавишу (Ctrl S), почему же событие не срабатывает при нажатии на кнопку? :idontnow:


Код:

Opt("GuiOnEventMode", 1)
#include <GUIConstants.au3>
HotKeySet("^s", "SetExitLoop")

Global $ExitLoop, $Mark = 10
$gui = GUICreate("Abort GUI", 420, 140, -1, -1, $WS_SIZEBOX)
$Button = GUICtrlCreateButton("Start", 180, 20, 70)
GUICtrlSetOnEvent($Button, "Button")
GUISetOnEvent(-3, "ExitScript")

$Progress = GUICtrlCreateProgress(60, 60, 300, 15)
GUISetState(@SW_SHOW)

While 1
  Sleep(100)
WEnd

Func Button()
    GUICtrlSetData($Button, "Abort")
    While $ExitLoop = 0
        For $i = $Mark To 100
            If $i = 100 Then $i = 0
            GUICtrlSetData($Progress, $i)
            If $ExitLoop = 1 Then
                $Mark = $i
                ExitLoop
            EndIf
            Sleep(10)
        Next
    WEnd
    GUICtrlSetData($Button, "Start")
    $ExitLoop = 0
EndFunc

Func SetExitLoop()
    $ExitLoop = 1
EndFunc

Func ExitScript()
    Exit
EndFunc


Diamond 06-01-2007 04:21 532337

Creat0R
Цитата:

Нужно каким то образом, заставить вызвать событие (функцию) из самого цикла
Чтобы реализовать это, придётся отказаться от Opt("GuiOnEventMode", 1), тогда опрос событий GUIGetMsg() можно будет проводить непосредственно в твоём цикле. Другого выхода не вижу. :idontnow: Возможно это не удобно с точки зрения программиста но с точки зрения функциональности скрипта - вполне приемлемо.

RemoteAdmin 06-01-2007 13:16 532466

Всем привет! Помогите новичку.
Вообщем возникла такая проблема. Мне нужно заменить один текст внутри exe файла, на свой.

Ну например, текст: This program cannot be run in DOS mode
Заменить на текст: <----------------AutoIT RuleZ---------------->

Я пытался использовать вот эту функцию:
Код:

Func ReplaceText($FileNameT, $OldText, $NewText)
        $hFile = FileOpen($FileNameT, 0)
        $aArray = StringSplit(FileRead($hFile, FileGetSize($FileNameT)), @LF)
        If Not @error Then
                FileClose($hFile)
                $hFilew = FileOpen($FileNameT, 2)
                For $iaar = 1 To $aArray[0] - 1
                        $ReplStrT = StringReplace($aArray[$iaar], $OldText, $NewText)
                        FileWrite($hFilew, $ReplStrT & @LF)
                Next
                FileClose($hFilew)
        EndIf
EndFunc

Текст заменяется, но из конца файла отрезается маленький кусок, т.е. как я понимаю, он после разбиения файла на подстроки, не может его обратно собрать.

Я также пытался, передавать ему не простые строки текста, но и в HEX, Binary формате (BinaryString), всё равно не может ничё сделать.
На офф, форумах AutoIT нашёл функции BinaryWrite/BinaryRead, но так и не смог в них разобратся.

Не могли бы вы помочь мне, в реализации моей затеи, желательно с примерами. Спасибо.

Creat0R 06-01-2007 16:46 532556

Diamond_m
Цитата:

Чтобы реализовать это, придётся отказаться от Opt("GuiOnEventMode", 1), тогда опрос событий GUIGetMsg() можно будет проводить непосредственно в твоём цикле.
В принципе это даже очень подходит, просто отменяем проверку событии (Opt("GuiOnEventMode", 0)) перед началом цикла, а в начало цикла ставим $Msg = GuiGetMsg() - ну и потом всё что нужно обрабатываем на основе $Msg = $ID ... а в конце цикла просто включаем обратно обработку событии - вобщем, вроде проблема решена :) - спасибо.

Diamond 06-01-2007 19:55 532647

Creat0R
Цитата:

а в конце цикла просто включаем обратно обработку событии
Отлично придумал!!! :victory: Это позволит не переписывать большую часть скрипта заново, а также добавит ему гибкости.

Creat0R 07-01-2007 23:32 533177

RemoteAdmin
Цитата:

из конца файла отрезается маленький кусок
Это можно поправить убрав - 1 от общего числа массива (For $iaar = 1 To $aArray[0]), но тогда в конец файла всегда будет дописываться новая строка...

Могу предложить такой вариант на функцию замены текста в файле:

Код:

Func ReplaceText($FileName, $OldText, $NewText)
    If $OldText <> "" Then
        $hFile = FileOpen($FileName, 0)
        $VarToWrite = FileRead($hFile, FileGetSize($FileName))
        $ReplStr = StringReplace($VarToWrite, $OldText, $NewText)
        FileClose($hFile)
        $hFilew = FileOpen($FileName, 2)
        FileWrite($hFilew, $ReplStr)
        FileClose($hFilew)
    EndIf
 EndFunc

Diamond_m
Цитата:

Отлично придумал!!!
Это благодаря твоим наводкам ;) - спасибо ещё раз!

Creat0R 09-01-2007 06:05 533616

Написал две примитивные функции - Одна предназначена для не совсем точного подсчёта скорости закачки (по InetGet), а друга на основе этой скорости закачки высчитывает сколько времени осталось до окончания (в секундах)...
НО! я полагаю что есть более точное решение этой задумке, ведь по идее, должны учитываться не просто полученные данные в интервале одной секунды, а ещё и скорость модема, скорость отдачи на сервере и т.п... вот как бы всё это расчитать, и построить точную функцию для подсчёта скорости закачки и оставшееся время до окончания? :idontnow:

Вот эти две функции и пример их применения:

Код:

;Заносим в переменную $URL ссылку на закачку.
$URL = "http://www.autoitscript.com/cgi-bin/getfile.pl?autoit3/autoit-v3.2.2.0-setup.exe"

;Берём из ссылки только имя файла.
$FileName = StringRegExpReplace($URL, "^.*/", "")

;Ставим ссылку на закачку в фоновом режиме.
InetGet($URL, "C:\" & $FileName, 1, 1)

;Получаем общий размер файла по ссылке (в байтах).
$InetGetSize = InetGetSize($URL)

;Пока файл закачивается, проверяем размер, оставшееся время, и выводим в трее результаты.
While @InetGetActive
    $BytesCheckBefore = @InetGetBytesRead
    Sleep(1000)
    $BytesCheckAfter = @InetGetBytesRead
    $SpeedByBytes = _InetGetSpeed($BytesCheckAfter, $BytesCheckBefore)
    TrayTip("Download", "Approximately Remained Time (seconds): " & Round(_InetGetRemained(@InetGetBytesRead, $InetGetSize, $SpeedByBytes)), 0, 1)
WEnd

;Функция возвращает скорость скачивания на основе полученных данных (до, и после секунды) - возвращаются байты в секунду (b/s).
Func _InetGetSpeed($BytesCheckAfter, $BytesCheckBefore)
    $RetSpeedByBytes = $BytesCheckAfter - $BytesCheckBefore
    If $RetSpeedByBytes < 0 Then Return 0
    Return $RetSpeedByBytes
EndFunc

;Функция возвращает оставшееся время в секундах (за счёт вычесления из общего размера файла и деления на скорость скачивания).
Func _InetGetRemained($Bytes, $TotalBytesSize, $SpeedByBytes)
    $RemainedBytes = $TotalBytesSize - $Bytes
    If $RemainedBytes <= 0 Then Return 0
    Return $RemainedBytes / $SpeedByBytes
EndFunc


P.S.
Если файл около 2-ух 3-ёх MB, то функции подсчитывают довольно точно, но если речь идёт уже о 5-ти и более MB, то счётчик начинает показыать результаты в хаотичном порядке.

timon_90 09-01-2007 12:53 533750

Привет народ... Я в этом деле новичок, но мне нужно сделать автоматизацию не из самых простых (как для меня) :) Вообщем помогите плиз чем сможете... Что собственно нужно:
Есть кейген...
1) Нужно его запустить (сделал)
2) Нажать на кнопку Generate (не получилось, но это впринципе не обязательно)
3) Скопировать текст(ключ), который он выдал (тоже непонятно)
4) Затем создать новую запись в реестре по заданному мной пути (ну в данном случае это HKEY_LOCAL_MACHINE\SOFTWARE\Electronic Arts\EA Games\Battlefield 2\ergc)
5) Создать там параметр со стандартным именем (строковый, REG_SZ)
6) Изменить его значение на такое - x9392тотсерийникбезчёрточек
вот собственно и конец... Если никто не сможет помочь по каким либо причинам то расскажите хотя бы как делать вышеперечисленные операции :) Заранее спасибо !!!

Sanja Alone 09-01-2007 15:29 533809

timon_90
Для начала, прочти FAQ

2). Пункт 7 раздела Вввод данных / работа с элементами управления FAQ - ф-ция ControlClick();
3). Ф-ция ControlGetText();
4,5,6). Пункт 2 раздела Импорт данных из reg-файла в реестр FAQ - ф-ция RegWrite(). Заменить черточки пустотой - StringReplace("серийник с черточками","-","").

P.S. Во многих моих скриптах выполняются подобные действия - используй их в кач-ве примера (посмотри скрипт для Alcohol, FR7, SoundForge 6 и др.)

timon_90 09-01-2007 15:43 533817

Сенк большой!) Если будет чёто не понятно то напишу)

Diamond 09-01-2007 17:26 533858

Для тех кто хочет использовать трекерную музыку в проектах AutoIt.
Трекерная музыка фактически не загружает CPU и из-за её малых размеров, пользуется популярностью программистов при написании кейгенов, кряков, трайнеров, а также инсталяторов.
Для проигрывания трекерных модулей в AutoIt я использую библиотеку BASSMOD.dll.
BASSMOD.dll (не путать с bass.dll) можно скачать c оф. сайта http://www.un4seen.com весит 33,5 КБ
Много трекерной музыки можно найти на сайте http://www.keygenmusic.net а также на http://www.websound.ru

Размещаем в папку \AutoIt3\Include\ скрипт(bassmod.au3) следующего содержания:
Код:

#include-once
; Поддерживает: .mod .xm .it .s3m .mtm
; P.S. Глобальные константы добавлены исключительно для удобства...
;---------------------------------
; Music flags:
Global Const $BASS_MUSIC_RAMP = 1 ; normal ramping
Global Const $BASS_MUSIC_RAMPS = 2 ; sensitive ramping
Global Const $BASS_MUSIC_LOOP = 4 ; loop music
Global Const $BASS_MUSIC_FT2MOD = 16 ; play .MOD as FastTracker 2 does
Global Const $BASS_MUSIC_PT1MOD = 32 ; play .MOD as ProTracker 1 does
;Global Const $BASS_MUSIC_POSRESET = 256 ; stop all notes when moving position
Global Const $BASS_MUSIC_SURROUND = 512 ;surround sound
Global Const $BASS_MUSIC_SURROUND2 = 1024 ;surround sound (mode 2)
Global Const $BASS_MUSIC_STOPBACK = 2048 ;stop the music on a backwards jump effect
;Global Const $BASS_MUSIC_CALCLEN        = 8192 ;calculate playback length
Global Const $BASS_MUSIC_NONINTER = 16384 ; non-interpolated mixing
;---------------------------------
Func BassMod($dllPath,$sPath,$flag)
        If $dllPath="" Or $dllPath="-1" Then
                $dllPath="BASSMOD.dll"
        EndIf
        If Not FileExists($dllPath) Then
                If Not SysFileExist($dllPath) Then
                        MsgBox(16,"Error","Не найден BASSMOD.dll")
                        Exit
                EndIf
        EndIf
        Global $music_handle = -1
        Global $BassModDll = DllOpen($dllPath)
        $init = DllCall($BassModDll, "int", "BASSMOD_Init", "int", -1, _  ;device
                                                        "int", 44100, _  ;freq Hz
                                                        "int", 0)      ;flag
        $fName = DllStructCreate("char[255]")
        DllStructSetData($fName, 1, $sPath)
        $load = DllCall($BassModDll, "int", "BASSMOD_MusicLoad", "int", False, _  ;loading from memory
                                                        "ptr", DllStructGetPtr($fName), _ ;file
                                                        "int", 0, _  ;offset
                                                        "int", 0, _  ;length
                                                        "int", $flag) ;flag
        $music_handle = $load[0]
        $fName = 0
        DllCall($BassModDll, "int:cdecl", "BASSMOD_MusicPlay", "int", $music_handle)
EndFunc
Func BassModClose()
        If IsDeclared("BassModDll") Then
                DllCall($BassModDll, "int:cdecl", "BASSMOD_Free", "int", $music_handle) ;clear resource
                DllClose($BassModDll)
        EndIf
EndFunc
; Проверка наличия указанного файла в путях переменной %Path%
Func SysFileExist($sFile)
        $old=@WorkingDir
        $array = StringSplit(EnvGet("PATH"),";")
        For $i=1 To $array[0]
                FileChangeDir($array[$i])
                $get=FileExists($sFile)
                If $get=1 Then ExitLoop
        Next
        FileChangeDir($old)
        Return $get
EndFunc

Синтаксис:
BassMod($dllPath,$sPath,$flag)
$dllPath - Путь к BASSMOD.dll (Если в качестве пути указать (-1 или "") функция поищет BASSMOD.dll в текущем директории а также в путях определённых для системной переменной %path% )
$sPath - Путь к трекерному модулю
$flag - Метод обработки (см. предыдущий код: Music flags)
BassModClose() - закрывает BASSMOD.dll и выгружает музыку из памяти (Эту функцию следует вызывать при выходе из GUI)
Пример использования:
Код:

#include <GUIConstants.au3>
#include <bassmod.au3>
Opt("GUIOnEventMode", 1)
$title="BASSMOD_TEST"
$test=GUICreate($title,320,240)
GUISetOnEvent($GUI_EVENT_CLOSE,"ExitGui")
GUISetState()

BassMod(-1,"Music.xm",512+4)

While 1
Sleep(1000)
WEnd

Func ExitGui()
        BassModClose()
        Exit(0)
EndFunc


Creat0R 10-01-2007 00:54 534023

Diamond_m
Спасибо! давно искал подобное решение - оно позволяет проигрывать мелодию в фоновом режиме, и многое другое...

Примечание и вопрос:

Примечание - Если путь к BASSMOD.dll не указать полный (просто "BASSMOD.dll"), то мелодия не играет. Это можно исправить изменив немного первое условие функции BassMod, и добавив после него такую строку:

Код:

If StringRegExpReplace($dllPath, "^.*\\", "") = $dllPath Then $dllPath = @ScriptDir & "\" & $dllPath
Т.е первые две строки будут выглядеть так:

Код:

If $dllPath = "" Or $dllPath = -1 Then $dllPath = @ScriptDir & "\BASSMOD.dll"
If StringRegExpReplace($dllPath, "^.*\\", "") = $dllPath Then $dllPath = @ScriptDir & "\" & $dllPath

Вопрос:
-Я в системной папке нашёл файл BassMod.dll, возможно ли как то использовать его?

Diamond 10-01-2007 07:53 534089

Creat0R
Цитата:

Если путь к BASSMOD.dll не указать полный (просто "BASSMOD.dll"), то мелодия не играет.
Странно... У меня почему-то играет... Использую "AutoIt v 3.2.0.1" Может произошла ошибка инициализации самой библиотеки? Даже не знаю что и подумать.
Цитата:

Я в системной папке нашёл файл BassMod.dll, возможно ли как то использовать его?
...если при вызове функции вместо пути к BASSMOD.dll указать -1 или "" AutoIt в первую очередь поищет библиотеку в директории скрипта и не найдя его там, продолжит поиск в путях переменной %path% (обычно это WINDOWS и WINDOWS\system32) т.е. попытается инициализировать найденную тобой библиотеку. Это не желательно поскольку "неизвестный" BassMod.dll вполне может оказаться устаревшим или что нибудь ещё...
Я считаю что лучше указывать полный путь, чтобы уж знать наверняка, что играет правильный BASSMOD.dll.
P.S.
Скорее всего какая нибудь программа временно извлекла BASSMOD.dll для одноразового проигрывания музыки, а в последствии не стала его удалять. Лично я считаю такое поведение некорректным для программы, поскольку это засоряет системную папку.

Вот ещё вариант для скомпилированного скрипта с применением FileInstall() (по крайней мере как это вижу я)
Все ресурсные файлы извлекаются в @TempDir только после запуска окна справки, а после его закрытия сразу удаляются.
Код:

#include <GUIConstants.au3>
#include <bassmod.au3>
Opt("GUIOnEventMode", 1)
$title="BASSMOD_TEST"
$test=GUICreate($title,320,240)
GUISetOnEvent($GUI_EVENT_CLOSE,"ExitGui")
$CTRL_help = GUICtrlCreateButton ("", 260, 20, 30, 30,$BS_ICON)
GUICtrlSetImage($CTRL_help,"shell32.dll",23,1)
GUICtrlSetOnEvent($CTRL_help,"help")
Global $HelpStart=0
Global $lib=@TempDir & "\BASSMOD.dll"
Global $sound=@TempDir & "\moon trip.xm"
GUISetState()

While 1
        Sleep(100)
WEnd

Func ExitGui()
BassModClose()
FileDelete($lib)
If @GUI_WINHANDLE = $help Then
        GUIDelete()
        $HelpStart=0
Else
        Exit(0)
EndIf
EndFunc

Func help()
Local $size = WinGetPos("")
If $HelpStart=0 Then
        Local $HelpInfo="На этом месте могла бы быть ваша реклама..." & @CRLF & _
        "Но её здесь точно не будет!"
        Global $help=GUICreate("О программе...",240,180,$size[0]+40,$size[1]+40,-1,$WS_EX_TOOLWINDOW,$test)
        $label_help=GUICtrlCreateLabel($HelpInfo,0,0,240,180)
        GUICtrlSetBkColor(-1,0x000000)
        GUICtrlSetColor(-1,0x000000)
        GUISetOnEvent($GUI_EVENT_CLOSE,"ExitGui")
        GUISetState()
        $HelpStart=1 ;защита от повторного запуска help'а
        $color=0
        Sleep(120)
        Do
                Sleep(40)
                $color=$color+5
                $H=StringRight(Hex($color),2)
                GUICtrlSetColor ($label_help,"0x" & $H & $H & $H)
        Until $color=255
FileInstall("BASSMOD.dll",$lib,1)
FileInstall("moon trip.xm",$sound,1)
BASSMOD($lib,$sound,1024+4)
; Т.к. музыка загружена в память, файл модуля можно сразу же удалить
FileDelete($sound)
EndIf
EndFunc


nadge 10-01-2007 13:51 534290

AutoIt, "защита от пользователя", как?
 
Добрый день.


Проблема такая. Некоторые пользователи любят во время установки программ крутить и тыкать во все стороны мышью :) У меня довольно много программ настраиваются при помощи скриптов автоит. Пользователи от этого офигевают - мышка сама ездит :)

Вобщем нужно на время установки запретить использование мыши и клавиатуры. Кто-нибудь делал так? Как это можно реализовать?

godoo 10-01-2007 15:24 534307

nadge все вопросы по AutoIt задавайте пожалуйста в соответствующей теме http://forum.oszone.net/thread-60616.html
Если почитать эту тему, то ответ на Ваш вопрос уже давно есть:
Код:

;блокируем мышь и клаву
If @OSType="WIN32_NT" Then BlockInput ( 1 )

включить
Код:

BlockInput ( 0 )

nadge 10-01-2007 17:19 534344

Цитата:

nadge все вопросы по AutoIt задавайте пожалуйста в соответствующей теме http://forum.oszone.net/thread-60616.html
Сорри, тему заметил только после создания своей.


Спасибо за ответ.

Creat0R 14-01-2007 14:57 535824

Хотел было спросить, как переделать функцию для поиска в файле, чтобы искать можно было исключительно слово целиком (Match whole word only), но сначала решил немного поковыряться в ней (функция от Sanja Alone), и на моё же удивление, у меня получилось это осуществить... :yes:
Не знаю пока корректный ли мой способ, но вроде работает:


Код:

Func _FindTextInFile($iFile, $Text, $MtchWholeWrdFlag = 0, $CaseSense = 0)
    If Not FileExists($iFile) Then Return -1
    Dim $ret[2]
    Local $File = FileOpen($iFile, 0)
    $a = StringSplit(FileRead($File, FileGetSize($iFile)), @LF)
    FileClose($File)

    If StringIsASCII($Text) Then
        For $i = 1 To UBound($a, 1) - 1
            If StringInStr($a[$i], $Text, $CaseSense) Then
                $ret[0] = $i
                $ret[1] = $a[$i]
                If $MtchWholeWrdFlag = 1 Then
                    $StrPos = StringInStr($ret[1], $Text)
                    If StringStripWS(StringMid($ret[1], $StrPos - 1, 1), 2) <> "" Or StringStripWS(StringMid($ret[1], $StrPos + StringLen($Text), 1), 2) <> "" Then $ret = 0
                EndIf
                Return $ret
            EndIf
        Next
    Else
        For $i = 1 To UBound($a, 1) - 1
            If StringInStr(StringLower($a[$i]), StringLower($Text)) Then
                $ret[0] = $i
                $ret[1] = $a[$i]
                If $MtchWholeWrdFlag = 1 Then
                    $StrPos = StringInStr(StringLower($ret[1]), StringLower($Text))
                    If StringStripWS(StringMid($ret[1], $StrPos - 1, 1), 2) <> "" Or StringStripWS(StringMid($ret[1], $StrPos + StringLen($Text), 1), 2) <> "" Then $ret = 0
                EndIf
                Return $ret
            EndIf
        Next
    EndIf
EndFunc

Если у 3-го параметра указать 1, то поиск будет осуществляться с учётом слова целиком, если опустить этот параметр (или указать 0), то поиск будет обычный :) .

Немного переделал функцию, тепрь если искать кириллицу, то чувствительность к целому слову учитывается... но вот если проверять учитывая регистр, то для кириллицы не действует... также добавил в функцию 4-ты параметр, который определяет чувствительность к регистру букв. А также в начале функции поставил проверку на существование файла, если не существует, то возвращается -1.

P.S.
Если кто-то знает более правильный способ, или более эффективный, то буду рад узнать его ;)

Creat0R 15-01-2007 18:55 536455

Никак не могу разобраться со всем что связанно с кодировками...

При проверке на существование файла, если проверяемы путь в кодировке UTF-8, и содержит кериллицу (русские буквы), то файл не найден, перекодировать то можно, но что делать если заранее не известно какая будет кодировка (путь к примеру берётся из файла конфигурации)?

Можно ли написать функцию, которая будет определять кодировку строки?

А таже проблема с отображением кодировки в гуи, если язык в системе не русский и не английски, то ни одна функция не помагает нормально отобразить кириллицу. Есть функция _Utf8ToAnsi() (от amel27), но она тут не помагает (помагает если системный язык русский), есть также функция StringToUTF(), и она тоже не помагает... как сделать уникальное отображение кириллицы в гуи, чтобы на любом языке (установленном в системе), нормально всё отображалось?

i_mihal 15-01-2007 20:41 536502

написал скрипт на AutoIt для установки Office 2000.
серийник там в SETUP.INI никак не задается,
поэтому серийный номер ввожу вот так:

Send('FXWX9QCJ4FGHCRYH9Y8FXQP6G')

но срабатывает это далеко не всегда. есть две проблемы:

1) если в винде язык по умолчанию - русский, то вместо латинских букв
скрипт вводит в поле ввода русские: АЧЦЧ9 ЙСО4А итд, то есть
те русские буквы, которые написаны на соответствующих клавишах.
2) иногда что-то протормаживает и вообще вводится мешанина из букв,
как будто из этой строки Send('FXWX9QCJ4FGHCRYH9Y8FXQP6G')
выбрали 7-9 букв, через каждые 2-3 буквы и разбавили их буквой "Ж",
которой вообще по-идее там быть не может, ведь она соответствует
на клавиатуре знаку ";"

сейчас попробую сделать ввод серийника с помощью ControlSetText,
но мне непонятно, почему так странно работает 'Send' если язык в винде
по умолчанию задан русский? может подскажет кто-нибудь?

спасибо.

p.s. с помощью 'ControlSetText' вроде получилось, хотя учитывая непонятность
работы 'Send' нет уверенности, что все и всегда будет работать корректно :(
пока работает...

Diamond 15-01-2007 21:34 536524

i_mihal
Да, есть такая проблема... Я её решаю с помощью вставки из буфера обмена:
ClipPut("FXWX9QCJ4FGHCRYH9Y8FXQP6G")
Send("^м")
Цитата:

почему так странно работает 'Send'
Вопрос, скорее всего, относиться к разработчикам AutoIt. :not-me:

Всем:
Оказывается, с помощью WinApi можно проделывать интересные манипуляции с окнами...
Анимация окон GUI, с помощью WinApi
Использование:
DllCall("User32.dll","long","AnimateWindow","hwnd",Идентификатор окна,"long",Продолжительность в миллисекундах,"long",Эффект)
Эффекты:
Эффекты имеет смысл задавать в качестве констант: Const $AW_ACTIVATE = 0x20000
AW_ACTIVATE = 0x20000 (Активирует окно, конфликтует с AW_HIDE)
AW_BLEND = 0x80000 (Постепенное исчезновение-появление)
AW_CENTER = 0x10 (Разворачивает окно из центра)
AW_HOR_POSITIVE = 0x1 (Слева направо)
AW_HOR_NEGATIVE = 0x2 (Справа налево)
AW_SLIDE = 0x40000 (Прокрутка)
AW_VER_POSITIVE = 0x4 (Сверху в низ)
AW_VER_NEGATIVE = 0x8 (Снизу в верх)
AW_HIDE = 0x10000 (Скрывает окно)
Эффекты по умолчанию ориентированны на появление окна, для скрытия окна используйте их совместно с AW_HIDE.
Можно получить интересные результаты комбинируя эффекты между собой. Например: 0x4 + 0x1 (анимация по диагонали)

Рабочий пример:
Код:

#include <Guiconstants.au3>
Opt("GUIOnEventMode",1)
$test=GUICreate("WinApi_test",400,300)
GUISetOnEvent($GUI_EVENT_CLOSE,"ExitGui")
DllCall("User32.dll","long","AnimateWindow","hwnd",$test,"long",700,"long",0x8+0x40000)
GUISetState()

While 1
Sleep(100)
WEnd

Func ExitGui()
DllCall("User32.dll","long","AnimateWindow","hwnd",$test,"long",500,"long",0x10+0x10000)
Exit
EndFunc


Creat0R 15-01-2007 23:04 536560

i_mihal
ControlCommand вроде будет всегда срабатывать:

Код:

ControlCommand("Title", "", "Edit1", "EditPaste", "FXWX9QCJ4FGHCRYH9Y8FXQP6G")
На счёт Send(), решение для смены раскладки клавиатуры вроде есть в Faq'е (см. “Как с помощью AutoIt сменить раскладку клавиатуры”)

Diamond

Красиво! :UP: но рамка всего гуи как бы нарисованна, т.е углы не округлённые как должны быть в XP, даже немного затемнённые, это можно поправить?

P.S
Цитата:

Я её решаю с помощью вставки из буфера обмена
Это тоже не всегда надёжно, буфер обмена может неправильно отдавать текст (при вставке в него текста Аутоитом).

Creat0R 15-01-2007 23:42 536583

:yahoo:
Оказывается, возможно привязать функцию _MsgBox() (от amel27), и любое окно гуи к другому окну (не обязательно к гуи)....

На мысль меня навёл пример из Faq'а о переключении раскладки клавиатуры (а именно, пременная $hWnd):


Код:

Opt("WinTitleMatchMode", 4)
Run("notepad.exe")
$NotPadTitle = "classname=Notepad"

WinWait($NotPadTitle, "", 5)
$hWnd = WinGetHandle($NotPadTitle)

WinSetState($NotPadTitle, "", @SW_DISABLE)
GuiCreate("Attach To Window Gui", 300, 400, -1, -1, -1, -1, $hWnd)
GuiSetState()

$Msg = 0
While $Msg <> -3
    $Msg = GuiGetMsg()
    Sleep(10)
Wend

WinSetState($NotPadTitle, "", @SW_ENABLE)


Diamond 16-01-2007 01:25 536607

Creat0R
Цитата:

углы не округлённые как должны быть в XP
Я тоже заметил этот дефект. Честно говоря, не знаю... :sorry: Других вариантов или комбинаций для "AnimateWindow" пока найти не удалось. Разве что попытаться использовать другие стили окна... Во ещё что: Если окно имеет тень, анимация может происходить "рывками".
Цитата:

буфер обмена может неправильно отдавать текст (при вставке в него текста Аутоитом)
Наверное имелось ввиду: "буфер обмена может неправильно принимать текст"? Насколько неправильно? При копировании-вставке обычного текста, у меня ошибок пока не случалось...
Спасибо, приму к сведению. :)

Creat0R 16-01-2007 03:24 536613

Diamond
Цитата:

Разве что попытаться использовать другие стили окна
Перепробовал почти все, один только справляется почти нормально с задачей - $WS_EX_TOOLWINDOW - но как известно, это не совсем обычное окно ;) - но всё же неплохая вещь которую ты привёл в студию :) спасибо!

Цитата:

Наверное имелось ввиду: "буфер обмена может неправильно принимать текст"?
Скорее так.

Цитата:

Насколько неправильно?
Ну возьмём к примеру кириллицу из ком. строки...

Вставляем так:

ClipPut($CmdLine[1])

Если Ком. строка содержит кириллицу, то когда пытаемся куда то вставить текст из буфера обмена, то уже вставляется в неверном формате... кстати я даже не знаю как перекодировать его, кто знает плиз подскажите, давно хотел узнать :blush2:

Т.е вот к примеру если такой скрипт закомпилировать:

Код:

ClipPut($CmdLine[1])
MsgBox(0, "", ClipGet())

А потом запустить его к примеру из батника так:

Код:

Start ClipTest.exe тест
То в сообщении мы увидим ЄхёЄ (крякозябры) :)

Creat0R 16-01-2007 03:55 536614

Ещё один способ получить список существующих дисков на компьютере:

Код:

$Drives = ""
For $iDrv = 65 to 90
    If DriveGetType(Chr($iDrv) & ":\") <> "" Then $Drives = $Drives & @CR & Chr($iDrv) & ":\"
Next
MsgBox(262144+64, "Existing Drives List", $Drives)


VelDmi 16-01-2007 18:22 536920

Creat0R
Цитата:

Оказывается, возможно привязать функцию _MsgBox() (от amel27)
Где эту функцию взять?

Diamond 16-01-2007 21:37 537009

Creat0R
Цитата:

всё же неплохая вещь которую ты привёл в студию
Спасибо. Мне тоже очень понравилось. :)
Цитата:

Если Ком. строка содержит кириллицу
Через командную строку проблема решается так:
graftabl 1251 | echo %username%>MyName.txt
Хотя конкретно для твоего случая это не сработает. При создании пакетного Файла возьми за привычку конвертировать текст в Dos(oem), например c помощью текстового редактора: BRED - хороший заменитель блокнота, или любой другой доступный редактор который умеет работать с кодировками, в самом крайнем случае открываешь пакетный файл в WordPad ( > Сохранить как > Текстовой документ MS-DOS), а затем меняешь расширение на *.bat

Diamond 16-01-2007 23:09 537060

Creat0R
Цитата:

Ещё один способ получить список существующих дисков на компьютере:
Интересный вариант! Как-то мне пришлось использовать перебор A-Z, но только в пакетном файле, поскольку другой альтернативы в батниках просто нет.
Вот ещё один способ, сделано через VBScript
Код:

#CS
тип ресурса:
0 - неизвестное устройство
1 - устройство со сменным носителем.
2 - жёсткий диск.
3 - сетевой диск.
4 - CD-ROM.
5 - RAM-диск.
#CE

Dim $fso, $d, $dc, $s
$fso = ObjCreate("Scripting.FileSystemObject")
$dc = $fso.Drives
        For $d In $dc
                If $d.DriveType = "2" Then
                        $s = $s & $d.DriveLetter & ": "
                EndIf
        Next
MsgBox(0,"",$s)




Creat0R 17-01-2007 04:05 537124

VelDmi
Цитата:

Где эту функцию взять?
Вот:

Код:

Func _MsgBox ($mainGUI, $MsgBoxTitle, $MsgBoxText, $MsgBoxType)
    $ret = DllCall ("user32.dll", "int", "MessageBox", _
            "hwnd", $mainGUI, _
            "str", $MsgBoxText , _
            "str", $MsgBoxTitle, _
            "int", $MsgBoxType)
    Return $ret [0]
EndFunc


В первом параметре задаётся идентификатор гуи (как выяснилось можно и от WinGetHandle), во втором заголовок, в следующем текст, и в последнем тип (иконка, кол-во кнопок и т.д.)...

Вот рабочий пример с этой функцией:

Код:

Opt("WinTitleMatchMode", 4)
Run("notepad.exe")
$NotPadTitle = "classname=Notepad"

WinWait($NotPadTitle, "", 5)
$hWnd = WinGetHandle($NotPadTitle)

_MsgBox($hWnd, "Attached MsgBox to Notepad", "I am attached to notepad, you must close me before continue work in notepad ;-)", 64)

Func _MsgBox($mainGUI, $MsgBoxTitle, $MsgBoxText, $MsgBoxType)
    $ret = DllCall ("user32.dll", "int", "MessageBox", _
            "hwnd", $mainGUI, _
            "str", $MsgBoxText , _
            "str", $MsgBoxTitle, _
            "int", $MsgBoxType)
    Return $ret [0]
EndFunc


P.S.
Я когда то писал:

Цитата:

надеюсь что когда нибудь и с этим делом вяснится что мы ошибаемся
Так и выяснилось! :)


Diamond
Цитата:

При создании пакетного Файла
Я только для примера привёл запуск с пакетника :) - это происходит не только с батника, например, в браузере Opera, если выделить текст, и запустить программу (из меню) с параметром %T (идентификатор выделенного текста в браузере), то содержащий кириллицу текст будет также криво помещён в буфер обмена. Очень хотелось бы это решить, но я уже многое перепробовал, и решения так и не нашл :(

VelDmi 17-01-2007 08:33 537178

Creat0R
Цитата:

то содержащий кириллицу текст будет также криво помещён в буфер обмена.
Если не ошибаюсь, предварительно нужно переключить раскладку клавиатуры на русский, тогда будет помещен нормально.

mpn 17-01-2007 09:49 537202

Народ!
Я повторяюсь, но очень интересует ответ на простой вопрос: у кого нибудь выполняется корректно строка $f=Run("telnet","",@SW_MAXIMIZE,3) ? У меня, если ее выполнить без последнего параметра, открывается окно telnet, в противном случае процесс закрывается через 0,5 сек после запуска. AutoIt v.3.2.0.1.

Dicken 17-01-2007 10:40 537225

Цитата:

процесс закрывается через 0,5 сек после запуска. AutoIt v.3.2.0.1.
нет неработает!

Diamond 17-01-2007 12:51 537292

Creat0R
Пробовал через WinApi - kernel32.dll там вроде бы должна быть нужная функция... В общем совсем запутался - ничего не получается. :(
Если у тебя проблемы только с Dos-кодировкой, то можно побить кракозябру её же собственным оружием.
Код:

$ret="ЄхёЄ"
MsgBox(0,"",OEM_Decode($ret))

Func OEM_Decode($string)
$foo = Run(@ComSpec & " /c @echo " & $ret,"", @SW_HIDE, 2)
$line = StdoutRead($foo)
Return $line
EndFunc


Creat0R 17-01-2007 14:22 537352

Diamond
Цитата:

можно побить кракозябру её же собственным оружием
Оригинально! :victory: Спасибо.

По поводу режима чтения из консоли (StdoutRead), если я ставлю 2 как последний параметр у команды Run, влияет ли это на то как будут выполняться команды ком. строки? т.е на что вообще это повлияет (кроме как на возможность чтения изх консоли)?

Diamond 17-01-2007 20:48 537508

Creat0R
Эта Функция в её текущем виде не предназначена для чтения из консоли, она задумана мной только для преобразования искажённого текста.
Т.е я заставляю консоль испортить кирилический текст, как она это делает обычно, но только в нужную нам сторону. Но если ты хочешь использовать StdoutRead() непосредственно по назначению, т.е для чтения стандартного потока из консоли...

Пример кода был взят из справки AutoIt v 3.2.2.0
$STDOUT_CHILD = 2 Необходима для получения StdoutRead() в первом цикле
$STDERR_CHILD = 4 Необходима для получения StderrRead() во втором цикле
Имена констант очевидно говорят об их предназначении (см. справка: StdoutRead и StderrRead)
Константы влияют только на возможность чтения потока из консоли. При этом возможность сохраняется до тех пор, пока ты делаешь запросы StdoutRead(), вплоть до закрытия самой консоли.
Код:

; Demonstrates StdoutRead()
#include <Constants.au3>

$foo = Run(@ComSpec & " /c dir foo.bar", @SystemDir, @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)

While 1
    $line = StdoutRead($foo)
    If @error Then ExitLoop
    MsgBox(0, "STDOUT read:", $line)
Wend

While 1
    $line = StderrRead($foo)
    If @error Then ExitLoop
    ;MsgBox(0, "STDERR read:", $line)
Wend

MsgBox(0, "Debug", "Exiting...")

Понятно, что разработчики при написании справки не подумали о нас русских и, как следствие, о существовании кирилицы.
Исправляем этот недостаток заменой первой строки в коде:
Код:

$foo = Run(@ComSpec & " /c graftabl 1251 | dir foo.bar", @SystemDir, @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)

Creat0R 17-01-2007 21:12 537518

Как можно изменить функцию _ChooseColor(), чтобы можно было прикрепить окно выбора цвета к гуи?
Я пробовал в DllCall добавить параметр ..."hwnd", $Gui...., но функция ругается на сбой в скрипте и не хочет запускаться :( - возможно ли это как то решить?

Diamond
Цитата:

Эта Функция в её текущем виде не предназначена для чтения из консоли
Я вкурсе :) , пример из справки я уже иследовал, поэтому и появился вопрос, влияет ли запуск ком. строки в режиме чтения, на выполнение команд ком. строки (без всякой связи с кириллицей, это был не касающийся этого вопрос).

Diamond 18-01-2007 01:14 537623

Три способа определить - является ли файл папкой:
P.S.
Возможно, для многих это не новость, и всё-таки...
Код:

;~ Путём получения атрибутов
;~ Возвращает положительное число если папка существует, иначе 0
Func FolderExist($name)
$Folder=StringInStr(FileGetAttrib($name),"D")
Return $Folder
EndFunc

;~ С помощью файла "nul" присутствующего в каждой папке
;~ Возвращает 1 если папка существует, иначе 0
Func _FolderExist($name)
$Folder=FileExists($name & "\nul")
Return $Folder
EndFunc

;~ С помощью функции VBScript
;~ Возвращает 1 если папка существует, иначе 0
Func VbFolderExist($name)
$fso=ObjCreate("scripting.filesystemobject")
$Folder=Abs($fso.FolderExists($name))
Return $Folder
EndFunc

Creat0R
Цитата:

без всякой связи с кириллицей, это был не касающийся этого вопрос
В любом случае, исправленный код может оказаться полезным и для других участников форума. :)
А всё-таки кракозябры были не связаны с буфером обмена или AutoIt. :no: А то, я уж чуть было не усомнился в эфективности способа который я предложил i_mihal :tomato:

papik_bat 18-01-2007 10:47 537779

Здрасьте всем.
Вот история моей болезни:
я написал батник для автоматической рассылки писем, когда он срабатывает, то появляеться окно аутглюк с предуприждением, что программа пытаеться сама отправить письмо и т.д.. На нужную кнопку в этом окне я нажимал скриптом Autoit.

[code]Opt("TrayIconHide", 1)
WinWaitActive("Microsoft Office Outlook")
Sleep(6000)
ControlClick("Microsoft Office Outlook", "", "Button4")
Send("{ENTER}")

Все работало нормально, но последнее время если компьютер заблакированн мой "нажиматель" не срабатывает, так как окно аутглюка стало теперь не активным. на писал такой скрипт:

Код:

Opt("TrayIconHide", 1)
If WinWait("Microsoft Office Outlook") then
WinActivate("Microsoft Office Outlook","")
WinWaitActive("Microsoft Office Outlook")
Sleep(6000)
ControlClick("Microsoft Office Outlook", "", "Button4")
Send("{ENTER}")
EndIf

Но проблема не решилась, если комп заблокированн окно не активируеться и кнопка не нажимаеться.

Кто виноват? Что делать?

Creat0R 18-01-2007 13:08 537841

Diamond
Цитата:

Три способа определить - является ли файл папкой
Ещё один (который я до сих пор юзал):
;Возвращает -1 если файл вовсе не существует, 1 если папка, и 0 если файл....

Код:

Func _IsDir($FileName)
    If FileExists($FileName) Then
        $FCheck = FileOpen($FileName, 0)
        If $FCheck = -1 Then
            Return 1
        Else
            FileClose($FCheck)
            Return 0
        EndIf
    Else
        Return -1
    EndIf
EndFunc

Но видимо начну юзать один из твоих примеров, тот что проверяет атрибуты, пожалуй это надёжнее.


Цитата:

В любом случае, исправленный код может оказаться полезным и для других участников форума.
Безусловно :)


papik_bat
Цитата:

если компьютер заблакированн
Что значит заблокирован? AutoIt'ом?

У тебя второй пример весь держится на условии что “скрипт будет дожидаться” окна, попробуй опустить условие и ограничить дожидание:

Код:

#NoTrayIcon ;Так надёжнее ;)

WinWait("Microsoft Office Outlook", "", 10)
;Иногда один раз не срабатывает (глюк аутоита), пробуем два раза подряд...
WinActivate("Microsoft Office Outlook")
WinActivate("Microsoft Office Outlook")
WinWaitActive("Microsoft Office Outlook", "", 10)
Sleep(6000)
ControlClick("Microsoft Office Outlook", "", "Button4")
Send("{ENTER}")


papik_bat 18-01-2007 13:43 537868

Продолжаем беседу...

CreatoR

Компьютер заблокирован = Ctrl+Alt+Delete -> Блокировка, либо когда блокировка включаеться автоматически.
ПопробЫвал предложенный код, не идет...

После разблокировки окно аутлука свернуто.

papik_bat 18-01-2007 15:58 537941

Вот нашел описание команды которая могла бы, я думаю, решить мою беду WinRestore, но у себя в Autoit 3, ее не нахожу. Как быть?

Creat0R 18-01-2007 19:25 538026

papik_bat
Цитата:

у себя в Autoit 3, ее не нахожу.
Она относится к аутоиту Version 2.63, Version 2.64

Теперь (в 3.2.2) нужно так:

Код:

WinSetState("Microsoft Office Outlook", "", @SW_RESTORE)

papik_bat 19-01-2007 10:54 538300

CreatOR
Цитата:


WinSetState("Microsoft Office Outlook", "", @SW_RESTORE)
все ровно не работает.
Попробую пойти другим путем, не дам компютеру блокироваться написал скрипт Autoit "мышка летит на юг" :-)!
Через каждые 10 минут мышка двигаеться в южном направлении. Просто отключить блокировку нельзя.

Diamond 19-01-2007 17:55 538568

Creat0R
Цитата:

тот что проверяет атрибуты, пожалуй это надёжнее
На самом деле все три способа надёжны!
Тот что на основе VBScript запрашивает напрямую ($fso.FolderExists() куда уж надёжней...). Там я сделал только одну поправочку. Дело в том что в VBScript, значение False понятно 0, а вот значение True = -1, поэтому я добавил Abs() для совместимости с AutoIt.

Файл "nul" - неотъемлемый элемент папки и он никуда не денется, так что тоже можно пользоваться смело. :)

Respect 19-01-2007 20:15 538617


Уважаемые, подскажите пожалуйста, может кто знает как реализовать на AutoIt v 3 следующее:
(Что-то сам никак не могу придумать)

1. Как вызвать меню программы, которое вызывается только по клику правой кнопкой мыши на иконку программы в трее ?
(Другого интерфейса программа не имеет...) Или как кликнуть нужную иконку программы в трее ?

Creat0R 20-01-2007 03:08 538808

Respect
Цитата:

как кликнуть нужную иконку программы в трее ?
Мне кажется только по координатам - используй Au3Info.exe, и нажми на нужную иконку, затем посмотри координаты которые выдаст этот инструмент (под надписью >>>Mouse Details <<< - X: и Y: ), далее используй их примерно так:

Код:

#NoTrayIcon
$X = 930
$Y = 717
MouseClick("right", $X, $Y, 1, 0)

Первая строка обязательна, иначе появится икона самого скрипта, и тогда координаты уже будут не актуальны (не верны).

Diamond
Цитата:

все три способа надёжны!
А если работа Vbscript нарушена в системе? ;) (у меня такое бывало)
А по поводу файла Nul, видимо он гинерируется (по крайней мере имитируется его присутствие) если существует файл с таким же имененм без расширения...
Т.е к примеру, создаём файл Test в папке C:\ (без расширения), и проверяем является ли он папкой:

Код:

$TestName = "C:\test"

MsgBox(0, "", _FolderExist($TestName))

Func _FolderExist($name)
    $Folder = FileExists($name & "\nul")
    Return $Folder
EndFunc

Получаем 1 (хотя это не папка) :) .

Creat0R 20-01-2007 03:31 538814

У меня есть такой вопрос:
-Возможно ли проверить функцию BlockInput()? т.е есть способ узнать, включена ли (или отключена) такая блокировка (от самого скрипта)?
Мне нужно включить BlockInput(1), и в течении того времни пока всё заблокированно, проверять были ли нажаты клавиши Alt Ctrl Del (что и вызывает отключение блокировки) - или хотябы как проверить нажатие этих клавишь, _IsPressed не помагает, не получается проверить нажатие сразу трёх клавишь :(


P.S.

И ещё такой между прочный вопрос - почему в справке нет (у меня) описании команд StringRegExp, StringRegExpReplace? где можно почитать описания, и желательно примеры этих функции? может мне справка попалась бракованная? (она шла вместе с дистрибютивом AutoIt'а).

Respect 20-01-2007 18:20 539043

Цитата:

To CreatOR
К сожалению это единственный вариант, который приходит в голову и мне. Но это уже не имеет никакого отношения к автоматизации, ибо необходим универсальный способ, а на разных машинах с различным набором установленных программ
координаты конкретной иконки будут однозначно отличаться !?...

Вопрос № 2.

Как определить какая в текущий момент раскладка клавиатуры RU or EN и как переключать раскладку клавиатуры, не применяя эмуляцию нажатия клавиш ?

Наверняка не сложный вопрос, просто нет времени разбираться. Извините, если эти вопросы уже обсуждались в форуме. Хочется услышать именно ответы.
Спасибо.

Diamond 21-01-2007 09:53 539222

Creat0R
Цитата:

почему в справке нет (у меня) описании команд StringRegExp, StringRegExpReplace?
В папке AutoIt я нашёл 4 файла справки, все шли вместе с дистрибутивом v3.2.2.0
AutoIt, AutoIt3, AutoIt3Help, и наконец UDFs3 - (User Defined Function). В первых трёх, есть описания этих команд (у меня). :)
Цитата:

А если работа Vbscript нарушена в системе?
В этом плане, полностью с тобой согласен, любой объектно-ориентированный язык зависим от библиотек, их регистрации в системе и т.д. Но думаю что написанный на AutoIt'е код, так же не защищён от различных неприятностей, особенно если использует внешние dll библиотеки. Например применение функций ObjCreate() и DllCall() я считаю одинаково ненадёжным. С другой стороны... если отказаться от их использования, AutoIt будет выглядеть пустым. ;)
Цитата:

по поводу файла Nul
Беру свои слова обратно. :pray: Странно... проверяется путь "C:\test\nul" и возвращается True, хотя на самом деле такого пути не существует - мистика. Раньше я использовал этот способ в батниках - как единственно возможный. А проверить его подобным образом, просто в голову не приходило... :idontnow:

Creat0R 22-01-2007 05:06 539521

Respect
Цитата:

необходим универсальный способ
Такого как мне кажется, в Аутоите, для этой задачи, увы нет :( .

Цитата:

как переключать раскладку клавиатуры, не применяя эмуляцию нажатия клавиш ?
См. в шапке AutoIt скрипты - введение и FAQ (Как с помощью AutoIt сменить раскладку клавиатуры).

Diamond
Цитата:

все шли вместе с дистрибутивом v3.2.2.0
Интересно, я установил эту версию, но поверх старой (v3.2.0.1), неужели файлы справки в таком случае не заменяются? :dont-know (в самих справках написанно v3.2.0.1).

Цитата:

проверяется путь "C:\test\nul" и возвращается True, хотя на самом деле такого пути не существует - мистика.
Ну это не совсем мистика, просто видимо Nul, интерпритируется как “Ничто” (также как и при проверке If FileExists("") ... ), т.е учитывается только путь до Nul (в случае с FileExists("") это путь к скрипту, ну или к рабочему каталогу).

Цитата:

использовал этот способ в батниках - как единственно возможный
Кстати, в батниках тоже можно “атрибутным” (почти) способом проверять :) :

Код:

@echo off
Set Dir=c:\D
If Not Exist "%Dir%" Goto ExitMsg
Attrib %Dir% > "%temp%\~6456t56iu.tmp"
For /f "delims= " %%a in (%temp%\~6456t56iu.tmp) Do If /i %%a==%Dir% (
Echo "%Dir%" Is a folder!  ---^> Exit in 7 seconds ;-^) ) Else (
Echo "%Dir%" Is Not a folder!  ---^> Exit in 7 seconds ;-^) )
Goto Exit
:ExitMsg
Echo This file ^<%Dir%^> was not found  ---^> Exit in 7 seconds ;-)

:Exit
ping -n 7 localhost > nul
Del "%temp%\~6456t56iu.tmp"

Хотя тоже не очень наджёжно, но это уже другая тема, сорри за офтоп :blush2:



Diamond 22-01-2007 12:16 539690

Вопрос:
Можно ли как-то заставить GUI, игнорировать (установленый в системе по умолчанию) стиль Windows XP. Т.е чтобы окно отбражалось в классическом виде (как в 98-м) не зависимо от системного стиля?
Второй вопрос:
Сущесвует ли какой нибудь простой способ претаскивания окна стиля $WS_POPUP или это возможно только за счёт слежения за позицией курсора? Кому нибудь уже удавалось двигать такое окно с помощью мыши? Я написал код, окно двигается без проблем, только вот я не уверен что это правильный способ.
Код:

#include <Guiconstants.au3>
Opt("GUIOnEventMode",1)
$test=GUICreate("",400,300,-1,-1,$WS_POPUP+$WS_BORDER)
GUISetBkColor(0xBEFFBE)
GUISetOnEvent($GUI_EVENT_CLOSE,"ExitGui")
$Closed_button=GUICtrlCreateButton("X",377,3,18,18)
GUICtrlSetFont(-1,10,700,0,"Tahoma")
GUICtrlSetOnEvent(-1,"ExitGui")
$Mim_button=GUICtrlCreateButton("-",337,3,18,18)
GUICtrlSetFont(-1,13,700,0,"Arial Black")
GUICtrlSetOnEvent(-1,"MimimizeGui")
$Max_button=GUICtrlCreateButton(CHR(152),357,3,18,18)
GUICtrlSetFont(-1,9,700,0,"Tahoma")
GUICtrlSetState(-1,$GUI_DISABLE)
$panel=GUICtrlCreateGraphic(0,0,400,24)
GUICtrlSetOnEvent(-1,"MoveWindow")
$text=GUICtrlCreateLabel("TEST",5,5,100,18)
GUICtrlSetFont(-1,12,700,0,"Courier New")
GUICtrlSetColor(-1,0xBEFFBE)
GUICtrlSetBkColor(-1,0x000000)
DllCall("User32.dll","long","AnimateWindow","hwnd",$test,"long",300,"long",0x10)
GUICtrlSetBkColor($panel,0x000000)
GUISetState()

While 1
        Sleep(100)
WEnd

Func MoveWindow()
Opt("GUIOnEventMode",0)
        $Win=WinGetPos("")
        $Mouse=MouseGetPos()
        $fix_X=$Mouse[0]-$Win[0]
        $fix_Y=$Mouse[1]-$Win[1]
        Do
                $msg=GUIGetMsg()
                $move=MouseGetPos()
                $x=$move[0]-$fix_X
                $y=$move[1]-$fix_Y
                WinMove("","",$x,$y)
        Until $msg=$GUI_EVENT_PRIMARYUP
Opt("GUIOnEventMode",1)
EndFunc

Func MimimizeGui()
GUISetState(@SW_MINIMIZE)
EndFunc

Func ExitGui()
DllCall("User32.dll","long","AnimateWindow","hwnd",$test,"long",300,"long",0x10+0x10000)
Exit
EndFunc

Creat0R
Цитата:

Кстати, в батниках тоже можно “атрибутным” (почти) способом проверять
Да ты оказывается Спец в батниках. :UP: Т.е. папка определяется по отсутствию отрибутов... действительно работает, спасибо!!! :)
Цитата:

я установил эту версию, но поверх старой (v3.2.0.1), неужели файлы справки в таком случае не заменяются?
Ну, либо так как ты предположил, либо они обновили дистрибутив уже после того как ты его скачал. Я посмотрел, у меня в заголовках 3-x справок написано: v3.2.2.0 (скачивал я его, где-то после 10.01.2007)

DenchikK 22-01-2007 18:24 539863

Хочется узнать, как бы сделать так, чтоб скрипт искал файл qip.exe во
всём каталоге Program Files, и если таковой найдется - возвратил бы
тот каталог, в котором он лежит и запихнул бы в реестр полный путь к
катлогу (не к файлу). Это вообще осуществимо?
Заранее спасибо!

Creat0R 23-01-2007 00:41 539972

Diamond
Цитата:

Можно ли как-то заставить GUI, игнорировать (установленый в системе по умолчанию) стиль Windows XP
Такого конкретного стиля (кажется) нет, но можно вручную это делать, почти также как ты это сделал с примером для следующего вопроса ;)

Цитата:

Сущесвует ли какой нибудь простой способ претаскивания окна стиля $WS_POPUP
Есть стил $GUI_WS_EX_PARENTDRAG, его нужно “вешать” например на GuiCtrlCreateLabel, и тогда можно перетаскивать окно тягая этот контроль:

Код:

#include <Guiconstants.au3>
Opt("GUIOnEventMode",1)
$test=GUICreate("",400,300,-1,-1,$WS_POPUP+$WS_BORDER)
GUISetBkColor(0xBEFFBE)
GUISetOnEvent($GUI_EVENT_CLOSE,"ExitGui")
$Closed_button=GUICtrlCreateButton("X",377,4,18,18)
GUICtrlSetFont(-1,10,700,0,"Tahoma")
GUICtrlSetOnEvent(-1,"ExitGui")
$Mim_button=GUICtrlCreateButton("-",337,4,18,18)
GUICtrlSetFont(-1,13,700,0,"Arial Black")
GUICtrlSetOnEvent(-1,"MimimizeGui")
$Max_button=GUICtrlCreateButton(CHR(152),357,4,18,18)
GUICtrlSetFont(-1,9,700,0,"Tahoma")
GUICtrlSetState(-1,$GUI_DISABLE)
$text=GUICtrlCreateLabel("Manual GUI Drag",5,5,325,18, $SS_Center, $GUI_WS_EX_PARENTDRAG)
GUICtrlSetFont(-1,12,700,0,"Courier New")
GUICtrlSetColor(-1,0xBEFFBE)
GUICtrlSetBkColor(-1,0x000000)
DllCall("User32.dll","long","AnimateWindow","hwnd",$test,"long",300,"long",0x10)
GUISetState()

While 1
      Sleep(100)
WEnd

Func MimimizeGui()
      GUISetState(@SW_MINIMIZE)
EndFunc

Func ExitGui()
      DllCall("User32.dll","long","AnimateWindow","hwnd",$test,"long",300,"long",0x10+0x10000)
      Exit
EndFunc


Цитата:

либо они обновили дистрибутив уже после того как ты его скачал
Ладно, спасибо, попробую ещё раз перекачать и установить.

Creat0R 23-01-2007 01:06 539974

DenchikK
Цитата:

чтоб скрипт искал файл qip.exe во
всём каталоге Program Files, и если таковой найдется - возвратил бы
тот каталог, в котором он лежит и запихнул бы в реестр полный путь к
катлогу (не к файлу).
Вот рабочий пример, путь в реестре куда писать, поменяешь у переменной $RegKey, а имя значения у переменной $RegValueName:

Код:

#include <File.au3>
#include <Array.au3>

$PathForSearch = @ProgramFilesDir
$FileToFind = "Qip.exe"
$RegKey = "HKEY_CURRENT_USER\Software\QIP"
$RegValueName = "Path"

ProgressOn("Please wait...", "Getting Folders Structure...", $PathForSearch, -1, -1, 16)
$SearchResults = _FileFind($PathForSearch, $FileToFind)
ProgressOff()
If $SearchResults <> -1 Then
      RegWrite($RegKey, $RegValueName, "REG_SZ", $SearchResults)
      MsgBox(262144+64, "Done!", "File <" & $FileToFind & "> was found in this path <" & $SearchResults & ">, and the path was writen to registry key <" & $RegKey & "> under <" & $RegValueName & "> valuename.")
Else
      MsgBox(262144+48, "Attention!", "File <" & $FileToFind & "> was not found on <" & $PathForSearch & "> and it subfolders." & @CR & @CR & "OK ---> EXIT")
EndIf

Func _FileFind($Path, $FileToFind)
      Local $RetPath = $Path
      If FileExists($Path & "\" & $FileToFind) Then Return $Path
      $SubFoldersArr = _DirListToArray($Path)
      If IsArray($SubFoldersArr) Then
            $PrgrsDelim = 100 / $SubFoldersArr[0]
            $Prgrrs = $PrgrsDelim
            ProgressSet($Prgrrs, $Path, "Search for <" & $FileToFind & "> is in process...")
            For $iF = 1 To $SubFoldersArr[0]
                  ProgressSet($Prgrrs, $SubFoldersArr[$iF])
                  $Prgrrs = $Prgrrs + $PrgrsDelim
                  If FileExists($SubFoldersArr[$iF] & "\" & $FileToFind) Then
                        $RetPath = $SubFoldersArr[$iF]
                        ExitLoop
                  EndIf
            Next
      EndIf
      If $RetPath <> $Path Then
            Return $RetPath
      Else
            Return -1
      EndIf
EndFunc

Func _DirListToArray ($sPath)
    Local $i, $j, $rlist[1]=[0], $blist, $alist=_FileListToArray ($sPath, '*', 2)
    If IsArray ($alist) Then
      For $i=1 To $alist [0]
            _ArrayAdd ($rlist, $sPath & "\" & $alist [$i])
            $blist = _DirListToArray ($sPath & "\" & $alist [$i])
            If $blist[0] > 0 Then
                  $PrgrsDelim = 100 / ($blist[0] + $alist[0])
                  $Prgrrs = $PrgrsDelim
                  For $j=1 To $blist[0]
                        ProgressSet($Prgrrs, $blist[$j])
                        $Prgrrs = $Prgrrs + $PrgrsDelim
                        _ArrayAdd ($rlist, $blist[$j])
                  Next
            EndIf
        Next
    EndIf
    $rlist [0] = UBound ($rlist) - 1
    Return $rlist
EndFunc

Если ненужен вывод прогресса, просто убери строчки связанные с Progress ;)

Diamond 23-01-2007 05:31 539995

DenchikK
Creat0R
К сожалению, а может и к радости, мне не удалось найти уже готового решения и я решил написать функцию поиска сам.
А сейчас захожу на форум и, вот тебе раз, опоздал... Ну да ладно... как вам такой вариант, вроде бы тоже ничего? :blush2:
P.S. Есть ещё перебор через VBScript с помощью ObjCreate(). Если интересно - выложу. :)
Код:

$ret = find(@ProgramFilesDir,"qip.exe")
If Not $ret=0 Then
        MsgBox(0,"",$ret)
        ; Записываем значение $ret в реестр...
Else
        MsgBox(0,"","Файл не найден.")
EndIf

;=================================

; $Path - Путь поиска. ( Не должен заканчиваться слэшем!!! )
; $FileName - Имя искомого файла.
; Возвращает полный путь к каталогу (не к файлу), если файл осутствует возвращает 0

Func find($Path,$FileName)
If Not IsDeclared("GetPath") Then
        Global $GetPath=0
EndIf

$ModPath=$Path & "\*" ; Формирую строку поиска (толко для инициализации)
$file=FileFindFirstFile($ModPath) ; Инициализация поиска
While 1
        $get=FileFindNextFile($file) ; Поиск...
        If @error Then ExitLoop
        $string=$Path & "\" & $get ; Формирую новый путь
        If Not StringInStr(FileGetAttrib($string),"D") Then ;Если не является папкой тогда:
                If $get=$FileName Then
                        $GetPath=$Path
                        ExitLoop
                EndIf
        Else
                find($string,$FileName) ; Запуск подфункции для поиска в подпапке
        EndIf
WEnd
FileClose($file) ;Завершение инициализации
Return $GetPath
EndFunc

Исправлено!

Creat0R 23-01-2007 05:47 539997

Такой вопрос:
-Возможно ли получить иконку из файла, в случае если расширение файла не зарегистрированно в системе? Т.е мне нужно сделать GuiCtrlSetImage(), и указать так, чтобы та иконка которая отображается на файле, была считана для контроля ($CtrlID).
К примеру, есть файл Program.exe, известно что далеко не все исполняемые файлы (и другие) содержат иконку, и нужно каким то образом определить, содержит ли этот файл иконку, если не содержит, то естественно путь к иконке можно указать к Shell32.dll, 2 (где 2 это ID иконки для екзешников не содержащих иконки), если содержит, то к самому файлу, и как ID ставить 0. А если файл не исполняемы, то можно по расширению читать из реестра путь к иконке.

Вобщем-то сам вопрос - Как узнать, содержит ли файл иконку? и по возможности, получить путь к иконке для не зарегистрированных типов файлов.

Creat0R 23-01-2007 06:38 540004

Diamond
Цитата:

вроде бы тоже ничего?
Вроде бы? :o а теперь засекай время поиска моей функции (часть которой является также и функция от amel27 - _DirListToArray()), и время для поиска которое уходит у твоей функции, результат шокирующий (меня) - Мой скрипт ищет (у меня на компе, с моей кучей программ) ровно 16 секунд, твой, ровно в два раза быстрее! 8 секунд! :UP: я понимаю что ProgressSet занимает время, но я сравнивал “голые” функции в действии, и тоже в два раза твоя оказалась быстрее.
Правда есть пару минусов - нет возможности заранее получить общее количество найденых папок (для точного подсчёта прогрессбара, или вывода прочей информации), также нельзя искать по маске, или ставить случайно слеш после пути :tongue: . Но в данном случае, если требуется произвести исключительно поиск, то этот (твой) вариант идеальный! :up:

P.S.
Немного изменил гуи для перетаскивания, и код для поиска (там в самой функции случайно указал \qip.exe :blush2: ).

Creat0R 23-01-2007 07:51 540019

Diamond
А функция не работает то :( - нужно Global $GetPath = 0 ставить вне функции, т.к каждый вызов подфункции, вне зависимости от того найден ли файл, задаёт переменной $GetPath значение 0, таким образом цикл не прирывается, и пока не проверяются все файлы функция действует...

Вот немного изменил её (сорри если что), а также добавил в неё определение файла в корневом каталоге (в $Path):

Код:

Global $GetPath=0
$ret = find(@ProgramFilesDir,"qip.exe")
If Not $ret=0 Then
        MsgBox(0,"",$ret)
        ; Записываем значение $ret в реестр...
Else
        MsgBox(0,"","Файл не найден.")
EndIf

;=================================

; $Path - Путь поиска. ( Не должен заканчиваться слэшем!!! )
; $FileName - Имя искомого файла.
; Возвращает полный путь к каталогу (не к файлу), если файл осутствует возвращает 0

Func find($Path,$FileName)
$ModPath=$Path & "\*" ; Формирую строку поиска (толко для инициализации)
$file=FileFindFirstFile($ModPath) ; Инициализация поиска
While 1
; Условие для прерывания всех циклов - чтобы быстро выйти из функции
        If $GetPath <> 0 Then ; Если нужный нам файл уже найден тогда
                ExitLoop ; Прерываю циклы всех подфункций
        EndIf
        $get=FileFindNextFile($file) ; Поиск...
        If @error Then ExitLoop
        $string=$Path & "\" & $get ; Формирую новый путь
        If Not StringInStr(FileGetAttrib($string),"D") Then ;Если не является папкой тогда:
                If $get=$FileName Then
                        $GetPath=$Path
                        ExitLoop
                EndIf

        Else
                find($string,$FileName) ; Запуск подфункции для поиска в подпапке
        EndIf
WEnd
FileClose($file) ;Завершение инициализации
Return $GetPath
EndFunc

Файл в корневом каталоге и раньше определялся (если убрать Global $GetPath = 0 из функции), но так быстрее ;)
P.S. всё изменённое выделенно.

Creat0R 23-01-2007 08:44 540034

Diamond
Немного “гуинизировал” твою функцию для поиска файла :biggrin: - в первом поле задаём путь в котором нужно искать, а в нижнем запрос (имя файла) - неверно набранный путь (если не существует или содержит слеш на конце) определяется, а также определяется если набранное имя файла содержит непозволенные символы (< > | ? : * / \ "):

Код:

Opt("GuiOnEventMode", 1)

Global $Progress = 0.1, $GetPath = 0
$PathForSearch = @ProgramFilesDir
$FileToFind = "FileName.exe"

$Gui = GUICreate("File Finder", 300, 170, -1, -1, -1, 0x00000088)
GUISetOnEvent(-3, "ExitScript")

GUICtrlCreateLabel("Path to search on:", 20, 30)
$PathInput = GUICtrlCreateInput($PathForSearch, 20, 50, 270)

GUICtrlCreateLabel("File to find:", 20, 90)
$FileNameInput = GUICtrlCreateInput($FileToFind, 20, 110, 270)

$SearchButton = GUICtrlCreateButton("Search", 70, 140, 60, 20)
GUICtrlSetOnEvent(-1, "SearchButton")
$CancelButton = GUICtrlCreateButton("Cancel", 180, 140, 60, 20)
GUICtrlSetOnEvent(-1, "ExitScript")

GUISetState()

While 1
    Sleep(100)
WEnd

Func _FindFile($Path, $FileName)
    $ModPath = $Path & "\*" ; Формирую строку поиска (толко для инициализации)
    $File = FileFindFirstFile($ModPath) ; Инициализация поиска
    While 1
        ; Условие для прерывания всех циклов - чтобы быстро выйти из функции
        If $GetPath <> 0 Then ExitLoop ; Прерываю циклы всех подфункций
        $Get = FileFindNextFile($File)
        If @error Then ExitLoop
        $String = $Path & "\" & $Get ; Формирую новый путь
        ProgressSet($Progress, $Path & @CR & $Get)
        $Progress = $Progress + 0.1
        If $Progress >= 100 Then $Progress = 0.1
        If Not StringInStr(FileGetAttrib($String), "D") Then ;Если не является папкой тогда:
            If $Get = $FileName Then
                $GetPath = $Path
                ExitLoop
            EndIf
        Else
            _FindFile($String, $FileName) ; Запуск подфункции для поиска в подпапке
        EndIf
    WEnd
    FileClose($File) ;Завершение инициализации
    Return $GetPath
EndFunc

Func SearchButton()
    If Not FileExists(GUICtrlRead($PathInput)) Then
        _MsgBox(16, "Error", "You must type an existing path", $Gui)
    ElseIf StringRight(GUICtrlRead($PathInput), 1) = "\" Then
        _MsgBox(48, "Attention!", "The path must not have a slash (\) at the end of it.", $Gui)
    ElseIf GUICtrlRead($FileNameInput) = "" Then
        _MsgBox(16, "Error", "You must type a file name", $Gui)
    ElseIf Not _IsFileName(GUICtrlRead($FileNameInput)) Then
        _MsgBox(16, 'Error', 'The file name include an invalid characters' & @CR & '< > | ? : * / \ "', $Gui)
    Else
        $PathForSearch = GUICtrlRead($PathInput)
        $FileToFind = GUICtrlRead($FileNameInput)
        GUISetState(@SW_HIDE, $Gui)
        ProgressOn("Please wait...", "Search is in progress...", $PathForSearch, -1, -1, 16)
        $SearchResults = _FindFile($PathForSearch, $FileToFind)
        ProgressOff()
        If Not $SearchResults = 0 Then
            MsgBox(262144+64, "Done!", "File <" & $FileToFind & "> was found in this path <" & $SearchResults & ">.")
        Else
            MsgBox(262144+48, "Attention!", "File <" & $FileToFind & "> was not found on <" & $PathForSearch & "> and it subfolders." & @CR & @CR & "OK ---> EXIT")
        EndIf
        GUISetState(@SW_SHOW, $Gui)
    EndIf
EndFunc

Func _IsFileName($Test)
    If StringRegExp($Test, '[<>|?:"*/\\]') <> 0 Then
        Return False
    Else
        Return True
    EndIf
EndFunc

Func _MsgBox ($MsgBoxType, $MsgBoxTitle, $MsgBoxText, $mainGUI=0)
    $ret = DllCall ("user32.dll", "int", "MessageBox", _
            "hwnd", $mainGUI, _
            "str", $MsgBoxText , _
            "str", $MsgBoxTitle, _
            "int", $MsgBoxType)
    Return $ret [0]
EndFunc

Func ExitScript()
    Exit
EndFunc


Diamond 23-01-2007 09:30 540045

Creat0R
Цитата:

Такого конкретного стиля (кажется) нет
Вот и я так подумал что в самом AutoIt классического стиля нет. Мне кажется, что это сама система навязывает свой стиль(Windows XP). Т.е. это как например если не указать конкретно цвет фона для GUI, то цвет фона по умолчанию становится системный(BtnFace). Вот если бы это дело можно было как-то "блокировать", думаю нужно копать в сторону WinApi.
Цитата:

тогда можно перетаскивать окно тягая этот контроль:
Отлично! Что-то вроде этого я как раз и искал. :) Спасибо! Жалко только что GuiCtrlCreateLabel перекрывает мои кнопки.
Цитата:

твой, ровно в два раза быстрее!
Я считаю что мой скрипт значительно уступает твоему по функциональности. :not-me:
Цитата:

цикл не прирывается, и пока не проверяются все файлы функция действует
Да действительно... я добавил Global $GetPath=0 в самый последний момент, и видимо как следует не протестировал, :blush: а до того у меня стоял Global $GetPath без всяких нулей - соответственно, при отсутствии файла возвращалось пусто (""). В принципе, $GetPath можно оставить и внутри функции (только не приравнивать нулю или, проверять переменную на декларирование), а на скорости я думаю это сильно не отразится. Кстати протестировал на скорость у меня разница где-то 1,5 раза. Спасибо что указал на ошибку! :)
А вот ExitLoop что ты добавил, никак не влияет на прерывание! :nono:

Creat0R 23-01-2007 10:27 540069

Diamond
Цитата:

ExitLoop что ты добавил, никак не влияет на прерывание!
Создай в C:\program files файл test.txt, и задай вместо qip.exe - test.txt, теперь запусти функцию без ExitLoop (засеки время поиска), и запусти с ExitLoop, файл найден почти сразу же ;)

Diamond 24-01-2007 02:45 540390

Creat0R
Цитата:

запусти функцию без ExitLoop (засеки время поиска), и запусти с ExitLoop, файл найден почти сразу же
Твой способ проверки (сравнение по времени) оказался не стабилен. Я долго гонял:maniac:скрипт и, во многих случаях получалось как раз то всё наоборот. Но я решил подставлять Msgbox() в разных места и при различных вариантах. Получается что ты прав! И даже больше!!! :UP:

Когда дочерняя подфункция находит файл, она завершаясь возвращает контроль родительской функции, которая в свою очередь (как я понял) продолжает работу с того места откуда последний раз запускала дочернюю подфукцию, а вот тут-то :moderator её будет поджидать твой ExitLoop. Исходя из всего выше сказаного, я думаю (моё) "условие для прерывания всех циклов" - абсолютно лишнее!
Т.е. когда стоит твой ExitLoop, то до моего условия (прерывания), дело вообще не доходит!!! Уф-ф... В общем, я убираю его (условие)... :)

Creat0R 24-01-2007 17:36 540715

Нашёл в аутоите баг (или это так задуманно?) - При BlockInput(1), вроде всё кроме Ctrl Alt Del должно быть заблокированно, но срабатывает нажатие и на Sleep и на Power.
Собственно вопрос: Возможно ли перед блокировкой, назначить другое действие для этих клавиш? (т.е чтобы при их нажатии ничего не происходило) - Очень очень нужно :( .

P.S
Задать клавишу Sleep можно, но она почему то продолжает работать (как Sleep)

Creat0R 24-01-2007 21:47 540839

Давно искал способ сделать “плавающее окошко”, чтобы ещё при “плавании” :), перемещалось хаотично по экрану. Когда ещё только начинал разбирать гуи в AutoIt'е, думал это не реально, и забросил эту затею, но вот тут ни с того ни с сего, я вдруг вспомнил об этом, и решил попробовать реализовать (всё же знании уже побольше), и, реализовал! (довольно без проблем, и быстро)...

Вот Пример:

Код:

#include <GuiConstants.au3>
Opt("GuiOnEventMode", 1)

;Создаём стильны гуи для показа ;-)
GUICreate("Fading GUI", 200, 100, -1, -1, $WS_POPUP+$WS_DLGFRAME, $WS_EX_CLIENTEDGE+$WS_EX_TOPMOST)
GUISetOnEvent(-3, "ExitScript")
GUISetBkColor(0xC1C9FD)
;Активируем гуи в скрытом режиме, в целях избежания мерцания окна при первом запуске
GUISetState(@SW_HIDE)
;Устанавливаем самый высокий уровень (0) прозрачности окна гуи
WinSetTrans("Fading GUI", "", 0)
;Показываем обратно гуи в невидемом состоянии (100 % прозрачности)
GUISetState(@SW_SHOW)

$Close = GUICtrlCreateButton("Close", 70, 40, 60, 20)
GUICtrlSetOnEvent(-1, "ExitScript")

;Включаем функцию утухания и перемещения окна каждые 100 м"с
AdlibEnable("GUIFad", 100)
While 1
    Sleep(10)
WEnd

Func GUIFad()
    ;Задаём интервал исчезновения окна и проходимся по нему
    For $i = 0 To 255
        Sleep(10)
        WinSetTrans("Fading GUI", "", $i)
    Next
    Sleep(50)
    ;Задаём интервал появления окна и проходимся по нему (в обратном порядке)
    For $j = 255 To 0 Step -1
        Sleep(10)
        WinSetTrans("Fading GUI", "", $j)
    Next
    ;Двигаем окно в хаотичном порядке (хм, парадокс получается ;) ), в соответствии с координатами разрешения экрана
    WinMove("Fading GUI", "", Random(0, @DesktopWidth-200), Random(0, @DesktopHeight-200))
EndFunc

Func ExitScript()
    Exit
EndFunc

Очень подходит если нужно сделать своего рода призентацию, или просто слайдшоу картинок или ещё чего нибудь :blush2: .

Creat0R 26-01-2007 03:48 541486

Оказывается, можно вызвать MsgBox не в стильном виде (не испоьзуя стиль WinXP) - т.е сообщение будет выглядеть как системное в Win98...

Нужно просто перед основным флагом, ставить стиль 0x20000:

Код:

MsgBox(0x20000+64, "Hello!", "I am styleless MsgBox ;) ")
Я вот только не знаю как убрать атрибут “поверх всех окон”, перепробовал кучу номеров, но так и не нашёл подходящий.

borzoy 27-01-2007 01:32 541945

Привет всем!!!
Помогите пожалуйста с скриптом для установкой Fraps и Runpad Shell.
Для тихой установки уже наверное все ключики перепробЫвал, но не помогает, всеравно вылазиет табличка с уведомлением установить программу.

Creat0R 27-01-2007 10:28 542047

borzoy
Цитата:

Для тихой установки уже наверное все ключики перепробЫвал
Эта инфа, я полагаю должна сопоставляться с установщиком...
А вообще, нужно было создавать отдельный топик:

Цитата:

Данная тема предназначена для общих вопросов по AutoIt. Вопросы по установке приложений при помощи AutoIt следует задавать в соответствии с правилами форума "Автоматическая установка приложений". Таким образом, если вы хотите узнать как установить Winamp 5.x при помощи AutoIt, то создайте тему [autoit] Winamp 5.х (если таковой еще нет на форуме). Проверить наличие тем можно при помощи поиска или фильтров.

borzoy 27-01-2007 19:12 542273

Creat0R
Цитата:

Таким образом, если вы хотите узнать как установить Winamp 5.x при помощи AutoIt, то создайте тему [autoit] Winamp 5.х (если таковой еще нет на форуме).
Видимо Модераторы плохо знают правила раз сами их не знают. Сделал как и написано было тему [autoit]Fraps и Punpad Shell4 но какой то модератор удалил эту тему!!!

jameszero 28-01-2007 00:39 542398

borzoy
Я отправил вам оповещение, что ваша тема [autoit] Fraps и Punpad Shell4, с просьбой помочь создать скрипт, перенесена в созданную вами же тему Помогите с тихой установкой Fraps и Runpad Shell, в которой уже начато обсуждение.
Зачем создавать одинаковые темы? ОПК - пункт 2.1
(Тема переименована в [autoit] Fraps и Runpad Shell, ни один пост не удалён)

Creat0R 29-01-2007 18:44 543173

В AutoIt'е плохо (а точнее не корректно) работает функция FileDelete - например если написать её так:

Код:

FileDelete(@TempDir & "\")
То в папке @TempDir будут удалены все файлы (не папки), т.е если я укажу файл для удаления в виде переменной, и каким то образом эта переменная окажется пуста (""), то может произойти нежеланная катастрофа :blush2: - будьте очень остарожны, я на днях попал на эту удочку (правда к счастью у меня был бекап уалившихся файлов).

Diamond 30-01-2007 06:28 543340

Creat0R
Цитата:

В AutoIt'е плохо (а точнее не корректно) работает функция FileDelete
Здесь, если даже не включать проверку на существование файла, то (в случае с пустой переменной или отсутствием файла) скрипт завершиться с ошибкой, но ничего удалено не будет! :tongue:
Думаю всё же, такой способ надёжней в плане безопасности, чем мучаться и придумывать разные хитрости, пытаясь исправить баг AutoIt'а. :)
Код:

Dim $fso
;~ Создание объекта
$fso = ObjCreate("scripting.filesystemobject")

;~ Удаление файла
Func DeleteFile($FileSpec)
If $fso.FileExists($FileSpec) Then
        $fso.DeleteFile($FileSpec, True)
EndIf
EndFunc

;~ Удаление папки
Func DeleteFolder($FolderSpec)
If $fso.FolderExists($FolderSpec) Then
        $fso.DeleteFolder($FolderSpec, True)
EndIf
EndFunc


Creat0R 04-02-2007 06:38 545433

Diamond
Да, это неплохой способ, спасибо, возьмём его пожалуй в арсенал функции аутоита ;)




Я что-то не нашёл функции, которая проверяла бы данное число на чётность/не чётность, и решил её сам сделать (понадобилась сея функция), но не уверен что это правильное решение, может уже есть подобная функция, или у кого то есть более универсальное предложение? :shuffle:

Код:

$iNumber = 2075674

If _IsEven($iNumber) Then
    MsgBox(64, "Even check", "The given number <" & $iNumber & "> is an Even number")
Else
    MsgBox(64, "Even check", "The given number <" & $iNumber & "> is not an Even number (it is Odd)")
EndIf

Func _IsEven($NumString)
    If $NumString < 1 Then
        $NumStrArr = StringSplit($NumString, ".")
        If IsArray($NumStrArr) And $NumStrArr[0] > 1 Then $NumString = $NumStrArr[2]
    EndIf
    If IsFloat($NumString / 2) Then
        Return 0
    Else
        Return 1
    EndIf
EndFunc

.........
И ещё, заметил вроде ещё багу в аутоите, проверить очень просто:

Код:

MsgBox(0, "", 0.00001)
Получаем 1e-005 - и это так должно быть? я понимаю что можно заключить в кавычки, и тогда будет отображать дословно, но просто интересно, почему это происходит? :blink:

amel27 04-02-2007 07:18 545435

Creat0R
Привет, на самом деле все гораздо проще:
Код:

Func _IsEven ($num)
    If Mod($num,2)=0 Then
        Return 1
    Else
        Return 0
    EndIf
EndFunc

...хотя твои манипуляции с точкой наводят на мысль что обычной четности тебе мало (имеет смысл только для целых чисел).
Цитата:

И ещё, заметил вроде ещё багу в аутоите
Это не баг, это фича. ;) ...Это разное представление одного числа, поэтому все вполне корректно.
Для однозначного представления используй StringFormat:
Код:

MsgBox (0,'',StringFormat('%.5f',0.00001))

amel27 04-02-2007 08:29 545444

Creat0R
Diamond


Красивый способ для FileDelete с форума поддержки:
Код:

Func _FileDelete ($file)
    If Not StringInStr(FileGetAttrib($file),'D') Then
        FileDelete($file)
    EndIf
EndFunc


Diamond 04-02-2007 20:34 545643

Подскажите, как с помощью WinApi поменять частоту обновления экрана?
В интернете есть множество примеров с использованием библиотеки: user32.dll функция: ChangeDisplaySettingsA, но как реализовать это в AutoIt совершенно не представляю. Очень надо!!!

Creat0R 05-02-2007 00:51 545717

amel27
Цитата:

на самом деле все гораздо проще
Действительно, а главное, этот пример есть и в справке, как я его упустил :) спасибо!

Цитата:

твои манипуляции с точкой наводят на мысль что обычной четности тебе мало
Просто хотел проверять и чётность дробных чисел.

Цитата:

Красивый способ для FileDelete с форума поддержки
Хм, это видимо самый верный способ, просто проверяется если это не папка, тогда удаляется файл... а разработчики вкурсе об этом? почему не сделают “офицеальную” команду в таком же духе ;)




Такой вопрос:
Как послать обычное нажатие клавишы Windows (с изображением окон)? нужно отдельно в експлорере вызвать контекстное меню, и единственны способ который мне пришел в голову, так это нажать эту клавишу...
Пробую так:
Код:

Send("#")
Ничего не происходит, в полукруглые скобки заключать пробовал, тоже никакого эффекта, есть идеи?

Или, как можно обновить окно експлорера, но не посыланием F5, а именно полноценным обновлением (в некоторых случаях F5 не помагает).

Creat0R 06-02-2007 04:32 546256

Ещё способ удаления файла:

Код:

Func _FileDelete($Path, $FileName)
    If StringLen($FileName) >= 1 Then FileDelete($Path & "\" & $FileName)
EndFunc

А также способ подсчёта количества символов в файле:

Код:

$FileName = @ScriptDir & "\test.txt"
$FileCharCount = _FileCountChar($FileName, 0)
If $FileCharCount <> -1 Then
    MsgBox(64, "File Characters Count", "In the file <" & $FileName & "> was found [" & $FileCharCount & "] characters (including Carriage Returns and Line Feeds)")
Else
    MsgBox(16, "Error!", "The file <" & $FileName & "> was not found")
EndIf

Func _FileCountChar($FileName, $Flag=0)
    If Not FileExists($FileName) Then Return -1
    Local $CharsCount = 0
    $fRead = FileRead($FileName, FileGetSize($FileName))
    $fReadArr = StringSplit($fRead, "")
    If IsArray($fReadArr) Then
        For $i = 1 To $fReadArr[0]
            If ($Flag = 1 And $fReadArr[$i] <> @CR And $fReadArr[$i] <> @LF) Or ($Flag = 2 And $fReadArr[$i] <> @CR) Or ($Flag = 3 And $fReadArr[$i] <> @LF) Or $Flag = 0 Then $CharsCount += 1
        Next
        Return $CharsCount
      EndIf
EndFunc


Если поставить последний параметр как 1 ($Flag=1), то подсчёт не будет учитывать возврат каретки и перевод строки (@CRLF), если поставить параметр на 2, то будут учитываться все символы кроме @CR, ну а если поставит параметр $Flag = 3, то будут учитываться все символы за исключением символа перевода строки (@LF).

amel27 06-02-2007 11:35 546384

Diamond
Цитата:

Подскажите, как с помощью WinApi поменять частоту обновления экрана?
Код:

; Пример использования функции
_DisplaySetRes (1024, 768, 32, 75)

; Функция изменения видеорежима (для одного монитора)
Func _DisplaySetRes ($width, $height, $depth, $freq)
    Local $dev = DllStructCreate ("byte[32];int[10];byte[32];int[6]")
    ; Возвращаем текущее состояние устройства
    Local $ret = DLLCall ('user32.dll', 'int', 'EnumDisplaySettings', _
        'ptr' , 0, _
        'long', 0, _
        'ptr' , DllStructGetPtr ($dev) )
    If @error Then Return 0
    If $ret[0]=0 Then Return 0
    ; Правим нужные элементы структуры
    DllStructSetData ($dev, 4, $depth, 1)
    DllStructSetData ($dev, 4, $width, 2)
    DllStructSetData ($dev, 4, $height, 3)
    DllStructSetData ($dev, 4, $freq, 5)
    ; Проверяем корректность параметров
    $ret = DllCall ('user32.dll', 'int', 'ChangeDisplaySettings', _
        'ptr', DllStructGetPtr ($dev), _
        'int', 2 )
    If @error Then  Return 0
    ; Если все ОК - применяем новые параметры
    If $ret[0] =0 Then
        $ret = DllCall ('user32.dll', 'int', 'ChangeDisplaySettings', _
            'ptr', DllStructGetPtr ($dev), _
            'int', 1 )
        If @error Then  Return 0
        Return 1
    Else
        Return -1
    EndIf
EndFunc


amel27 06-02-2007 12:13 546399

Creat0R
Цитата:

А также способ подсчёта количества символов в файле
Альтернативный вариант. Правда пришлось сдвинуть значения флагов, чтобы одному биту соответствовал один пропускаемый символ: @CR - Bit 1 ; @LF - Bit 2.
Код:

Func _FileCharCount ($file, $flag=1)
    Local $str = FileRead ($file)
    If BitAND ($flag, 1) Then $str = StringStripCR ($str)
    If BitAND ($flag, 2) Then $str = StringReplace ($str, @LF, '')
    Return StringLen ($str)
EndFunc


Diamond 06-02-2007 18:29 546566

amel27
По поводу частоты обновления
Отлично! Всё работает! :UP: Если честно, я и не надеялся что вообще кто нибудь ответит, иначе задал бы этот вопрос ещё месяц назад. Большое спасибо!
P.S.
Была проблема с видеокартой, в некоторых играх частота сбрасывалась с 85 Гц. на 60 Гц. Перепробовал уже (наверное) все известные утилиты и ни одна из них не помогла. Теперь проблема решилась. :victory: Ещё раз спасибо!

i_mihal 12-02-2007 01:19 548665

Есть фирменная YAMAHA'овская программа для конвертирования звуковых WAV-файлов
в формат MMF (используется в сотовых телефонах Samsung, LG, Pantech, etc...)
Называется WSC-MA2, сайт http://smaf-yamaha.com/

Это, похоже, единственая программа, которая может конвертировать WAV->MMF.
Но она не работает из командной строки, у нее нет меню, она не работат в пакетном режиме.
Для того чтоб сконвертировать WAV в MMF надо схватить WAV-файл мышкой,
перетащить и бросить его на маленькое, красивенькое окошко этой программы.

Можно ли с помощью AutoIt проделать такую операцию?
То есть "взять некий WAV-файл мышкой" и "кинуть его на окошко этой проги"
(в перспективе взять по-очереди в цикле все файлы с расширением WAV
и покидать их на окошко программы)

Реализуемо ли это в рамках Auto-It?
или вообще как-нибудь, кроме как вручную.

спасибо.


amel27 12-02-2007 06:36 548710

i_mihal
обычно перетаскивание можно заменить на копировать/вставить через буфер обмена...

amel27 12-02-2007 07:05 548717

Чтение параметров локализации средствами API:
Код:

$sys = DllCall ("kernel32.dll", "int", "GetSystemDefaultLCID")
$usr = DllCall ("kernel32.dll", "int", "GetUserDefaultLCID")
MsgBox (0,'Default locale ID','Пользователи: ' & @TAB & @TAB & $usr[0] & @CRLF & _
    'Системные службы: ' & @TAB  & $sys[0])


Creat0R 12-02-2007 10:59 548797

Написал давно желанную функцию, но она работает как бы наполовину - она должна заменять стандартную функцию FileSelectFolder, но проблема в том, что у меня не получается - А) либо создать все вкладки (в TreeView) для всех существующих папок (это также займёт кучу времени на их генерацию), Б) либо создавать их “находу” (т.е в момент вызова/раскрытия той или иной вкладки) - в принципе, проблема со вторым вариантом такая - нужно узнать как очистить одну выделенную вкладку от её подвкладок (не удаляя её саму).
Для чего нужна такая функция? во-первых для того чтобы можно было прикреплять это окно к другому приложению (или к родительскому гуи) - эта одна из основных причин (даже самая) - далее можно также используя подобную функцию, просто создавать это окно с разными размерами, с разными кнопками и возвращаемой информацией, также будет возможность задать этому окну атрибут “поверх всех окон” и т.д и т.п...

Вот в принципе сам скрипт с примером:

Код:

#include <GUIConstants.au3>
#include <GUITreeView.au3>
#include <File.au3>

$Parent = GUICreate("test", 200, 200)
$Select = GUICtrlCreateButton("Select", 50, 50)

GUISetState()

While 1
        $Msg = GUIGetMsg()
        If $Msg = -3 Then ExitLoop
        If $Msg = $Select Then
                GUISetState(@SW_DISABLE)
                $Path = _FileSelectFolder("Select Folder", "Choose needed Path:", 300, 300, 1, $Parent)
                If Not @error Then MsgBox(64, "Path", "The selected path is: <" & $Path & ">")
                GUISetState(@SW_RESTORE)
                GUISetState(@SW_ENABLE)
        EndIf
WEnd

GUIDelete()

Func _FileSelectFolder($Title, $Dialog_Text, $Width=300, $Heght=300, $OnTop=0, $Hwnd="")
        Opt("GuiOnEventMode", 1)
        Global $IsExit = 0, $IsCancel = 0, $PathInput, $MainTreeViewID, $TOPMOST
        If $OnTop = 1 Then $OnTop = 8
        GUICreate($Title, $Width, $Heght, -1, -1, $WS_SYSMENU+$WS_CAPTION+$WS_SIZEBOX, $WS_EX_CONTEXTHELP+$OnTop, $Hwnd)
        GUISetOnEvent(-3, "Cancel")
       
        GUICtrlCreateLabel($Dialog_Text, 10, 5)

        $ButtonOK = GUICtrlCreateButton("OK", $Width-180, $Heght-25, 70, 20)
        GUICtrlSetOnEvent(-1, "OK")
       
        $ButtonCancel = GUICtrlCreateButton("Cancel", $Width-80, $Heght-25, 70, 20)
        GUICtrlSetOnEvent(-1, "Cancel")
       
        $PathInput = GUICtrlCreateInput("", 10, $Heght-50, $Width-20)

        $MainTreeViewID = GUICtrlCreateTreeView(10, 30, $Width-20, $Heght-90, BitOr($TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_DISABLEDRAGDROP, $TVS_SHOWSELALWAYS), $WS_EX_CLIENTEDGE)

        GUISetState()

        $DrivesArr = _DrivesListToArray("all")
        If IsArray($DrivesArr) Then
                Dim $MainDriveID[$DrivesArr[0]+1], $CurrentIcon, $CurrentIcID
                For $i = 1 To $DrivesArr[0]
                        $CurrentDrive = $DrivesArr[$i]
                        If $CurrentDrive <> "a:" And $CurrentDrive <> "b:" Then
                                $CurrentIcon = $CurrentDrive & "\" & IniRead($CurrentDrive & "\Autorun.inf", "Autorun", "Icon", "")
                                $CurrentIcID = 0
                        EndIf
                        If Not FileExists($CurrentIcon) Then
                                $CurrentIcon = "shell32.dll"
                                $CurrentIcID = 8
                        EndIf
                        $MainDriveID[$i] = GUICtrlCreateTreeViewItem(StringUpper($CurrentDrive) & "\", $MainTreeViewID)
                        GUICtrlSetOnEvent(-1, "GetText")
                       
                        If $CurrentDrive = "a:" Or $CurrentDrive = "b:" Then
                                GUICtrlSetImage(-1, "shell32.dll", 6, 0)
                        ElseIf DriveGetType($CurrentDrive) = "CDROM" Then
                                GUICtrlSetImage(-1, "shell32.dll", 11, -1)
                        Else
                                GUICtrlSetImage(-1, StringStripWS($CurrentIcon, 3), $CurrentIcID, -1)
                        EndIf
                       
                        If $CurrentDrive <> "a:" And $CurrentDrive <> "b:" Then
                                $DirsArr = _FileListToArray($CurrentDrive, "*", 2)
                                If IsArray($DirsArr) Then
                                        For $j = 1 To $DirsArr[0]
                                                $CurrentDir = $DirsArr[$j]
                                                GUICtrlCreateTreeViewItem($CurrentDir, $MainDriveID[$i])
                                                GUICtrlSetOnEvent(-1, "GetText")
                                                _GUICtrlTreeViewSetIcon($MainTreeViewID, -1, "shell32.dll", 4)
                                        Next
                                EndIf
                        EndIf
                Next
        EndIf

        While $IsExit = 0
                Sleep(10)
        WEnd
        $Path = StringReplace(_GUICtrlTreeViewGetTree($MainTreeViewID, "\"), "\\", "\")
        GUIDelete()
        Opt("GuiOnEventMode", 0)
        If $IsCancel = 1 Then
                SetError(1)
                Return ""
        Else
                Return $Path
        EndIf
EndFunc

Func GetText()
        GUICtrlSetData($PathInput, GUICtrlRead(@GUI_CtrlId, 1))
EndFunc

Func OK()
        Global $IsExit = 1
EndFunc

Func Cancel()
        Global $IsExit = 1, $IsCancel = 1
EndFunc

Func Quit()
        Exit
EndFunc

Func _DrivesListToArray($Type)
        $DrivesArr = DriveGetDrive($Type)
        If IsArray($DrivesArr) Then
                Dim $DrivesListArr[$DrivesArr[0]+1]
                $DrivesListArr[0] = $DrivesArr[0]
                For $iDrive = 1 To $DrivesArr[0]
                        $CurrentDrive = $DrivesArr[$iDrive]
                        $DrivesListArr[$iDrive] = $CurrentDrive
                Next
        EndIf
        Return $DrivesListArr
EndFunc

И ещё хотелось бы сделать чтобы можно было задать при вызове функции исходную папку (Init Dir) - но увы я только сегодня начал разбирать основы TreeView, и поэтому не знаю как заставить раскрыться вкладкам на том месте где находится указанное имя (т.е имя вкладки).

biggreeder 12-02-2007 21:42 549092

Вопрос знатокам.
А можно ли как-нибудь "раскомпилировать" .exe файл обратно в .au3?

Creat0R 12-02-2007 22:39 549114

biggreeder
Цитата:

можно ли как-нибудь "раскомпилировать" .exe файл обратно в .au3?
Посмотри в папке с установленным AutoIt'ом - C:\Program Files\AutoIt3\Extras\Exe2Aut - но этолько если в момент компилляции опция позволяющая декомпилировать была утановлена, а также если был задан пароль, то без него никак не декомпилировать.

biggreeder 12-02-2007 23:52 549150

Creat0R
Спасибо, дружище. Выручил. Винт накрылся. Думал пропали все мои скрипты (на диск записывал только exe-файлы)

Dicken 13-02-2007 07:07 549192

День добрый,
интересует следующий вопрос:
Можно ли запускать IT скрипт с какимилибо параметрами, например мне нужен скрипт который бы выводи мне 2 значения из командной строки
т.е. скрипт я запускаю
Код:

RUN.exe параметр1 параметр2
и в результате скрипт выдал мне мессаге в котором мне былибы выданы 1 и 2 параметры
заранее спасибо

Positiv 13-02-2007 08:13 549213

Вообщем такой трабл, при установке Agnitum Outpost Firewall выдает 2 окна с ошибками Microsoft Visual C++ Runtime Library. Я написал в скрипте функцию отлова этих окон с ошибками, но когда закрывается первое окно с ошибкой установка стопорится на Мастере Настройки, т.е дальше только вручную нажимать кнопки приходится. Посмотрите скрипт, мож че подскажите, или из-за чего такие ошибки вылетают, вроде библиотеки Си стоят.
СИНИМ выделено то, что добавил я, все остальное исходный скрипт от Sanja Alone
Код:

#cs
----------------------
Приложение: Agnitum Outpost
На какой(их) версии(ях) тестировалось: 3.5 (ru); 3.51 (ru)

Автор скрипта: Sanja Alone (http://forum.oszone.net/member.php?userid=28800)
----------------------
#ce
;предотвращение возможности множественного запуска скрипта
If WinExists(@ScriptName) Then Exit
AutoItWinSetTitle(@ScriptName)
;блокируем мышь и клаву
;AutoItSetOption("TrayIconHide", 1)
;Отображать текущую строку сценария с помощью индикатора системной панели в режиме отладки.
AutoItSetOption("TrayIconDebug", 1)
AutoItSetOption("SendKeyDelay", 15)
If ProcessExists ( "ps.exe" )<>0 Then
    ProcessClose ( "ps.exe" )
    ProcessWaitClose ( "ps.exe" )
EndIf
;нельзя блокировать при находящемся в памяти Punto Switcher-е - не будет работать установка
;блокируем мышь и клаву
;If @OSType="WIN32_NT" Then BlockInput ( 1 )
#cs
----------------------
объявление переменных
----------------------
$file - установочный файл
$serial - если имеете рабочий ключ, то введите его сюда
$programgroup - в какую программную группу положить ярлыки программы
$delfromautorun - удалить Outpost из автозапуска (1 - удалить (по ум.), любое другое значение - не удалять)

----------------------
#ce
Global $file='OutpostProInstall.exe', $serial='XXXXX', $programgroup='Agnitum Outpost Firewall', $delfromautorun=1
AdlibEnable("wfp",1000)
If FileExists ( @ProgramFilesDir & '\Agnitum\Outpost Firewall\outpost.exe' ) Then
    MsgBox (64, 'Сообщение', 'Agnitum Outpost Firewall уже установлен', 5)
    Exit
  Else
    Run ( @ScriptDir & '\' & $file & ' /LANG="ru" /NOAUTOUPDATE /NORESTART /VERYSILENT' )
EndIf
WinWait ( 'Мастер настройки' )
WinActivate ( 'Мастер настройки' )
WinWaitActive ( 'Мастер настройки' )
Send ( '{ENTER}' )
While ControlCommand ( 'Мастер настройки', '', '< &Назад', 'IsEnabled', '')=0
WEnd
WinActivate ( 'Мастер настройки' )
WinWaitActive ( 'Мастер настройки' )
;Далее
Send ( '{ENTER}' )
WinWait ( 'Ручная настройка' )
WinActivate ( 'Ручная настройка' )
WinWaitActive ( 'Ручная настройка' )
;Готово
Send ( '{ENTER}' )
#cs
----------------------
Крякнутые dll-ки и настройки программы поместите в самораспаковывающиеся архивы
        settings.exe - настройки
        opst_ui.exe - крякнутые dll-ки (если нет рабочего серийника)

команды SFX-сценария (для обоих архивов, winrar):
       
        Path=Agnitum\Outpost Firewall
        SavePath
        Silent=1
        Overwrite=1

----------------------
#ce

If WinWait("Microsoft Visual C++ Runtime Library") Then
WinActivate("Microsoft Visual C++ Runtime Library")
WinWaitActive("Microsoft Visual C++ Runtime Library")
Send("{ENTER}")
EndIf

If FileExists ( @ScriptDir & '\settings.exe' ) Then RunWait ( @ScriptDir & '\settings.exe' )
;регистрация
If $serial<>'' Then
RegWrite("HKEY_LOCAL_MACHINE\SOFTWARE\Agnitum\Outpost Firewall","Key","REG_SZ",$serial)
ElseIf FileExists ( @ScriptDir & '\opst_ui.exe' ) Then
RunWait ( @ScriptDir & '\opst_ui.exe' )
EndIf


;перенос ярлыков
DirCopy ( @ProgramsCommonDir & '\Agnitum\Outpost Firewall', @ProgramsCommonDir & '\' & $programgroup, 1 )
DirRemove ( @ProgramsCommonDir & '\Agnitum', 1 )

;отключить Автообновление
RegWrite("HKEY_LOCAL_MACHINE\SOFTWARE\Agnitum\Outpost Firewall\General","AutoUpdate","REG_DWORD",0x00000000)

;убрать Аутпост из автозапуска (если это было задано выше)
If $delfromautorun=1 Then
RegDelete("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run", "Outpost Firewall")
RegDelete("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run", "OutpostFeedBack")
EndIf

AdlibDisable()

;BlockInput ( 0 )

Exit

Func wfp()
If WinWait("Microsoft Visual C++ Runtime Library","") Then
WinActivate("Microsoft Visual C++ Runtime Library")
WinWaitActive("Microsoft Visual C++ Runtime Library")
Send("{ENTER}")
EndIf
EndFunc


amel27 13-02-2007 09:27 549241

Dicken
Цитата:

Можно ли запускать IT скрипт с какимилибо параметрами
посмотри тут: http://forum.oszone.net/post-461784-212.html
... а также поищи в справке по ключу $CmdLine.

Positiv 14-02-2007 17:37 549947

В стандартных примерах нашёл скрипт sysinfo. Так вот, можно ли сделать, чтобы этот скрипт вместо временной папки или папки Windows(допустим) выводил пароль и имя для каждого пользователя?
Кстати, у кого-нибудь есль стандартные модули с русскими комментариями?

Diamond 14-02-2007 18:01 549964

Нашёл недостаток в InputBox(), проверка на IsNumber() всегда возвращает строчную переменную, даже если вводимые данные были представлены в цифре.
Предлагаю два варианта решения:
Код:

;~ Эта функция работает только с обычными целыми числами
;~ числа типа: 0x5, 4.03 или 00001 не подойдут

Проверка переменной на пренадлежность к числам:
Func _IsNumber($var)
$check=Number($var)
If String($check)=String($var) Then
        Return 1
Else
        Return 0
EndIf
EndFunc
;-------------------------------------
;~ А это первое что мне пришло в голову (банальный перебор)

Проверка переменной на принадлежность к целым числам:
Func _IsInt($var)
If $var= "" Then
        Return -1
EndIf
$len=StringLen($var)
$check=0
For $j=48 To 57
        For $i=1 To $len
                If StringMid($var,$i,1)=Chr($j) Then
                        $check=$check+1
                EndIf
        Next
Next
If $check=$len Then
        Return 1
Else
        Return 0
EndIf
EndFunc


amel27 15-02-2007 04:32 550109

Diamond
Это не недостаток, а издержки типа данных Variant - кстати, аналогично и в Visual Basic... Преобразование типа происходит непосредственно перед выполнением операций с данными - например, при попытке провести арифметические операции со строковой переменной... поэтому иногда вместо преобразования проще прибавить к переменной "0". То, что InputBox() возвращает текстовую строку вполне логично. ИМХО текстовый ввод проще контролировать регулярными выражениями, тем более что этот способ универсален и подходит для любых входных данных:
Код:

Func _IsStringNumber ($sVar)
    Return StringRegExp ($sVar, '^ *([0-9]+\.{0,1}[0-9]*|0x[0-9]+) *$')
EndFunc


Creat0R 15-02-2007 08:54 550174

amel27
Цитата:

текстовый ввод проще контролировать регулярными выражениями
Гинеально! блин, как научиться понимать столь сложные RegExp'ресовые выражения? :biggrin: - я немало часов потратил прочитывая справку на эту тему, но так ничего и не дошло :( ....




Немного в другую сторону...


У меня есть пару вопросов касающихся сети:

1) Функция InetGet при закачке файлов, обходит прокси? или таже UDF-функция для _InetGetSource тоже не работает с прокси?
Мне нужно каким то образом, получать данные с сети (будь то закачка файла или получение исходного кода страницы), вне зависимости от того, подключён ли компьютер к сети через прокси или напрямую. Но желательно каким то хитрым образом обходить прокси, не выключая его (т.е не заметно для юзера) - это вообще возможно?

2) В сети у меня лежит файл с расширением *.js (хотя не очень важно расширение), какое самое быстрое средство для получения с него данных (для его чтения)? неужели _InetGetSource() это самое быстрое(?) средство?

amel27 15-02-2007 12:13 550286

Creat0R
Цитата:

желательно каким то хитрым образом обходить прокси, не выключая его
если откроешь исходник _InetGetSource(), то увидишь вызов функции API-функции InternetOpen из библиотеки wininet.dll, так вот второй параметр (после имени инициатора) отвечает за тип подключения (в функции жестко пробит 0), возможные параметры:
Цитата:

0 - INTERNET_OPEN_TYPE_PRECONFIG - Запрашивает прокси или прямую конфигурацию из реестра.
1 - INTERNET_OPEN_TYPE_DIRECT - Разрешает имена всех хостов локально.
3 - INTERNET_OPEN_TYPE_PROXY - Направляет запрос прокси-серверу, в случае если не предоставлен лист обходов прокси-серверов и имени прокси-сервера нет списке прокси-серверов, которые можно обойти. В этом случае функция использует INTERNET_OPEN_TYPE_DIRECT.
4 - INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY - Запрашивает проки или прямую конфигурацию из реестра и предотвращает использование стартовых Microsoft JScript или Internet Setup (INS) файлов.

Diamond 15-02-2007 16:05 550443

amel27
Цитата:

текстовый ввод проще контролировать регулярными выражениями
Или функция не работает только у меня, или я неправильно понял её предназначение. При любом раскладе возвращает 0. Почему так?

amel27 16-02-2007 01:53 550637

Diamond
Обнови версию AutoIT - это новая фича, еще не устаканилась... :)

Creat0R 16-02-2007 18:47 550976

amel27
Цитата:

возможные параметры
Спасибо. Я только не совсем понимаю какой из них мне нужен (склоняюсь к INTERNET_OPEN_TYPE_DIRECT, но не уверен), и как быть с InetGet()? может есть такая же самодельная функция с подобным выходом в сеть как и у _InetGetSource()?

amel27 17-02-2007 10:13 551503

Creat0R
Цитата:

склоняюсь к INTERNET_OPEN_TYPE_DIRECT
правильно склоняешься :)
Цитата:

может есть такая же самодельная функция с подобным выходом в сеть как и у _InetGetSource()?
готовой чего-то не видать.... а все штатные очевидно используют настройки профиля. Как временный вариант могу предложить сугубо админский подход - запускать скрипт из-под другого узера, у которого в профиле отключен прокси (через RunAsSet)

amel27 17-02-2007 10:29 551505

Creat0R
Уф, добил таки самопальный _FileSelectFolder, только есть два замечания:
1. Внимание! В параметре $root передается код папки (CSIDL), но ни в коем случае не путь к ней!
2. Функция не поддерживает параметр каталога по умолчанию ("initial dir")... хотя теоретически эту фичу можно реализовать через GUICtrlSendMsg (), т.к. окно выбора может принимать сообщения пред-селекта и установки текста статус-бара
Код:

Func _FileSelectFolder ($title, $root = 0, $flags = 0, $hwnd = 0)
    Local $ret, $pidl, $res = ''
    ; Создание структур данных
    Local $ubi = DllStructCreate ("hwnd;ptr;ptr;ptr;int;ptr;ptr;int") ; управляющая структура BROWSEINFO
    Local $utl = DllStructCreate ("char[512],char") ; заголовок окна
    Local $urs = DllStructCreate ("char[260]") ; буфер для возвращаемого пути (длиной MAX_PATH)
    Local $ulf = BitOR (BitShift(BitAnd ($flags,1),-9), _ ; 1: не позволять создавать новые каталоги
        BitShift(BitAnd ($flags,2),-5), _ ; 2: использовать новый стиль диалога
        BitShift(BitAnd ($flags,4),-2)) ; 4: включить cтроку редактирования
    ; Заполнение структур данных
    DllStructSetData ($utl, 1, $title)
    DllStructSetData ($ubi, 1, $hwnd)
    DllStructSetData ($ubi, 3, DllStructGetPtr($urs))
    DllStructSetData ($ubi, 4, DllStructGetPtr($utl))
    DllStructSetData ($ubi, 5, $ulf)
    $ret = DllCall ("shell32.dll", "ptr", "SHGetSpecialFolderLocation", _
        "int", 0 , _
        "int", $root , _
        "ptr", DllStructGetPtr($ubi, 2))
    If $ret[0] Then Return $res
    ; Открытие окна выбора каталога
    $pidl = DllCall ("shell32.dll", "ptr", "SHBrowseForFolder", "ptr", DllStructGetPtr ($ubi))
    If $pidl[0] Then
        $ret = DllCall ("shell32.dll", "int", "SHGetPathFromIDList", _
            "ptr", $pidl[0], _
            "ptr", DllStructGetPtr ($urs))
        If $ret[0] Then $res = DllStructGetData ($urs, 1)
        DllCall ("ole32.dll", "int", "CoTaskMemFree", "ptr", $pidl[0]) ; чистим за собой
    EndIf
    DllCall ("ole32.dll", "int", "CoTaskMemFree", "ptr", DllStructGetData ($ubi, 2))
    Return $res ; Вывод результата
EndFunc


Diamond 17-02-2007 19:45 551733

amel27
Цитата:

Обнови версию AutoIT - это новая фича, еще не устаканилась
Дело оказалось не в версии, видимо, код неправильно скопировался (почему-то полностью отсутствовали символы *, | и \) :blush: Наверное, когда копировал код с форума, страница не до конца загрузилась...
Приношу свои извинения. :)

i_mihal 17-02-2007 22:50 551796

Mihal> Можно ли с помощью AutoIt проделать такую операцию?
Mihal> То есть "взять некий WAV-файл мышкой" и "кинуть его на окошко этой проги"

amel27> обычно перетаскивание можно заменить на копировать/вставить через буфер обмена...

в этой проге (yamaha'вская wscma) нет "вставить" к сожалению.

Creat0R 18-02-2007 01:11 551850

amel27
Цитата:

добил таки самопальный _FileSelectFolder
:yahoo: Огромное челевечное спасибо!!!

Цитата:

Функция не поддерживает параметр каталога по умолчанию ("initial dir")...
Жалко, один из самых важных параметров этой функции...

Цитата:

хотя теоретически эту фичу можно реализовать через GUICtrlSendMsg ()
Хм... я пробовал, но что то не получается :cry: , во-первых я не очень понимаю как её использовать в данном случае, а во-вторых на момент вызова самой функции (_FileSelectFolder) скрипт как бы останавливается, и послать что либо просто невозможно... может нужно в самой функции где то ставить посылание параметров, но я так и не понял где.

Но всё же ещё раз огромное спасибо за эту долгожданную функцию :)

P.S
На офф форуме кстати, тоже вроде с нетерпением её ожидают ;)

amel27 18-02-2007 07:23 551884

Creat0R
Цитата:

я не очень понимаю как её использовать в данном случае
Подобные фокусы обычно реализуются через CallBack-функции для окон, но к сожалению пока AutoIT позволяет их регистрировать только для лист-контролов (GUICtrlRegisterListViewSort). По сути требуется лишь узнать точку входа AutoIT-функции и передать этот указатель как параметр.... но пока ничего кроме создания "фиктивного" лист-контрола ничего не приходит в голову, а это имхо из разряда извращений :)

FYI: "по горячему" немного оптимизировал код

Creat0R 18-02-2007 09:31 551898

amel27
Цитата:

кроме создания "фиктивного" лист-контрола ничего не приходит в голову, а это имхо из разряда извращений
Это тот самый лист котроль над которым я извращался тут? :biggrin: (пост номер 694).

Немного поизвращался в другом направлении, и сделал нужные для себя функции связанные с массивами, но подумал может кому то ещё пригодятся :shuffle: (комментов нет, но думаю запустив примеры всё довольно быстро станет ясно):

Код:

#include <Array.au3>

Dim $Arr1[4]
$Arr1[0] = UBound($Arr1) - 1
$Arr1[1] = "Hello"
$Arr1[2] = "My"
$Arr1[3] = "Friend!"

Dim $Arr2[4]
$Arr2[0] = UBound($Arr2) - 1
$Arr2[1] = "AutoIt"
$Arr2[2] = "Is"
$Arr2[3] = "The best!"

_ArrayDisplay($Arr1, "Display the first array")
_ArrayDisplay($Arr2, "Display the second array")

_ArrayJoin($Arr1, $Arr2, 1)

_ArrayDisplay($Arr1, "Demo of _ArrayJoin() function")

_ArrayClone($Arr1, 2)

_ArrayDisplay($Arr1, "Demo of _ArrayClone() function")

_ArrayDeleteClones($Arr1)

_ArrayDisplay($Arr1, "Demo of _ArrayDeleteClones() function")

_ArrayClear($Arr1)

_ArrayDisplay($Arr1, "Demo of _ArrayClean() function")

Func _ArrayJoin(ByRef $Array1, ByRef $Array2, $JoinedArray=1)
    If IsArray($Array1) And IsArray($Array2) Then
        If $JoinedArray = 1 Then
            For $iArr = 1 To UBound($Array2) - 1
                ReDim $Array1[UBound($Array1) + 1]
                $Array1[UBound($Array1) - 1] = $Array2[$iArr]
            Next
            $Array1[0] = UBound($Array1) - 1
        Else
            For $iArr = 1 To UBound($Array1) - 1
                ReDim $Array2[UBound($Array2) + 1]
                $Array2[UBound($Array2) - 1] = $Array1[$iArr]
            Next
            $Array2[0] = UBound($Array2) - 1
        EndIf
        SetError(0)
    Else
        SetError(1)
        Return -1
    EndIf
EndFunc

Func _ArrayClone(ByRef $Array, $Repeat=1)
    If IsArray($Array) Then
        Local $TempArr = $Array
        For $iR = 1 To $Repeat
            For $iArr = 1 To UBound($TempArr) - 1
                ReDim $Array[UBound($Array) + 1]
                $Array[UBound($Array) - 1] = $TempArr[$iArr]
            Next
            $Array[0] = UBound($Array) - 1
        Next
        SetError(0)
        Return 1
    Else
        SetError(1)
        Return -1
    EndIf
EndFunc

Func _ArrayDeleteClones(ByRef $Array)
    If IsArray($Array) Then
        Local $StringWithDelValue
        For $iD = 1 To UBound($Array) - 1
            $FindInArr = _ArraySearch($Array, $Array[$iD])
            If $FindInArr <> $iD Then $StringWithDelValue &= $Array[$iD] & "|"
        Next
        If $StringWithDelValue <> "" Then
            $TempArrOfIndexesString = StringSplit($StringWithDelValue, "|")
            If IsArray($TempArrOfIndexesString) Then
                For $iI = 1 To $TempArrOfIndexesString[0]
                    $CurrentIndexToDel = _ArraySearch($Array, $TempArrOfIndexesString[$iI])
                    If $CurrentIndexToDel = -1 Then ExitLoop
                    _ArrayDelete($Array, $CurrentIndexToDel)
                Next
            Else
                _ArrayDelete($Array, StringReplace($StringWithDelValue, "|", ""))
            EndIf
            $Array[0] = UBound($Array) - 1
            SetError(0)
            Return 1
        Else
            SetError(0)
            Return 0
        EndIf
    Else
        SetError(1)
        Return -1
    EndIf
EndFunc

Func _ArrayClear(ByRef $Array)
    If IsArray($Array) Then
        For $iArr = 1 To UBound($Array) - 1
            _ArrayDelete($Array, $iArr)
        Next
        $Array[0] = 0
        SetError(0)
        Return 1
    Else
        SetError(1)
        Return -1
    EndIf
EndFunc


Creat0R 18-02-2007 22:57 552118

Ещё функция для работы с массивом - _ArrayReplace() - Кстати, предыдущие и эта функция, работают только с одномерным (с одним элементом) массивом:

Код:

Func _ArrayReplace(ByRef $Array, $ValueToReplace, $NewValue)
    Local $IsReplaced = 0
    If IsArray($Array) Then
        For $iR = 1 To UBound($Array) - 1
            $Array[$iR] = StringReplace($Array[$iR], $ValueToReplace, $NewValue)
            If StringInStr($Array[$iR], $ValueToReplace) Then $IsReplaced = 1
        Next
        SetError(0)
        If $IsReplaced = 1 Then
            Return 1
        Else
            Return 0
        EndIf
    Else
        SetError(1)
        Return -1
    EndIf
EndFunc

Эта функция позволяет произвести замену значении в массиве.

P.S
А как определять является ли массив двухмерным, или нет?

Creat0R 19-02-2007 02:14 552171

Всем всем!

Кому интересна фича отката скрытых папок и расширении файлов, посмотрите на эти два скрипта:

Для отката расширении файлов:

Код:

$RegKey = "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced"
If RegRead($RegKey, "HideFileExt") Then
    RegWrite($RegKey, "HideFileExt", "REG_DWORD", 0)
Else
    RegWrite($RegKey, "HideFileExt", "REG_DWORD", 1)
EndIf

UpdateExplorer()

Func UpdateExplorer()
    $WinExpListArr = _ExplWinGetList()
    If IsArray($WinExpListArr) Then
        For $iWin = 1 To $WinExpListArr[0]
            $GetWinState = WinGetState($WinExpListArr[$iWin])
            $Hwnd = WinGetHandle($WinExpListArr[$iWin])
            DllCall("user32.dll", "long", "SendMessage", "hwnd", $hWnd, "int", 0x111, "int", 28931, "int", 0)
        Next
    EndIf

        Opt("WinTitleMatchMode", 4)
    $Hwnd = WinGetHandle("classname=Progman")
    DllCall("user32.dll", "long", "SendMessage", "hwnd", $hWnd, "int", 0x111, "int", 28931, "int", 0)
EndFunc

Func _ExplWinGetList()
    Opt("WinTitleMatchMode", 4)
    $WinList = WinList("classname=CabinetWClass")
    If IsArray($WinList) Then
        Local $WinListArr[$WinList[0][0]+1]
        For $iW = 1 To $WinList[0][0]
            $WinListArr[$iW] = $WinList[$iW][0]
        Next
        $WinListArr[0] = $WinList[0][0]
        Return $WinListArr
    Else
        Return ""
    EndIf
EndFunc


Для отката скрытых папок и файлов:

Код:

$RegKey = "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced"
If RegRead($RegKey, "Hidden") = 1 Then
    RegWrite($RegKey, "Hidden", "REG_DWORD", 2)
Else
    RegWrite($RegKey, "Hidden", "REG_DWORD", 1)
EndIf

UpdateExplorer()

Func UpdateExplorer()
    $WinExpListArr = _ExplWinGetList()
    If IsArray($WinExpListArr) Then
        For $iWin = 1 To $WinExpListArr[0]
            $GetWinState = WinGetState($WinExpListArr[$iWin])
            $Hwnd = WinGetHandle($WinExpListArr[$iWin])
            DllCall("user32.dll", "long", "SendMessage", "hwnd", $hWnd, "int", 0x111, "int", 28931, "int", 0)
        Next
    EndIf

        Opt("WinTitleMatchMode", 4)
    $Hwnd = WinGetHandle("classname=Progman")
    DllCall("user32.dll", "long", "SendMessage", "hwnd", $hWnd, "int", 0x111, "int", 28931, "int", 0)
EndFunc

Func _ExplWinGetList()
    Opt("WinTitleMatchMode", 4)
    $WinList = WinList("classname=CabinetWClass")
    If IsArray($WinList) Then
        Local $WinListArr[$WinList[0][0]+1]
        For $iW = 1 To $WinList[0][0]
            $WinListArr[$iW] = $WinList[$iW][0]
        Next
        $WinListArr[0] = $WinList[0][0]
        Return $WinListArr
    Else
        Return ""
    EndIf
EndFunc

Процесс проходит практический незаметно, все открытые окна обновляются, и в конце также обновляется рабочий стол!
В сети можно найте несколько подобных расширении, но я ещё не видел подобное, чтобы весь процесс проходил незаметно.

Вот если бы ещё найти способ как внедрить пункт в контекстное меню папки, по нажатию которого и запускался бы этот скрипт (в закомпилированном виде), то это было бы вообще шикарно!

amel27 19-02-2007 05:40 552188

Creat0R
Цитата:

сделал нужные для себя функции связанные с массивами
несколько замечаний... и свой вариант. ;)
- во избежание проблем индексные переменные в функциях нужно объявлять как Local;
- пустые массивы (счетчик со значением 0) нужно обрабатывать отдельно перед входом в цикл;
- учитывая, что счет индекса идет всегда с единицы, одной проверки IsArray() явно недостаточно. На самом деле все приведенные функции работают с пользовательским типом данных - "массив со счетчиком"… вот на принадлежность этому типу и надо проверять. Более того, при наличии уверенности в корректности массива можно обойтись без лишнего пользования UBound() - достаточно взять значение по индексу 0.
- параметр $JoinedArray в функции _ArrayJoin() имхо избыточный, при нужде поменять параметры проблемы не составит:
Код:

If $JoinedArray Then
    _ArrayJoin ($arr1, $arr2)
Else
    _ArrayJoin ($arr2, $arr1)
EndIf

- зачем нужна _ArrayClear(), если можно обычным оператором присвоения переинициализировать массив?
- в функции _ArrayReplace две строки перепутаны местами.
Код:

#include <Array.au3>

Func _IsCountArray (ByRef $arr)
    If IsArray ($arr) Then
        If $arr[0] = UBound ($arr)-1 Then Return True
    EndIf
    Return False
EndFunc

Func _ArrayJoin (ByRef $arrFrom, ByRef $arrTo)
    If _IsCountArray($arrFrom) And _IsCountArray($arrTo) Then
        Local $i, $n=0
        If $arrFrom[0] =0 Then Return 0
        For $i=1 To $arrFrom[0]
            $n+=_ArrayAdd ($arrTo, $arrFrom [$i])
        Next
        $arrTo[0]+=$n
        Return $n
    EndIf
    SetError (1)
    Return -1
EndFunc

Func _ArrayClone (ByRef $arr, $count = 1)
    Local $i, $n=0, $tmp = $arr
    If _IsCountArray ($arr) Then
        For $i=1 To $count
            $n+=_ArrayJoin ($tmp, $arr)
        Next
        Return $n
    EndIf
    SetError(1)
    Return -1
EndFunc

Func _ArrayDeleteClones (ByRef $arr, $iCaseSense = 0)
    If _IsCountArray ($arr) Then
        Local $i, $n=0, $iClone
        If $arr[0] <2 Then Return 0
        For $i=$arr[0] To 2 Step -1
            $iClone = _ArraySearch ($arr, $arr[$i], 1, $i-1, $iCaseSense)
            If $iClone >0 Then
                $n+=_ArrayDelete ($arr, $iClone)
                $i-=1
            EndIf
        Next
        $arr[0] = UBound($arr) -1
        Return $n
    EndIf
    SetError(1)
    Return -1
EndFunc

Func _ArrayReplace (ByRef $Array, $ValueToReplace, $NewValue)
    Local $i, $n=0
    If _IsCountArray($Array) And IsString ($ValueToReplace) Then
        For $i = 1 To $Array[0]
            If StringInStr ($Array[$i], $ValueToReplace) Then
                $Array[$i] = StringReplace ($Array[$i], $ValueToReplace, $NewValue)
                $n+=1
            EndIf
        Next
        Return $n
    EndIf
    SetError(1)
    Return -1
EndFunc

Цитата:

А как определять является ли массив двухмерным, или нет?
UBound ($Array,0) вернет размерность массива

amel27 19-02-2007 07:28 552207

Creat0R
Цитата:

Кому интересна фича
не стоит приводить код одной функции дважды, кстати я не вижу разницы между этими двумя примерами... ;)
Цитата:

Вот если бы ещё найти способ как внедрить пункт в контекстное меню папки
это сюда: http://forum.oszone.net/showthread.php?t=62252

Creat0R 19-02-2007 10:16 552278

amel27
Цитата:

несколько замечаний
Спасибо!

Цитата:

во избежание проблем индексные переменные в функциях нужно объявлять как Local
Ну у меня вроде бы все так обьявляется.

Цитата:

достаточно взять значение по индексу 0
Я знаю, но мне казалось что Ubound надёжнее, и к тому же иногда в индексе 0 может ничего и не быть (не формальный массив :) ).

Цитата:

зачем нужна _ArrayClear(), если можно обычным оператором присвоения переинициализировать массив?
А вот тут поподробнее плиз, я что то не совсем понял, как это реализовать на практике? (нужно “опусташить” массив).

Цитата:

в функции _ArrayReplace две строки перепутаны местами.
Нет, я так специально сделал, ведь если нечего заменять, то ничего не будет тронуто, а проверка на наличие значения только лишь для того чтобы вернуть из функции статус о том, произошла ли замена - но твой пример куда продвинутый, в нём также подсчитывается количество замен!

Цитата:

UBound ($Array,0) вернет размерность массива
О! Спасибо, это я и хотел узнать.

Цитата:

не вижу разницы между этими двумя примерами
Упс! :shuffle: - перепутал при вставке из разукрашалки :biggrin: - поправил.

Цитата:

это сюда:
Уау! спасибо, будем смотреть.

P.S
Думаю мне можно простить ошибки которые я допустил в функциях, т.к совсем недавно я вовсе не мог работать с массивами (для меня это было что то страшное и неопознанное), и то что я осмелился написать сам нужные мне функции, это что то - и благодаря таким замечаням как твои, думаю я вскоре освою их основы :UP: .

amel27 19-02-2007 11:44 552342

Creat0R
Цитата:

Ну у меня вроде бы все так обьявляется
возьми к примеру $iR - она используется в цикле без предварительного объявления
Цитата:

но мне казалось что Ubound надёжнее
не спорю - надежней, но еще надежней ужесточить проверку на входе... :)
Цитата:

А вот тут поподробнее плиз, я что то не совсем понял, как это реализовать на практике? (нужно “опусташить” массив)
легко... :) скажем, для случая массива со счетчиком:
Код:

Func _ArrayClear (ByRef $arr)
    Dim $arr[1] = [0]
EndFunc

...теперь вопрос: нужно ли для этого создавать отдельную функцию? ;)

Цитата:

думаю я вскоре освою их основы
не сомневаюсь ;)

Creat0R 19-02-2007 21:25 552606

amel27
Цитата:

возьми к примеру $iR - она используется в цикле без предварительного объявления
Интересно, а я об этом не подумал, почему то считал что испольование переменной в цикле For (в начале) не объявляет её, а просто использует для конкретного цикла, но теперь если вдуматься, то далее после цикла можно будет использовать эту же переменную (и значение она будет иметь тоже что и значение поставленное после To - если конечно не прервать цикл), так что спасибо за подсказку, буду это учитывать :)

Цитата:

легко...
Действительнно легко! Спасибо!

Цитата:

нужно ли для этого создавать отдельную функцию?
Ну только разве что для проверки на массивность и возврата кода ошибочности (если к примеру пытаемся опусташить не массив) :)

Creat0R 20-02-2007 04:28 552703

amel27
На основе твоего примера для определения цифрового значения, я сделал функцию для обнажения всех НЕ числовых значении, т.е в результате возвращается значение содержащее только цифры:

Код:

Func _StringStripNotNumber($String, $RetType=0)
    If StringLen($String) < 2 Then
        If StringRegExp($String, '^ *([0-9]+\.{0,1}[0-9]*|0x[0-9]+) *$') Then Return $String
        Return ""
    EndIf
    Local $i, $RetNumber, $AllStringArr = StringSplit($String, "")
    For $i = 1 To $AllStringArr[0]
        If StringRegExp($AllStringArr[$i], '^ *([0-9]+\.{0,1}[0-9]*|0x[0-9]+) *$') Then $RetNumber &= $AllStringArr[$i]
    Next
    If $RetType = 1 And StringLen($RetNumber) >= 1 Then
        $AllStringArr = StringSplit($RetNumber, "")
        Return $AllStringArr
    EndIf
    Return $RetNumber
EndFunc

Если в качестве второго параметра поставить 1, то функция вернёт массив с найденными цифрами, если оставить по умолчанию (0), то возвращается обычная переменная с найденными цифрами.

Может у кого то есть более оригинальное название для этой функции? :shuffle: мне если честно ничего другого в голову не пришло.




А как можно получить весь путь до файла, за исключением самого имени файла?
Т.е к примеру, имеем путь C:\test\test.zip - и нужно получить только путь C:\test - хотел бы узнать как это можно осуществить исключительно регулярными вырожениями....

Я до сих пор обходился так:

Код:

$Path = "C:\test\test.zip"
$Path = StringTrimRight($Path, StringLen(StringRegExpReplace($Path, "^.*\\", ""))+1)

Но может есть путь по короче? я имею в виду так чтобы одной функцией StringRegExpReplace получить этот же эффект.

Creat0R 20-02-2007 06:02 552710

amel27
Извини что достаю тебя уже третьий пост подряд, но я нашел небольшой недочёт в функции _FileSelectFolder() - там заголовок (первый параметр $title) не отображается :shuffle:

amel27 20-02-2007 08:38 552738

Creat0R
Цитата:

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

Func _StringStripNotNumber ($String, $RetType=0)
    $String = StringRegExpReplace ($String,'[^0-9]','') ; Удаляем все не-цифры
    If $RetType = 1 Then Return StringSplit ($String, "")
    Return $String
EndFunc

Цитата:

А как можно получить весь путь до файла, за исключением самого имени файла?
например так:
Код:

StringRegExpReplace ($file, '[^\\]*$', '')

amel27 20-02-2007 08:54 552744

Creat0R
Цитата:

нашел небольшой недочёт в функции _FileSelectFolder() - там заголовок (первый параметр $title) не отображается
спасибо, исправил... забыл я про него совсем :)

Creat0R 20-02-2007 11:27 552819

amel27
Цитата:

честно говоря не очень представляю назначение этой функции
Я позже выложу скрипт примера (там скрипт предназначен для выбора файлов (кстати обе твои функции используются), и затем их архивирования, весь процесс архивирования считывается через StdOutRead() и из полученного значения нужно получать только цифры, т.к их нужно использовать для прогресс бара ;) ).

Цитата:

можно и так:
Уау! в три раза короче, и в 10 раз правильнее! спасибо!

Цитата:

например так:
Класс! спасибо (см. ниже, выложил свою версию для функции _PathSplit())

Цитата:

спасибо, исправил... забыл я про него совсем
Да нет, это тебе спасибо за эту функцию, я уже успешно её имплонтировал в один из своих скриптов (тот что для архивирования) ;)




Моя версия на функцию деления пути используя регулярные выражения:

Код:

#include <Array.au3>
$Path = "c:\my test\path\test.zip"

$PathArr = _PathSplitByRegExp($Path)

_ArrayDisplay($PathArr, "Demo of _PathSplitByRegExp()")

Func _PathSplitByRegExp($sPath, $pDelim="\")
    Local $RetArray[8], $iArr
    $pDelim = "\" & $pDelim
    $RetArray[0] = $sPath
    $RetArray[1] = StringRegExpReplace($sPath,  $pDelim & '.*', $pDelim) ;Drive letter
    $RetArray[2] = StringRegExpReplace($sPath, $pDelim & '[^' & $pDelim & ']*$', '') ;Path without FileName and extension
    $RetArray[3] = StringRegExpReplace($sPath, '\.[^.]*$', '') ;Full path without File Extension
      $RetArray[4] = StringRegExpReplace($sPath, '^.' & $pDelim & '*:', '') ;Full path without drive letter
    $RetArray[5] = StringRegExpReplace($sPath, '^.*' & $pDelim, '') ;FileName and extension
    $RetArray[6] = StringRegExpReplace(StringRegExpReplace($sPath, '^.*' & $pDelim, ''), '\.[^.]*$', '') ;Just Filename
    $RetArray[7] = StringRegExpReplace($sPath, '^.*\.', '') ;Just Extension of a file
    ;Проверяем все значения (элементы массива), если в каком то из них небыла произведена замена, то присваеваем ему пустое значение ("")
    For $iArr = 1 To 7
        If $RetArray[$iArr] = $sPath Then $RetArray[$iArr] = ""
    Next
    Return $RetArray
EndFunc


amel27 20-02-2007 12:59 552873

Creat0R
Цитата:

Моя версия на функцию деления пути используя регулярные выражения
угу, полезное упражнение, кстати в 4-м есть неточность.... и зачем дважды искать одно и тоже?.. (см. [6]) еще два момента:

- какие еще ты предполагал разделители кроме '\' ?... имхо часто перегружаешь функции избыточностью, да и читаются они так сложней - легко ошибку пропустить... знаком с "бритвой Оккама"? ;)
- зачем последний цикл?.. какие случаи имелись ввиду?... или опять на всякий случай? ;)

Creat0R 20-02-2007 15:33 552938

amel27
Цитата:

в 4-м есть неточность
Ты про то что в начале слешь остаётся? ну это так задуманно, но хотя да, нужно бы его убрать...

Цитата:

зачем дважды искать одно и тоже?.. (см. [6])
Ок, намёк понял ;) (см. ниже поправлены вариант)...

Цитата:

какие еще ты предполагал разделители кроме '\' ?
Ну вообще то я считал что символ \ “позволяет” считать последующий после этого символ дословно, и если как разделитель будет задан один из служебных (для StringRegExpReplace()) символов, то это позволит не считать символ как служебны - это не так?
Просто путь может быть и как ссылка, тогда разделитель будет другой.

Цитата:

знаком с "бритвой Оккама"?
Неа :no:

Цитата:

зачем последний цикл?
Чтобы проверить весь массив на пренадлежность НЕ замены, т.е если какой то элемент массива ровняется исходному пути, то я предполагаю что замена не осуществлялась, поэтому нужно опусташить этот элемент (это по мативам оригинальной функции _PathSplit() ;) ).

Соответсвенно замечаниям немного переделал функцию :) :

Код:

Func _PathSplitByRegExp($sPath, $pDelim="\")
    Local $RetArray[8], $iArr
    $pDelim = "\" & $pDelim
    $RetArray[0] = $sPath
    $RetArray[1] = StringRegExpReplace($sPath,  $pDelim & '.*', $pDelim) ;Drive letter
    $RetArray[2] = StringRegExpReplace($sPath, $pDelim & '[^' & $pDelim & ']*$', '') ;Path without FileName and extension
    $RetArray[3] = StringRegExpReplace($sPath, '\.[^.]*$', '') ;Full path without File Extension
      $RetArray[4] = StringRegExpReplace($sPath, '^.' & $pDelim & '*:.', '') ;Full path without drive letter
    $RetArray[5] = StringRegExpReplace($sPath, '^.*' & $pDelim, '') ;FileName and extension
    $RetArray[6] = StringRegExpReplace($RetArray[5], '\.[^.]*$', '') ;Just Filename
    $RetArray[7] = StringRegExpReplace($sPath, '^.*\.', '') ;Just Extension of a file
    ;Проверяем все значения (элементы массива), если в каком то из них небыла произведена замена, то присваеваем ему пустое значение ("")
    For $iArr = 1 To 7
        If $RetArray[$iArr] = $sPath Then $RetArray[$iArr] = ""
    Next
    Return $RetArray
EndFunc


Creat0R 20-02-2007 23:35 553157

Вот ссылка на пост в котором я оставил пример использования функции _StringStripNotNumber() - этот пример по сути предназначен для демонстрации чтения данных из консольного окна (при архивировании или расспаковке), вывод этих данных в статус баре, и собственно обнаженные значения до чисел для того чтобы корректно отобразить процесс распаковки/запаковки в прогресс баре.

http://www.autoitscript.com/forum/in...t=0&p=307745&#

P.S
Функцию может переименовать так: _StringStripWords() ?

amel27 21-02-2007 11:45 553332

Creat0R
Цитата:

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

Func _IsUNCPath ($str)
    Return StringRegExp ($str, '^(?i)([A-Z]:|\\)(\\[^\\]+)+$')
EndFunc

Цитата:

Неа
http://ru.wikipedia.org/wiki/%D0%91%...B0%D0%BC%D0%B0 ;)
Цитата:

Чтобы проверить весь массив на пренадлежность НЕ замены, т.е если какой то элемент массива ровняется исходному пути, то я предполагаю что замена не осуществлялась, поэтому нужно опусташить этот элемент (это по мативам оригинальной функции _PathSplit()
ничего такого в исходном _PathSplit нету - если искомый элемент не найден, тогда получится пустая строка... Если разбор ведется правильно, то никаких "хвостов" не дожно оставаться.

Creat0R 21-02-2007 18:00 553563

amel27
Цитата:

на его основе строить разбор - что является служебным символом, а что нет, что идет за чем и прочее
Как я понял эта функция проверяет является ли путь корректным путём, но как можно универсально проверить разделитель? т.е к примеру имеем такой путь - C:|program files|Program|Program.exe, нужно чтобы если как второй параметр задан разделитель |, то путь делился именно используя этот делитель.

Интересно, ну я кажется понял суть, но если смотреть в сторону программирования таким подходом, то тут нужен исключительно немалы опыт (которым обладаешь ты ;) ), имхо.

Цитата:

если искомый элемент не найден, тогда получится пустая строка...
Вот я примерно также и сделал, если не было замены, значит тот элемент в котором небыло замены становится пустым...

Цитата:

Если разбор ведется правильно, то никаких "хвостов" не дожно оставаться.
Ну а если в качестве пути задаётся не разбираемый путь? т.е даже вовсе не путь, а просто любое значение.

Можно последний цикл прописать так (чтобы не было хвостов в виде пустых элементов массива):

Код:

    For $iArr = 7 To 1 Step -1
        If $RetArray[$iArr] = $sPath Or $RetArray[$iArr] = "" Then _ArrayDelete($RetArray, $iArr)
    Next


amel27 22-02-2007 10:39 553781

Creat0R
Цитата:

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

#include <File.au3>
#include <GuiStatusBar.au3>

$sSourceFiles = @MyDocumentsDir & '\*.*'
$sDestinRarFile = @ScriptDir & '\test'

$Gui = GUICreate("Add files to archive: ", 500, 200)
$Progress = GUICtrlCreateProgress(40, 45, 430, 20)
$CancelButton = GUICtrlCreateButton("Cancel", 220, 80)
$ProgressStatus = _GUICtrlStatusBarCreate($Gui, 0, "")
_GUICtrlStatusBarSetSimple($ProgressStatus)
_GUICtrlStatusBarSetText($ProgressStatus, '123')
GUISetState()

$sCMD = 'rar.exe a ' & '"' & $sDestinRarFile & '" "' & $sSourceFiles & '"'
$foo = Run ($sCMD, @ScriptDir, @SW_HIDE, 2)

Dim $arrStatus [2] = ['','0%']
While _StdoutRefresh ($foo)
    $Msg = GUIGetMsg()
    If $Msg=-3 Or $Msg=$CancelButton Then
        ProcessClose($foo)
        Exit
    EndIf
WEnd
Exit

Func _StdoutRefresh ($foo)
    Local $sOut, $aOut, $i
    If StdoutRead ($foo,0,True) Then
        $sOut = StdoutRead ($foo)
        $aOut = StringSplit ($sOut, @CRLF & Chr(0x08))
        For $i=1 To $aOut[0]
            If StringRight ($aOut[$i],1)='%' Then
                $arrStatus[1] = $aOut[$i]
            ElseIf StringLen($aOut[$i]) >0 Then
                $arrStatus[0] = $aOut[$i]
            EndIf
        Next
        WinSetTitle ('Add files to archive','','Add files to archive: ' & $sDestinRarFile & ' (' & $arrStatus[1] & ')')
        GUICtrlSetData($Progress, StringTrimRight($arrStatus[1],1))
        _GUICtrlStatusBarSetText($ProgressStatus, $arrStatus[0],$SB_SIMPLEID)
    EndIf
    Return ProcessExists ($foo)
EndFunc

Цитата:

Ну а если в качестве пути задаётся не разбираемый путь?
тогда зачем его разбирать?... поставить на входе что-нибудь типа _IsStringPath() и не зависеть от случая... :)
Цитата:

тут нужен исключительно немалы опыт
плохая отмазка, а главное вредная... ;) дело не в опыте, а в отношении к результату своего труда

Creat0R 22-02-2007 20:25 554071

amel27

Вот более модифицированный пример архивирования файлов с выводом процесса в гуи (я там использовал новую твою функцию _FileSelectFolder(), а также заметь, я накалякал свою собственную функцию для InputBox() - она позволяет прикреплять InputBox к окну гуи, и также в ней есть всё тоже что и в обычной функции, и даже больше, мне впервые удалось реализовать ограничение на изменение размера гуи :) - т.е установить минимально допустимы размер окна гуи ) :

Код:

#include <GuiStatusBar.au3>
#include <GUIConstants.au3>
#include <Array.au3>

$ArchivatorPath = RegRead("HKEY_CURRENT_USER\Software\7-Zip", "Path") & "\7z.exe"
If Not FileExists($ArchivatorPath) Then
        $RegReadRar = RegRead("HKEY_CLASSES_ROOT\.rar\ShellNew", "FileName")
        $ArchivatorPath = StringReplace($RegReadRar, StringRegExpReplace($RegReadRar, "^.*\\", ""), "rar.exe;")
EndIf
If Not FileExists($ArchivatorPath) Then
        MsgBox(16, "Error!", "Archiving Program was not found" & @CR & @CR & "OK --> EXIT")
        Exit
EndIf

$ArchiveName = "Archive.zip"

$Gui = GUICreate("Add files to archive GUI", 500, 200)

$Progress = GUICtrlCreateProgress(40, 45, 430, 20)
$ProgressStatus = _GUICtrlStatusBarCreate($Gui, 0, "")
_GUICtrlStatusBarSetSimple($ProgressStatus)

$AddButton = GUICtrlCreateButton("Add file(s)/folder...", 200, 80, 110, 20)

$ContextMenu = GUICtrlCreateContextMenu()
$AddFiles = GUICtrlCreateMenuitem("Add files...", $ContextMenu)
$AddFolders = GUICtrlCreateMenuitem("Add folder...", $ContextMenu)

GUISetState()

While 1
        $Msg = GUIGetMsg()
        Switch $Msg
                Case -3
                        Exit
                Case $AddButton
                        ShowMenu($GUI, $AddButton, $ContextMenu)
                Case $AddFiles
                        $OpenFiles = _FileOpenDialog("Choose file(s) to add to archive", "", "All Files (*.*)", 4, "", "", $GUI)
                        If Not @error Then
                                If StringInStr($OpenFiles, "|") Then
                                        $OpenFiles = '"' & StringReplace(StringReplace($OpenFiles, @WorkingDir & "|", ""), '|', '" "') & '"'
                                Else
                                        $OpenFiles = '"' & StringStripCR($OpenFiles) & '"'
                                EndIf
                                $ArchiveNameInput = _InputBox("Archive Name", "Type archive name that files will be added into it:", $ArchiveName, 0, 0, 280, 150, -1, -1, 0, 0, 0, $GUI)
                                If $ArchiveNameInput <> "" Then
                                        $ArchiveNameInput = StringRegExpReplace($ArchiveNameInput, '["?:|/\\*<>]', '_')
                                        $Pid = Run($ArchivatorPath & ' a "' & @WorkingDir & "\" & $ArchiveNameInput & '" ' & $OpenFiles, "", @SW_HIDE, 2)
                                        GUICtrlSetData($AddButton, "Abort")
                                        AddFiles($Pid)
                                EndIf
                        EndIf
                Case $AddFolders
                        $OpenFolder = _FileSelectFolder("Choose directory for add it to archive...", 0, 0, $GUI)
                        If $OpenFolder <> "" Then
                                $ArchiveNameInput = _InputBox("Archive Name", "Type archive name that files will be added into it:", $ArchiveName, 0, 0, 280, 150, -1, -1, 0, 0, 0, $GUI)
                                If $ArchiveNameInput <> "" Then
                                        $ArchiveNameInput = StringRegExpReplace($ArchiveNameInput, '["?:|/\\*<>]', '_')
                                        $Pid = Run($ArchivatorPath & ' a "' & StringTrimRight($OpenFolder, StringLen(StringRegExpReplace($OpenFolder, "^.*\\", ""))) & $ArchiveNameInput & '" "' & $OpenFolder & '"', "", @SW_HIDE, 2)
                                        GUICtrlSetData($AddButton, "Abort")
                                        AddFiles($Pid)
                                EndIf
                        EndIf
        EndSwitch
WEnd

Func AddFiles($Pid)
        While ProcessExists($Pid)
                $Msg = GUIGetMsg()
                $ReadLine = StdoutRead($Pid, 0, True)
                _GUICtrlStatusBarSetText($ProgressStatus, "Add files process... " & $ReadLine, 255)
                GUICtrlSetData($Progress, _StringStripWords($ReadLine))
                $LastRead = $ReadLine
                If $Msg = $AddButton Then ExitLoop
        WEnd
        If $Msg = $AddButton Then
                ProcessClose($Pid)
                GUICtrlSetData($Progress, 0)
        EndIf
        GUICtrlSetData($AddButton, "Add file(s)/folder...")
        $DoneMsg = "Done!"
        If StringInStr($LastRead, "Warning") Or StringInStr($LastRead, "Error") Then
                If StringInStr($LastRead, "Warning") Then $ErrPos = StringInStr($LastRead, "Warning")
                If StringInStr($LastRead, "Error") Then $ErrPos = StringInStr($LastRead, "Error")
                $DoneMsg = "Done! (" & StringTrimLeft($LastRead, $ErrPos-2) & ")"
        EndIf
        _GUICtrlStatusBarSetText($ProgressStatus, $DoneMsg, 255)
EndFunc

Func _StringStripWords($String, $RetType=0)
    $String = StringRegExpReplace($String,'[^0-9]','') ; Удаляем все не-цифры
    If $RetType = 1 Then Return StringSplit($String, "")
    Return $String
EndFunc

Func _FileOpenDialog ($sTitle, $sInitDir, $sFilter = 'All (*.*)', $iOpt = 0, $sDefaultFile = "", $sDefaultExt = "", $mainGUI = 0)
    Local $iFileLen = 65536 ; Max chars in returned string
    ; API flags prepare
    Local $iFlag = BitOR ( _
        BitShift (BitAND ($iOpt, 1),-12), BitShift (BitAND ($iOpt, 2),-10), BitShift (BitAND ($iOpt, 4),-7 ), _
        BitShift (BitAND ($iOpt, 8),-10), BitShift (BitAND ($iOpt, 4),-17) )
    ; Filter string to array convertion
    Local $asFLines = StringSplit ( $sFilter, '|'), $asFilter [$asFLines [0] *2+1]
    Local $i, $iStart, $iFinal, $suFilter = ''
    $asFilter [0] = $asFLines [0] *2
    For $i=1 To $asFLines [0]
        $iStart = StringInStr ($asFLines [$i], '(', 0, 1)
        $iFinal = StringInStr ($asFLines [$i], ')', 0,-1)
        $asFilter [$i*2-1] = StringStripWS (StringLeft ($asFLines [$i], $iStart-1), 3)
        $asFilter [$i*2] = StringStripWS (StringTrimRight (StringTrimLeft ($asFLines [$i], $iStart), StringLen ($asFLines [$i]) -$iFinal+1), 3)
        $suFilter = $suFilter & 'byte[' & StringLen ($asFilter [$i*2-1])+1 & '];byte[' & StringLen ($asFilter [$i*2])+1 & '];'
    Next
    ; Create API structures
    Local $uOFN = DllStructCreate ('dword;int;int;ptr;ptr;dword;dword;ptr;dword' & _
        ';ptr;int;ptr;ptr;dword;short;short;ptr;ptr;ptr;ptr;ptr;dword;dword' )
    Local $usTitle  = DllStructCreate ('byte[' & StringLen ($sTitle) +1 & ']')
    Local $usInitDir= DllStructCreate ('byte[' & StringLen ($sInitDir) +1 & ']')
    Local $usFilter = DllStructCreate ($suFilter & 'byte')
    Local $usFile  = DllStructCreate ('byte[' & $iFileLen & ']')
    Local $usExtn  = DllStructCreate ('byte[' & StringLen ($sDefaultExt) +1 & ']')
    For $i=1 To $asFilter [0]
        DllStructSetData ($usFilter, $i, $asFilter [$i])
    Next
    ; Set Data of API structures
    DllStructSetData ($usTitle, 1, $sTitle)
    DllStructSetData ($usInitDir, 1, $sInitDir)
    DllStructSetData ($usFile, 1, $sDefaultFile)
    DllStructSetData ($usExtn, 1, $sDefaultExt)
    DllStructSetData ($uOFN,  1, DllStructGetSize($uOFN))
    DllStructSetData ($uOFN,  2, $mainGUI)
    DllStructSetData ($uOFN,  4, DllStructGetPtr ($usFilter))
    DllStructSetData ($uOFN,  7, 1)
    DllStructSetData ($uOFN,  8, DllStructGetPtr ($usFile))
    DllStructSetData ($uOFN,  9, $iFileLen)
    DllStructSetData ($uOFN, 12, DllStructGetPtr ($usInitDir))
    DllStructSetData ($uOFN, 13, DllStructGetPtr ($usTitle))
    DllStructSetData ($uOFN, 14, $iFlag)
    DllStructSetData ($uOFN, 17, DllStructGetPtr ($usExtn))
    DllStructSetData ($uOFN, 23, BitShift (BitAND ($iOpt, 32), 5))
    ; Call API function
    $ret = DllCall ('comdlg32.dll', 'int', 'GetOpenFileName', _
            'ptr', DllStructGetPtr ($uOFN) )
    If $ret [0] Then
        If BitAND ($iOpt, 4) Then
            $i = 1
            While 1
                If DllStructGetData ($usFile, 1, $i) =0 Then
                    If DllStructGetData ($usFile, 1, $i+1) Then
                        DllStructSetData ($usFile, 1, 124, $i)
                    Else
                        ExitLoop
                    EndIf
                EndIf
                $i += 1
            Wend
        EndIf
        Return DllStructGetData ($usFile, 1)
    Else
        SetError (1)
        Return ""
    EndIf
EndFunc

Func _FileSelectFolder ($title, $root = 0, $flags = 0, $hwnd = 0)
    Local $ret, $pidl, $res = ''
    ; Создание структур данных
    Local $ubi = DllStructCreate ("hwnd;ptr;ptr;ptr;int;ptr;ptr;int") ; управляющая структура BROWSEINFO
    Local $utl = DllStructCreate ("char[512],char") ; заголовок окна
    Local $urs = DllStructCreate ("char[260]") ; буфер для возвращаемого пути (длиной MAX_PATH)
    Local $ulf = BitOR (BitShift(BitAnd ($flags,1),-9), _ ; 1: не позволять создавать новые каталоги
        BitShift(BitAnd ($flags,2),-5), _ ; 2: использовать новый стиль диалога
        BitShift(BitAnd ($flags,4),-2)) ; 4: включить cтроку редактирования
    ; Заполнение структур данных
    DllStructSetData ($utl, 1, $title)
    DllStructSetData ($ubi, 1, $hwnd)
    DllStructSetData ($ubi, 3, DllStructGetPtr($urs))
    DllStructSetData ($ubi, 4, DllStructGetPtr($utl))
    DllStructSetData ($ubi, 5, $ulf)
    $ret = DllCall ("shell32.dll", "ptr", "SHGetSpecialFolderLocation", _
        "int", 0 , _
        "int", $root , _
        "ptr", DllStructGetPtr($ubi, 2))
    If $ret[0] Then Return $res
    ; Открытие окна выбора каталога
    $pidl = DllCall ("shell32.dll", "ptr", "SHBrowseForFolder", "ptr", DllStructGetPtr ($ubi))
    If $pidl[0] Then
        $ret = DllCall ("shell32.dll", "int", "SHGetPathFromIDList", _
            "ptr", $pidl[0], _
            "ptr", DllStructGetPtr ($urs))
        If $ret[0] Then $res = DllStructGetData ($urs, 1)
        DllCall ("ole32.dll", "int", "CoTaskMemFree", "ptr", $pidl[0]) ; чистим за собой
    EndIf
    DllCall ("ole32.dll", "int", "CoTaskMemFree", "ptr", DllStructGetData ($ubi, 2))
    Return $res ; Вывод результата
EndFunc

Func _InputBox($Title,$Promt,$Default="",$IsPassword=0,$IsDigits=0,$Width=-1,$Height=-1,$Left=-1,$Top=-1,$Style=0,$exStyle=0,$Timeout=0,$Parent=0)
        GUISetState(@SW_DISABLE, $Parent)
        If $Width < 200 Then $Width = 200
        If $Height < 150 Then $Height = 150
       
        Local $InputGui, $OKButton, $CancelButton, $InputBoxID, $Msg, $GuiCoords, $RetValue, $InputMsg, $TimerStart
       
        $InputGui = GUICreate($Title, $Width, $Height, $Left, $Top, 0x00040000+$Style, $exStyle, $Parent)
       
        GUICtrlCreateLabel($Promt, 20, 5, $Width-40, 35)
        GUICtrlSetResizing(-1, 32)
       
        $OKButton = GUICtrlCreateButton("OK", ($Width/2)-70, $Height-95, 60, 25)
        GUICtrlSetResizing(-1, 0x0240)
        $CancelButton = GUICtrlCreateButton("Cancel", ($Width/2)+10, $Height-95, 60, 25)
        GUICtrlSetResizing(-1, 0x0240)
       
        If $IsPassword <> 0 Then $IsPassword = 32
        If $IsDigits <> 0 Then $IsDigits = 8192
        $InputBoxID = GUICtrlCreateInput($Default, 20, $Height-60, $Width-40, 20, $IsPassword+$IsDigits, 0x00000001)
        GUICtrlSetResizing(-1, 0x0240)
        GUICtrlSetState(-1, 256)
       
        GUISetState(@SW_SHOW, $InputGui)
        If $Timeout > 0 Then $TimerStart = TimerInit()
        While 1
                $InputMsg = GUIGetMsg()
                Switch $InputMsg
                        Case -3, $CancelButton
                                GUISetState(@SW_ENABLE, $Parent)
                                GUISetState(@SW_RESTORE, $Parent)
                                GUIDelete($InputGui)
                                SetError(1)
                                Return ""
                        Case -12
                                $GuiCoords = WinGetPos($Title)
                                If $GuiCoords <> 0 Then
                                        $Width = $GuiCoords[2]
                                        $Height = $GuiCoords[3]
                                        If $Width < 200 And $Height >= 150 Then
                                                WinMove($Title, "", $GuiCoords[0], $GuiCoords[1], 200, $Height)
                                        ElseIf $Width < 200 And $Height < 150 Then
                                                WinMove($Title, "", $GuiCoords[0], $GuiCoords[1], 200, 150)
                                        EndIf
                                        If $Height < 150 And $Width >= 200 Then
                                                WinMove($Title, "", $GuiCoords[0], $GuiCoords[1], $Width, 150)
                                        ElseIf $Height < 150 And $Width < 200 Then
                                                WinMove($Title, "", $GuiCoords[0], $GuiCoords[1], 200, 150)
                                        EndIf
                                EndIf
                        Case $OKButton
                                $RetValue = GUICtrlRead($InputBoxID)
                                GUISetState(@SW_ENABLE, $Parent)
                                GUISetState(@SW_RESTORE, $Parent)
                                GUIDelete($InputGui)
                                SetError(0)
                                Return $RetValue
                EndSwitch
                If $Timeout > 0 And Round(TimerDiff($TimerStart)/1000) = $Timeout Then
                        $RetValue = GUICtrlRead($InputBoxID)
                        GUISetState(@SW_ENABLE, $Parent)
                        GUISetState(@SW_RESTORE, $Parent)
                        GUIDelete($InputGui)
                        SetError(2)
                        Return $RetValue
                EndIf
        WEnd
EndFunc

Func ShowMenu($hWnd, $CtrlID, $nContextID)
    Local $hMenu = GUICtrlGetHandle($nContextID)
   
    $arPos = ControlGetPos($hWnd, "", $CtrlID)
   
    Local $x = $arPos[0]
    Local $y = $arPos[1] + $arPos[3]
   
    ClientToScreen($hWnd, $x, $y)
    TrackPopupMenu($hWnd, $hMenu, $x, $y)
EndFunc

Func ClientToScreen($hWnd, ByRef $x, ByRef $y)
    Local $stPoint = DllStructCreate("int;int")
   
    DllStructSetData($stPoint, 1, $x)
    DllStructSetData($stPoint, 2, $y)

    DllCall("user32.dll", "int", "ClientToScreen", "hwnd", $hWnd, "ptr", DllStructGetPtr($stPoint))
   
    $x = DllStructGetData($stPoint, 1)
    $y = DllStructGetData($stPoint, 2)
    ; release Struct not really needed as it is a local
    $stPoint = 0
EndFunc

Func TrackPopupMenu($hWnd, $hMenu, $x, $y)
    DllCall("user32.dll", "int", "TrackPopupMenuEx", "hwnd", $hMenu, "int", 0, "int", $x, "int", $y, "hwnd", $hWnd, "ptr", 0)
EndFunc


Creat0R 24-02-2007 17:50 554729

Функция для ограничения размеров гуи при испольовании стиля $WS_SIZEBOX (я кажется как то спрашивал тут про это, но тогда не имел понятия как сделать, а сегодня уже знании побольше :) )...

Код:

#include <GuiConstants.au3>

$Title = "Resize Limit GUI Demo"
GUICreate($Title, 300, 250, -1, -1, $WS_SIZEBOX)

GUISetState()

While 1
    $Msg = GUIGetMsg()
    Switch $Msg
        Case -3
            Exit
        Case -11, -8
            _ResizeLimit($Title, "", 200, 200, 600, 500)
    EndSwitch
    Sleep(10)
WEnd

Func _ResizeLimit($Title, $Text="", $MinWidth=150, $MinHeight=100, $MaxWidth=@DesktopWidth, $MaxHeight=@DesktopHeight)
    If Not WinExists($Title, $Text) Then
        SetError(1)
        Return -1
    EndIf
    Local $PosArr = WinGetPos($Title, $Text), $xPos, $yPos, $wPos, $hPos
    If IsArray($PosArr) Then
        $xPos = $PosArr[0]
        $yPos = $PosArr[1]
        $wPos = $PosArr[2]
        $hPos = $PosArr[3]
        If ($wPos <> $MinWidth And $hPos <> $MinHeight) Or ($wPos <> $MaxWidth And $hPos <> $MaxHeight) Then
            If $wPos < $MinWidth And $hPos < $MinHeight Then WinMove($Title, $Text, $xPos, $yPos, $MinWidth, $MinHeight)
            If $wPos < $MinWidth And $hPos >= $MinHeight Then WinMove($Title, $Text, $xPos, $yPos, $MinWidth, $hPos)
                If $wPos >= $MinWidth And $hPos < $MinHeight Then WinMove($Title, $Text, $xPos, $yPos, $wPos, $MinHeight)

                        If $wPos > $MaxWidth And $hPos > $MaxHeight Then WinMove($Title, $Text, $xPos, $yPos, $MaxWidth, $MaxHeight)
            If $wPos > $MaxWidth And $hPos <= $MaxHeight Then WinMove($Title, $Text, $xPos, $yPos, $MaxWidth, $hPos)
                If $wPos <= $MaxWidth And $hPos > $MaxHeight Then WinMove($Title, $Text, $xPos, $yPos, $wPos, $MaxHeight)
        EndIf
    EndIf
EndFunc

Есть правда пару недостатков - к примеру, если достигать максимального/минимального размера используя левую или верхнюю сторону (дл изменения размера), то окно как бы сдвигается в ту сторону в которую произведена попытка изменить размер на столько же на сколько был промежуток от текущего размера и позволенного минимального/максимального размера.
Полагаю и это можно как то решить, но мне и так пока нравится, если у кого то есть желаение, милости просим ;) - буду благодарен.

Creat0R 26-02-2007 01:29 555215

Как можно изменить функцию _ChooseColor чтобы в ней был параметр hWnd?
Я пробовал подсталять этот параметр в DllStructCreate и потом задать его при заплонении структуры данных (DllStructSetData) но всё безуспешно :( ... может кто-то знает как это сделать, и возможно ли вообще?

P.S
В начале самой функции есть упоминание об этом:

Цитата:

;~ HWND hwndOwner;
;~ HWND hInstance;
Значит видимо возможно, но как?

amel27 26-02-2007 06:54 555268

Creat0R
Цитата:

Вот более модифицированный пример архивирования файлов
Если заметил, то перед чтением выходного потока StdoutRead($Pid) я добавил проверку на наличие данных в потоке StdoutRead ($foo,0,True) - это позволяет избежать подвисания окна AutoIT на время отсутствия выходных данных (об этом кстати сказано в справке к StdoutRead())... соответственно, пришлось изменить способ определения конца архивации - с проверки @error на ProcessExists ($foo).
Цитата:

Как можно изменить функцию _ChooseColor чтобы в ней был параметр hWnd?
так пробовал?
Код:

Func _ChooseColor($i_ReturnType = 0, $i_colorref = 0, $i_refType = 0, $hwnd = 0)
        ...
        DllStructSetData($p, 1, DllStructGetSize($p))
        DllStructSetData($p, 2, $hwnd)
        DllStructSetData($p, 4, $i_colorref)
        ...
EndFunc  ;==>_ChooseColor


13ghost 26-02-2007 11:54 555385

Здравия желаю!
Простите если повторюсь,просто не нашёл(а может плохо искал).
Есть скрипт ,который архивирует,а потом с помощью встроенного в винду ftp клиента отсылает архив восвояси.так вот хотелось бы перехватывать сообщения ftp и писать их в лог ,что бы занать что и когда
как это можно сделать?

Creat0R 26-02-2007 22:00 555670

amel27
Цитата:

Если заметил, то перед чтением выходного потока StdoutRead($Pid) я добавил проверку на наличие данных в потоке StdoutRead ($foo,0,True) - это позволяет избежать подвисания окна AutoIT на время отсутствия выходных данных (об этом кстати сказано в справке к StdoutRead())...
Интересно, я если честно не обратил внимания, спасибо, пойду поправлю свой пример ;)

Цитата:

так пробовал?
Нет, но мне уже на офф. форуме подсказали, нужно точно также но чтобы $hwnd = 0 был как первый параметр, иначе не работает (не знаю даже почему, вроде никак не должо влиять) - но всё же биг сенкс!

13ghost
Цитата:

перехватывать сообщения ftp и писать их в лог
Если это консольная утилита, то попробуй применить методы из примера для архивирования тут.

13ghost 26-02-2007 23:28 555717

Creat0R
завтра попробую

Creat0R 28-02-2007 04:49 556220

amel27
Цитата:

так вот второй параметр (после имени инициатора) отвечает за тип подключения
Где именно мне в функции поравить 0 на 1 (это я ещё по поводу _InetGetSource() )?

Вот исходник функции:
(если не трудно, укажи где именно нужно менять)

Код:

Func _INetGetSource($s_URL, $s_Header = '')
       
        If StringLeft($s_URL, 7) <> 'http://' And StringLeft($s_URL, 8) <> 'https://' Then $s_URL = 'http://' & $s_URL
       
        Local $h_DLL = DllOpen("wininet.dll")
       
        Local $ai_IRF, $s_Buf = ''
       
        Local $ai_IO = DllCall($h_DLL, 'int', 'InternetOpen', 'str', "AutoIt v3", 'int', 0, 'int', 0, 'int', 0, 'int', 0)
        If @error Or $ai_IO[0] = 0 Then
                DllClose($h_DLL)
                SetError(1)
                Return ""
        EndIf
       
        Local $ai_IOU = DllCall($h_DLL, 'int', 'InternetOpenUrl', 'int', $ai_IO[0], 'str', $s_URL, 'str', $s_Header, 'int', StringLen($s_Header), 'int', 0x80000000, 'int', 0)
        If @error Or $ai_IOU[0] = 0 Then
                DllCall($h_DLL, 'int', 'InternetCloseHandle', 'int', $ai_IO[0])
                DllClose($h_DLL)
                SetError(1)
                Return ""
        EndIf
       
        Local $v_Struct = DllStructCreate('udword')
        DllStructSetData($v_Struct, 1, 1)
       
        While DllStructGetData($v_Struct, 1) <> 0
                $ai_IRF = DllCall($h_DLL, 'int', 'InternetReadFile', 'int', $ai_IOU[0], 'str', '', 'int', 256, 'ptr', DllStructGetPtr($v_Struct))       
                $s_Buf &= StringLeft($ai_IRF[2], DllStructGetData($v_Struct, 1))
        WEnd
       
        DllCall($h_DLL, 'int', 'InternetCloseHandle', 'int', $ai_IOU[0])
        DllCall($h_DLL, 'int', 'InternetCloseHandle', 'int', $ai_IO[0])
        DllClose($h_DLL)
        Return $s_Buf
EndFunc


amel27 28-02-2007 07:05 556228

Creat0R
Код:

Local $ai_IO = DllCall($h_DLL, 'int', 'InternetOpen', 'str', "AutoIt v3", 'int', 1, 'int', 0, 'int', 0, 'int', 0)

Creat0R 28-02-2007 07:33 556233

amel27
Спасибо!




Такой вопрос по регулярным вырожениям - Как возможно получить определённый текст, который находится между двумя заранее известными символами?

Т.е к примеру, имеем такой текст:

Код:

test1*этот текст нам нужен*test2
Заранее известны только разделители *, и нужно бы получить всё что между ними... я конечно могу использовать разного рода ухитрения со StringSplit, StringInStr, StringLeft...Right и т.д, но мне хотелось бы узнать как это можно достичь регулярными выражениями, и тем более, что подобные методы будут не очень надёжны.

amel27 28-02-2007 08:40 556244

Creat0R
что-то подобное я делал в скрипте "расцветки":
Код:

$str='test1*этот текст нам нужен*test2'
$chr='\*'
MsgBox (0,'Результат',StringRegExpReplace ($str,'^.*' & $chr & '(.*)' & $chr & '.*$','\1'))

PS: естественно, разделителей должно быть два

Creat0R 28-02-2007 10:18 556289

amel27
Я имел ввиду получить текст между двумя символами, но они могут быть разные, к примеру если этот метод использовать так (как функию):

Код:

$String = '1теперь нам нужен этот текст2'

MsgBox(0, "", _StringInside($String, "1", "2"))

Func _StringInside($String, $Start, $End)
        Return StringRegExpReplace($String, '^.*\' & $Start & '(.*)\' & $End & '.*$', '\1')
EndFunc

То результат будет не верный, нужно как то получать текст между двумя заданными символами, и неважно какие символы, или где они стоят, если между ними ничего нет, то можно возвращать весь $String...

Добавлено:
Во! сделал, правда я не уверен что учёл все символы...

Код:

$String = '_теперь нам нужен этот текст^'

MsgBox(0, "", _StringInside($String, "_", "^"))

Func _StringInside($String, $Start, $End)
    If StringRegExp($Start, "[\+\|\*\^\$\.\[\]\(\)\?\\]") Then $Start = "\" & $Start
    If StringRegExp($End, "[\+\|\*\^\$\.\[\]\(\)\?\\]") Then $End = "\" & $End
    Local $Ret = StringRegExpReplace($String, '^.*' & $Start & '(.*)' & $End & '.*$', '\1')
    If $Ret = "" Then Return $String
    Return $Ret
EndFunc

Спасибо!

Хм, но теперь другая проблема - если более чем два совпадения символов, то возвращается последнее межсимвольное значение, а нужно чтобы в таком случае возвращалось первое совпадение (с левой стороны, т.е сначала).

amel27 28-02-2007 11:29 556326

Creat0R
ну... вот еще вариант, выбирающий фрагмент от первого вхождения 1-го символа до первого вхождения 2-го:
Код:

$String = '_теперь нам нужен этот текст^'

MsgBox(0, "", _StringInside($String, "_", "^"))

Func _StringInside($String, $Start, $End)
    $Start = StringRegExpReplace ($Start, '([\+\|\*\^\$\.\[\]\(\)\?\\])', '\\\1')
    $End = StringRegExpReplace ($End, '([\+\|\*\^\$\.\[\]\(\)\?\\])', '\\\1')
    Local $pattern = '^[^' & $Start & ']*' & $Start & '([^' & $End & ']*)' & $End & '.*$'
    Return StringRegExpReplace($String, $pattern, '\1')
EndFunc


Creat0R 28-02-2007 11:56 556349

amel27
Цитата:

вот еще вариант
Во! это то что нужно (правда Local там лишних два раза встречается ;) ), спасибо большое (см. ниже полный пример для подобной функции, я её уже переименовал :) )...

Поздравляю со статусом Ветерана! :4u:

Код:

$String = 'Это нам не нужно. Нам нужен этот текст, :и этот тоже:, а :этот нам не нужен:'

MsgBox(0, "", _StringMidle($String, ".", ","))

MsgBox(0, "", _StringMidle($String, ":", ":"))

Func _StringMidle($String, $Start, $End)
    $Start = StringRegExpReplace ($Start, '([\+\|\*\^\$\.\[\]\(\)\?\\])', '\\\1')
    $End = StringRegExpReplace ($End, '([\+\|\*\^\$\.\[\]\(\)\?\\])', '\\\1')
    Local $pattern = '^[^' & $Start & ']*' & $Start & '([^' & $End & ']*)' & $End & '.*$'
    Return StringRegExpReplace($String, $pattern, '\1')
EndFunc


13ghost 28-02-2007 20:50 556553

Объясните пожалуйста,а то я не догоняю,не могу понять что в справке написано:
что делает ConsoleWrite? и для чего её можно применить?
зарание благодарен

amel27 01-03-2007 05:22 556656

13ghost
Штатное применение - отладка скриптов средствами SciTE, кстати неплохая альтернатива MsgBox() ;). Выводит заданный тект (например, значения переменных) в экран вывода - тот, что включается по F8. Из нештатных - запись данных в STDOUT при запуске скрипта через CMD.

Creat0R
Цитата:

Local там лишних два раза встречается
гы-гы, а я исправил раньше твоего замечания ;)
Цитата:

Поздравляю со статусом Ветерана!
упс, а кем я был? :o

Vadikan 01-03-2007 07:00 556668

Цитата:

упс, а кем я был
Ты можешь быть кем хочешь, изменяя статус в профиле, - это привелегия участников, входящих в группу Contributors.

Creat0R 01-03-2007 10:35 556723

amel27
Цитата:

а я исправил раньше твоего замечания
Ивени, не заметил...

Цитата:

а кем я был?
Старожил'ом кажется :shuffle:

belonesox 02-03-2007 21:09 557400

Вопрос про чтение stdout'а AutoItом - наблюдаю эффект, что для некоторых программ, stdout то читается, то не читается (в зависимости от опций).
Например, рассмотрим следующий код:

Код:

Func ShowStdout($cmd)
        $stdout=""
        $foo = Run($cmd, @SystemDir, @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)
        While 1
                $line = StdoutRead($foo)
                If @error Then ExitLoop
                $stdout=$stdout & $line
        Wend
        MsgBox(0,$cmd,$stdout)
EndFunc

$cmd=@ComSpec & " /c " & " java  "
ShowStdout($cmd) ; Показывает STDOUT нормально
$cmd=@ComSpec & " /c " & " java -version "
ShowStdout($cmd) ; Показывает пустой STDOUT
$cmd=@ComSpec & " /c " & " python -h "
ShowStdout($cmd) ; Показывает STDOUT нормально
$cmd=@ComSpec & " /c " & " python -V "
ShowStdout($cmd) ; Показывает пустой STDOUT
Exit(0)

Если ли у кого-то идеи, с чем это может быть связано или обусловлено?

C уважением, Стас.

Evgeniy15 03-03-2007 01:10 557454

Иногда название окна не меняется. Получается, что посылая следующий {ENTER} нажимаешь на {Cancel}. Команда sleep не очень эффективна, т.к. она нормально отрабатывается на одном компе, на другом с заметной задержкой а на третьем задержки не хватает. Как быть в таком случае?

Creat0R 03-03-2007 09:28 557491

belonesox
Цитата:

с чем это может быть связано или обусловлено?
Если возращается пустое значение, значит произошла ошибка при первой попытке чтения, вот эту ошибку (а точнее пустое значение) можно и улавливать:

Код:

Func ShowStdout($cmd)
    $stdout=""
    $foo = Run($cmd, @SystemDir, @SW_HIDE, $STDERR_CHILD+$STDOUT_CHILD)
    While 1
        $line = StdoutRead($foo)
        If @error Then ExitLoop
        $stdout &= $line
    Wend
    If $stdout = "" Then $stdout = StderrRead($foo)
    MsgBox(0, $cmd, $stdout)
EndFunc


Evgeniy15
Цитата:

Как быть в таком случае?
В каком случае? я, как и многие другие, увы, гадать не умею :(

amel27 03-03-2007 10:18 557504

belonesox
попробуй следующий вариант (проверил только для java, python под рукой нет):
Код:

#include <Constants.au3>

$cmd=@ComSpec & " /c " & " java  2>&1"
ShowStdout($cmd) ; Показывает STDOUT нормально
$cmd=@ComSpec & " /c " & ' java -version 2>&1'
ShowStdout($cmd) ; Показывает пустой STDOUT
 $cmd=@ComSpec & " /c " & " python -h  2>&1"
ShowStdout($cmd) ; Показывает STDOUT нормально
$cmd=@ComSpec & " /c " & " python -V  2>&1"
ShowStdout($cmd) ; Показывает пустой STDOUT

 Func ShowStdout($cmd)
    Local $stdout
    $foo = Run ($cmd, @SystemDir, @SW_HIDE, $STDERR_CHILD + $STDERR_CHILD + $STDOUT_CHILD)
    While 1
        $line = StdoutRead($foo)
        If @error Then ExitLoop
        $stdout=$stdout & $line
    Wend
    MsgBox(0,$cmd,$stdout)
EndFunc

ALL
просьба не забывать добавлять в скрипты необходимые строчки #include !

Creat0R 03-03-2007 12:32 557527

Как можно получить загрузку ЦП определённого процесса? не важно, по имени образа, пути к файлу процесса, или по Pid. Это возможно узнать? (AutoIt'ом естественно ;) ).

amel27 03-03-2007 13:39 557545

Creat0R
что-то типа такого:
Код:

MsgBox (0, '', _GetCPUUsageProcess ('winrar'))

Func _GetCPUUsageProcess ($proc, $ticks = 1000)
    Local $aCount[3], $strProc = 'Name="' & $proc & '"'
    Local $colItems, $objItem, $objWMIService = ObjGet("winmgmts:\\.\root\CIMV2")
    If IsNumber ($proc) And $proc>0 Then $strProc = "IDProcess=" & $proc
    ; Считываем необходимые характеристики процесса - попытка №1
    $colItems = $objWMIService.ExecQuery ("SELECT IDProcess,PercentProcessorTime,Timestamp_Sys100NS FROM Win32_PerfRawData_PerfProc_Process WHERE " & $strProc, "WQL", 0x30)
    For $objItem In $colItems
        $aCount[0]=$objItem.IDProcess
        $aCount[1]=$objItem.PercentProcessorTime
        $aCount[2]=$objItem.Timestamp_Sys100NS
        ExitLoop
    Next
    If $aCount[0] Then
        ; Накапливаем статистику...
        Sleep ($ticks)
        ; Считываем необходимые характеристики процесса - попытка №2
        $colItems = $objWMIService.ExecQuery ("SELECT PercentProcessorTime,Timestamp_Sys100NS FROM Win32_PerfRawData_PerfProc_Process WHERE IDProcess=" & $aCount[0], "WQL", 0x30)
        For $objItem In $colItems
            Return Round (100*($objItem.PercentProcessorTime - $aCount[1])/($objItem.Timestamp_Sys100NS - $aCount[2]))
        Next
    EndIf
    Return ""
EndFunc


Creat0R 03-03-2007 14:40 557563

amel27
Цитата:

что-то типа такого:
Не работает :( до цикла дело не доходит...

Вернее доходит (это я с полным именем проверял, включая расширение), но возвращается всегда ноль :(

amel27 05-03-2007 02:36 557994

Creat0R
попробуй запустить архивацию каталога и проверить процесс "winrar",
FYI: эта функция показывает мгновенное значение загрузки CPU

Izh 05-03-2007 11:57 558088

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

Creat0R 05-03-2007 16:44 558170

amel27
Цитата:

попробуй запустить архивацию каталога и проверить процесс "winrar",
FYI: эта функция показывает мгновенное значение загрузки CPU
Да, для архивации показывает (хотя и не совсем мгновенно), но я пробовал на таком примере, и странно что не работает:

Код:

#include <GuiConstants.au3>
GUICreate("CPU Usage Test", 200, 200)

$ProcessName = "AutoIt3"
$StatusBar = GUICtrlCreateLabel("CPU Usage: ", 0, 185, 200, 15, BitOr($SS_SIMPLE,$SS_SUNKEN))

GUISetState()

AdlibEnable("SetStatus", 20)

While GUIGetMsg() <> -3
WEnd

Func SetStatus()
    GUICtrlSetData($StatusBar, "CPU Usage: " & _GetCPUUsage($ProcessName))
EndFunc

Ведь по идее сам процесс скрипта (AutoIt3.exe) занимает около 10-20-ти процентов загрузкий ЦП (в данном примере), но возвращается всегда ноль. Я пробовал и на других процессах, но результат тот же :(

И ещё, а для чего по умолчанию стоит процесс idle, как я понял это типа “Бездействие системы”? но если оставлять по умолчанию, то возвращается тоже ноль, хотя в Диспетчере задач если ничего не грузит процессор то это значение становиться 99.

P.S
Что такое FYI?


Izh
Цитата:

заставить скрипт определить сидюк
Из спраки немного изменил пример (поиск по команде DriveGetDrive):

Код:

$var = DriveGetDrive( "CDROM" )
If NOT @error Then
    MsgBox(4096,"", "Found " & $var[0] & " drives")
    For $i = 1 to $var[0]
        MsgBox(4096,"Drive " & $i, $var[$i])
    Next
EndIf


amel27 06-03-2007 05:51 558340

Как определить период бездействия пользователя (пример):
Код:

#include <Date.au3>
Opt("TrayIconHide", 1)

$IdleMinimum = 1000 ; Количество допустимых секунд неактивности
$LogFileName = StringTrimRight (@ScriptFullPath, 4) & ".log" ; Имя файла журнала

While 1
    ; Ожидание неактивности достаточной длительности
    $iIdle = _IdleWaitCommit ($IdleMinimum)
    ; Запись этого события в лог
    Local $sHours = '', $sMins = '', $sSecs = ''
    $iHours = Int ($iIdle/3600)
    If $iHours Then $sHours = $iHours & ' часов '
    $iMins = Int (Mod ($iIdle, 3600)/60)
    If $iMins Then $sMins = $iMins & ' минут '
    $iSecs = Round (Mod (Mod ($iIdle, 3600), 60))
    If $iSecs Then $sSecs = $iSecs & ' секунд'
    FileWriteLine ($LogFileName, _Now () & ' ' & @UserName & ' неактивен ' & $sHours & $sMins & $sSecs & @CRLF)
Wend

; Функция: ожидание неактивности пользователя.
; Возвращает: время неактивности в секундах.
; $idlesec - минимальная длительность ожидаемой неактивности в сек.
Func _IdleWaitCommit ($idlesec)
    $idlesec = $idlesec * 1000
    Local $iSave, $LastInputInfo = DllStructCreate ("uint;dword")
    DllStructSetData ($LastInputInfo, 1, DllStructGetSize ($LastInputInfo))
    DllCall ("user32.dll", "int", "GetLastInputInfo", "ptr", DllStructGetPtr ($LastInputInfo))
    Do
        $iSave = DllStructGetData ($LastInputInfo, 2)
        Sleep(500)
        DllCall ("user32.dll", "int", "GetLastInputInfo", "ptr", DllStructGetPtr ($LastInputInfo))
    Until (DllStructGetData ($LastInputInfo, 2)-$iSave) > $idlesec
    Return Round ((DllStructGetData ($LastInputInfo, 2)-$iSave)/1000)
EndFunc


amel27 06-03-2007 07:33 558361

Creat0R
Ну... значит процесс не может определить загрузку самого себя, т.к. эти операции выполняются синхронно - пока WMI вычисляет загрузку сам процесс (AutoIt3) ожидает ответа, т.е. действительно простаивает... потому я и сказал о мгновенном значении.

по поводу Idle - там скорей всего общая загрузка CPU

P.S. FYI - For Yur Information :)

xstranger 06-03-2007 07:58 558365

Цитата:

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

$source = RegRead("HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Setup", "SourcePath")

runwait($source & 'Software\prog.exe')


это хорошо работает на этапе GuiRunOnce, при автоустановке софта. но может и дальше использоваться если конфигурация носителей не меняется

Creat0R 06-03-2007 12:58 558477

amel27
Цитата:

значит процесс не может определить загрузку самого себя
Но ведь...

Цитата:

Я пробовал и на других процессах, но результат тот же :(
Цитата:

пока WMI вычисляет загрузку сам процесс (AutoIt3) ожидает ответа, т.е. действительно простаивает
Да, но, в Диспетчере задач явно видно что процесс вовсе не простаивает, а именно грузит ЦП.

Цитата:

по поводу Idle - там скорей всего общая загрузка CPU
Тогда почему тоже всегда ноль? :)

Цитата:

P.S. FYI - For Yur Information
Спасибо, буду знать (и наверное юзать ;) )

amel27 07-03-2007 09:37 558797

Creat0R
исправил скрипт - добавил усреднение по заданному интервалу (в "тиках"), кроме того процесс может теперь передаваться как по имени, так и по PID.

Creat0R 08-03-2007 05:51 559142

amel27
Цитата:

исправил скрипт
Большое спасибо, вроде работает....

Хотя мне пока не удаётся подобрать оптимальный интервал использования этой функции (между каждым её вызовом и установкой тикания ;) ).

Цитата:

процесс может теперь передаваться как по имени, так и по PID
По PID вроде не работает, а по имени опять же, нужно без расширения.... но это думаю не страшно (хотя иногда существуют процессы не только с расширением *.exe... тогда придётся делать перебор по всем процессам на существование с подобным именем)...

Мне вообще то всё это нужно для одного моего небольшого проэктика, я пытаюсь написать утилитку менеджер процессов - Получилось ВСЁ что хотел, кроме (теперь корректного, т.е в реальном времени) слежения за загрузкой ЦП (каждого процесса в отдельности и общего использования), и использования памяти каждым процессом.

Мне удалось адаптировать многие функции из офф. форума, естественно кучу твоих функции, и пару собственных.
Утилита позволяет просматривать подробную информацию о процессе, имеет почти все те же функции что и у встроенного taskmgr.exe в Windows (включая собственный диалог запуска приложении - FileRun), и даже чуть чуть больше :) .

Добавлено:



amel27
Цитата:

Как определить период бездействия пользователя
Бездействия в каком смысле? что юзер (не) должен делать для бездействия? я запустил этот пример, ничего не делал пару секунд, потом что то начал делать :), но лог не пишется.

Creat0R 08-03-2007 22:52 559359

Diamond
Ты как то спрашивал про то, как заставить гуи НЕ отображать системны стиль, так вот я нашел на офф. форуме решение этой задачки...

Это простой скачивальщик (не знаю на сколько он полезен), при его запуске задаётся стиль как в старых/без стильных виндоус.
Вот ссылка, я немного переделал, так как там не совсем весь гуи был таким стилем, я даже удивился, как окно от FileSelectFolder() приняло старый (не)стиль :) - видимо и всё остальное что будет использованно в гуи будет иметь подобный стиль.
Я не разбирался как оно работает, но видимо там упорно используются Dll'овские штучки :)

Creat0R 08-03-2007 23:12 559363

amel27
Тоже на офф. форуме нашел функцию для слежения за бездельем юзера :biggrin: (немного переделал для примера) :

Код:

Dim $i_LastActive = _LastActive()

$TimeInit = TimerInit()
While 1
    If $i_LastActive <> _LastActive() Then ExitLoop
    Sleep(100)
WEnd

MsgBox(64, "Activity Test", "You was not active <" & Round(TimerDiff($TimeInit)/1000, 1) & "> second(s)")

 Func _LastActive($v_User32Dll = 'user32.dll')
    Local $str_LastInput = DllStructCreate('uint;dword')
    DllStructSetData($str_LastInput, 1, DllStructGetSize($str_LastInput))
    DllCall($v_User32Dll, 'int', 'GetLastInputInfo', 'ptr', DllStructGetPtr($str_LastInput))
    Return DllStructGetData($str_LastInput, 2)
EndFunc

Я давно искал подобное, мне нужно было проверить, была ли нажата какая либо клавиша, или кнопка мышки, и это идеально подходит!

amel27 09-03-2007 03:06 559400

Creat0R
Цитата:

По PID вроде не работает
да не, вроде работает если PID передавать не строкой, а числом
Цитата:

я пытаюсь написать утилитку менеджер процессов
в таком случае эффективней выполнять запрос не по отдельным процессам, а сразу по всему списку, вот вариант ProcessList, который кроме PID и Name выводит дополнительно инфу по загрузке CPU:
Код:

$a = _ProcessList ('')
If IsArray ($a) Then
    For $i=0 To $a[0][0]
        ConsoleWrite (StringFormat('%4i', $a[$i][0]) & ' : ' & StringFormat('%02i', $a[$i][2]) & ' : ' & $a[$i][1] & @CRLF)
    Next
EndIf

Func _ProcessList ($name = '', $ticks = 1000)
    Local $arrWork[1][3] = [[0,0,0]], $arrMain[1][3] = [[0,'_Summary',0]]
    Local $i, $colItems, $objItem, $objWMIService = ObjGet("winmgmts:\\.\root\CIMV2"), $where = 'WHERE IDProcess>0'
    If $name <> '' Then $where &= ' AND Name=' & '"' & $name & '"'
    ; Считываем необходимые характеристики процессов - попытка №1
    $colItems = $objWMIService.ExecQuery ("SELECT IDProcess,PercentProcessorTime,Timestamp_Sys100NS FROM Win32_PerfRawData_PerfProc_Process " & $where, "WQL", 0x30)
    For $objItem In $colItems
        $arrWork[0][0]+=1
        ReDim $arrWork[$arrWork[0][0]+1][3]
        $arrWork[$arrWork[0][0]][0]=$objItem.IDProcess
        $arrWork[$arrWork[0][0]][1]=$objItem.PercentProcessorTime
        $arrWork[$arrWork[0][0]][2]=$objItem.Timestamp_Sys100NS
    Next
    If $arrWork[0][0]=0 Then Return ''
    ; Накапливаем статистику...
    Sleep ($ticks)
    ; Считываем необходимые характеристики процессов - попытка №2
    $colItems = $objWMIService.ExecQuery ("SELECT IDProcess,PercentProcessorTime,Timestamp_Sys100NS FROM Win32_PerfRawData_PerfProc_Process " & $where, "WQL", 0x30)
    For $objItem In $colItems
        For $i=1 To $arrWork[0][0]
            If $arrWork[$i][0]=$objItem.IDProcess Then
                $arrMain[0][0]+=1
                ReDim $arrMain[$arrMain[0][0]+1][3]
                $arrMain[$arrMain[0][0]][0]=$objItem.IDProcess
                $arrMain[$arrMain[0][0]][1]=$objItem.Name
                $arrMain[$arrMain[0][0]][2]=Round(100*($arrWork[$i][1]-$objItem.PercentProcessorTime)/($arrWork[$i][2]-$objItem.Timestamp_Sys100NS))
                $arrMain[0][2]+=$arrMain[$arrMain[0][0]][2]
            EndIf
        Next
    Next
    If $arrMain[0][2]>100 Then $arrMain[0][2]=100
    Return $arrMain
EndFunc


amel27 09-03-2007 03:25 559402

Creat0R
Цитата:

на офф. форуме нашел функцию для слежения за бездельем юзера
мне свой вариант нравится больше, т.к. позволяет отслеживать не только начало, но и конец бездействия.... кстати можно использовать для хранителей экрана :)
Код:

#include <Date.au3>

$IdleMinimum = 5000 ; допустимый период неактивности в миллисекундах

While 1
    $iIdle = _IdleWaitStart ($IdleMinimum)
    ConsoleWrite (_Now () & ' ' & @UserName & ' неактивен уже ' & _TickToTimeString ($iIdle) & @CRLF)
    $iIdle = _IdleWaitCommit($IdleMinimum)
    ConsoleWrite (_Now () & ' ' & @UserName & ' был неактивен ' & _TickToTimeString ($iIdle) & @CRLF)
Wend

; Ожидание начала бездействия пользователя.
; Возвращает время неактивности (в тиках)
; $idlesec - минимальная длительность ожидаемой неактивности (в тиках)
Func _IdleWaitStart ($idlesec)
    Local $aRet, $iSave, $iTick, $LastInputInfo = DllStructCreate ("uint;dword")
    DllStructSetData ($LastInputInfo, 1, DllStructGetSize ($LastInputInfo))
    DllCall ("user32.dll", "int", "GetLastInputInfo", "ptr", DllStructGetPtr ($LastInputInfo))
    Do
        Sleep(200)
        $iSave= DllStructGetData ($LastInputInfo, 2)
        DllCall ("user32.dll", "int", "GetLastInputInfo", "ptr", DllStructGetPtr ($LastInputInfo))
        $aRet = DllCall ("kernel32.dll", "long", "GetTickCount")
    Until ($aRet[0] - DllStructGetData ($LastInputInfo, 2))> $idlesec
    Return $aRet[0] - DllStructGetData ($LastInputInfo, 2)
EndFunc

; Ожидание окончания бездействия пользователя.
; Возвращает время неактивности в (тиках)
; $idlesec - минимальная длительность ожидаемой неактивности в (тиках)
Func _IdleWaitCommit ($idlesec)
    Local $iSave, $LastInputInfo = DllStructCreate ("uint;dword")
    DllStructSetData ($LastInputInfo, 1, DllStructGetSize ($LastInputInfo))
    DllCall ("user32.dll", "int", "GetLastInputInfo", "ptr", DllStructGetPtr ($LastInputInfo))
    Do
        $iSave = DllStructGetData ($LastInputInfo, 2)
        Sleep(200)
        DllCall ("user32.dll", "int", "GetLastInputInfo", "ptr", DllStructGetPtr ($LastInputInfo))
    Until (DllStructGetData ($LastInputInfo, 2)-$iSave) > $idlesec
    Return DllStructGetData ($LastInputInfo, 2)-$iSave
EndFunc

Func _TickToTimeString ($iTicks)
    Local $iHours, $iMins, $iSecs, $sText = ''
    _TicksToTime  ($iTicks, $iHours, $iMins, $iSecs)
    If $iHours Then $sText = $iHours & ' часов '
    If $iMins  Then $sText = $sText & $iMins & ' минут '
    If $iSecs  Then $sText = $sText & $iSecs & ' секунд'
    If $sText = '' Then $sText = 'меньше секунды'
    Return $sText
EndFunc


Creat0R 09-03-2007 21:17 559738

amel27
Цитата:

работает если PID передавать не строкой, а числом
Строкой в смысле String'ом ? я из переменной передаю, но переменная содержит непосредственно цифри (это PID берётся из списка прцессов в ListView)... но как выяснилось, берутся не только цифры(?), я подставил Number($Pid) и всё нормально определяется... мистика... :)

Цитата:

в таком случае эффективней выполнять запрос не по отдельным процессам, а сразу по всему списку
100% согласен, но у меня с этим проблема - у меня уже считывается список в ListView, и при обновлении этого списка, нужно обновлять только колонку с загрузкой ЦП, т.к весь список обновлять слишком долго (для обновления списка в случае отсутствия/добавления процесса, идёт отдельная проверка, где сравнивается список существующих процессов и список процессов в ListView, если найдены различия, то обновляется всё).

Цитата:

мне свой вариант нравится больше
Мне тоже (твой) :) - интересно, можно на его основе, сделать запись статистики? т.е к примеру, указать промежуток слежения за юзером (можно из InputBox() или ещё лучше, GUI нарисовать с отображением графика даты и времени), допустим в течении 24-ёх часов, и накапливать в переменную (а лучше в массив) данные, А) о том сколько юзер был не активен (в течении этого времени, т.е 24-ёх часов), и Б) сколько юзер был активен - данные чтобы возвращались в поноценном формате времени (по необходимости и даты)... я попробовал что-то подбное сделать, но безуспешно... могу выложить мои безнадёжные попытки если нужно (там уже гуик нарисован) :)

amel27 11-03-2007 07:20 560121

Creat0R
Цитата:

PID берётся из списка прцессов в ListView
значит нужно передавать значение переменной, обработанное ф-цией Number()

Цитата:

100% согласен, но у меня с этим проблема - у меня уже считывается список в ListView
Имхо лучше ввести пару рабочих массивов со списками процессов, которые бы поочередно (целиком) обновлялись WMI-запросами, и на основании сравнения этих массивов определять какие GUI-элементы необходимо обновить...

Цитата:

интересно, можно на его основе, сделать запись статистики?
не вижу препятствий, например можно вести два массива - с информаций об активности и о бездействии: начало, конец и длительность временного периода... останется только решить в каком виде представлять содержимое массивов
Код:

#include <Date.au3>

$IdleMinimum = 5000 ; Minimum inactivity in seconds

Dim $arrUserActive[1][3]=[[0,0,0]]
Dim $arrUserInactive[1][3]=[[0,0,0]]
While 1
    $arrUserActive[0][0]+=1
    ReDim $arrUserActive[$arrUserActive[0][0]+1][3]
    $arrUserActive[$arrUserActive[0][0]][0]=_Now ()
    $iIdle = _IdleWaitStart ($IdleMinimum)
    $arrUserActive[$arrUserActive[0][0]][1]=_Now ()
    $arrUserActive[$arrUserActive[0][0]][2]=_TickToTimeString($iIdle)
    ConsoleWrite ("Записей активности: " & $arrUserActive[0][0] & @TAB & "Записей нективности: " & $arrUserInactive[0][0] & @CRLF)

        $arrUserInactive[0][0]+=1
    ReDim $arrUserInactive[$arrUserInactive[0][0]+1][3]
    $arrUserInactive[$arrUserInactive[0][0]][0]=_Now ()
    $iIdle = _IdleWaitCommit($IdleMinimum)
    $arrUserInactive[$arrUserInactive[0][0]][1]=_Now ()
    $arrUserInactive[$arrUserInactive[0][0]][2]=_TickToTimeString($iIdle)
    ConsoleWrite ("Записей активности: " & $arrUserActive[0][0] & @TAB & "Записей нективности: " & $arrUserInactive[0][0] & @CRLF)
Wend

З.Ы.это только пример - для графического представления потребуется числовое представление интервалов а не текст

Creat0R 11-03-2007 07:56 560131

amel27
Цитата:

значит нужно передавать значение переменной, обработанное ф-цией Number()
Я так и делаю (уже)...
Цитата:

я подставил Number($Pid) и всё нормально определяется
Цитата:

Имхо лучше ввести пару рабочих массивов со списками процессов, которые бы поочередно (целиком) обновлялись WMI-запросами, и на основании сравнения этих массивов определять какие GUI-элементы необходимо обновить...
Не так то всё просто, ещё нужно сравнивать какой именно элемент в списке соответствует элементу массива, а иногда в списке могут быть (и будут) одинаковые имена процессов, что может вызвать конфиликты... естественно можно сравнивать по PID, но всё же всё это для меня пока ещё смутно... нужно немного поламать голову ;)

Цитата:

не вижу препятствий
Знаю, а вот я вижу... присмотревшись к твоему примеру, у меня началась голова кружится... я понимаю (с трудом) двумерный массив, а трёхмерный массив у меня вызывает желание закрыть побыстрее SciTE :biggrin:

Я пока остановлюсь на простеньком... я сделал типа юмористичесукую напоминалку для бездельника :) - вот код:

Код:

HotKeySet("^e", "Quit")
TraySetIcon("shell32.dll", 111)
TraySetToolTip("Laziness Detecter (!)")

$Idle = 0
$MinLaziness = 10
$MaxLaziness = 60
$LazyLimit = Random($MinLaziness, $MaxLaziness, 1)
$TimeStamp = TimerInit()
AdlibEnable("CheckLaziness", 10)

While 1
    $Idle = _IdleWaitCommit(0)
    TrayTip("", "", 0)
    $TimeStamp = TimerInit()
    $Idle = 0
WEnd

Func CheckLaziness()
    $TimeDiff = Round(TimerDiff($TimeStamp)/1000)
    If $TimeDiff > $LazyLimit And $Idle = 0 Then
        TrayTip("You are lazy", "You are been lazy for a long time (" & _SecsToTime($TimeDiff, ":") & ")", 5, 1)
        $TimeStamp = TimerInit()
        $LazyLimit = Random($MinLaziness, $MaxLaziness, 1)
    EndIf
    If $TimeDiff >= ($LazyLimit/2) Then TrayTip("", "", 0)
EndFunc

Func _SecsToTime($iTicks, $Delim)
    If Number($iTicks) >= 0 Then
        $iHours = Int($iTicks / 3600)
        $iTicks = Mod($iTicks, 3600)
        $iMins = Int($iTicks / 60)
        $iSecs = Round(Mod($iTicks, 60))
        If StringLen($iHours) = 1 Then $iHours = "0" & $iHours
        If StringLen($iMins) = 1 Then $iMins = "0" & $iMins
        If StringLen($iSecs) = 1 Then $iSecs = "0" & $iSecs
        $Time = $iHours & $Delim & $iMins & $Delim & $iSecs
        Return $Time
    Else
        SetError(1)
        Return 0
    EndIf
EndFunc

Func _IdleWaitCommit($idlesec)
    Local $iSave, $LastInputInfo = DllStructCreate ("uint;dword")
    DllStructSetData ($LastInputInfo, 1, DllStructGetSize ($LastInputInfo))
    DllCall ("user32.dll", "int", "GetLastInputInfo", "ptr", DllStructGetPtr ($LastInputInfo))
    Do
        $iSave = DllStructGetData ($LastInputInfo, 2)
        Sleep(200)
        DllCall ("user32.dll", "int", "GetLastInputInfo", "ptr", DllStructGetPtr ($LastInputInfo))
    Until (DllStructGetData ($LastInputInfo, 2)-$iSave) > $idlesec
    Return DllStructGetData ($LastInputInfo, 2)-$iSave
EndFunc

Func Quit()
    Exit
EndFunc

Можно задать минимум и максимум ($MinLaziness = 10 и $MaxLaziness = 60 - в секундах) время в течении которого будет считаться что юзер бкездельник :biggrin:
Будет перебираться случайный промежуток времени, и выскакивать треевская подсказака с напоминанием о том сколько времени пользователь ничего не делал.

amel27 11-03-2007 10:53 560160

Creat0R
Цитата:

трёхмерный массив у меня вызывает желание закрыть побыстрее SciTE
тут кажись только двумерные... ;)
Цитата:

Не так то всё просто, ещё нужно сравнивать какой именно элемент в списке соответствует элементу массива, а иногда в списке могут быть (и будут) одинаковые имена процессов, что может вызвать конфиликты... естественно можно сравнивать по PID, но всё же всё это для меня пока ещё смутно... нужно немного поламать голову
может этот пример поможет:
Код:

#include <array.au3>

$b = _ProcessList ()
While 1
    Sleep (1000)
    Dim $a = $b
    $b = _ProcessList ()
    _CompProcList ($a, $b)
Wend

Func _CompProcList (ByRef $a, ByRef $b)
    Local $i
    Local $a1[$a[0][0]+1], $a2[$a[0][0]+1], $b1[$b[0][0]+1], $b2[$b[0][0]+1]
    If $a[0][0] Then
        ; индексируем массив $a
        For $i=1 To $a[0][0]
            $a1[$i]=$a[$i][0] & $a[$i][1] ; PID и имя процесса
            $a2[$i]=$a[$i][0] & $a[$i][1] & $a[$i][2] ; PID, имя процесса и ЦП
        Next
        ; индексируем массив $b
        For $i=1 To $b[0][0]
            $b1[$i]=$b[$i][0] & $b[$i][1] ; PID и имя процесса
            $b2[$i]=$b[$i][0] & $b[$i][1] & $b[$i][2] ; PID, имя процесса и ЦП
        Next
        ; Сравниваем новый массив ($b) со старым ($a)
        For $i=1 To $b[0][0]
            $f1 = _ArraySearch($a1, $b1[$i], 1)
            $f2 = _ArraySearch($a2, $b2[$i], 1)
            If $f1<0 Then
                ConsoleWrite('Новый процесс: ' & StringFormat ('%4.0i',$b[$i][0]) & ' : ' & $b[$i][1] & @CRLF)
            ElseIf $f1>0 And $f2<0 Then
                ConsoleWrite('Изменилась загрузка ЦП: ' & StringFormat ('%4.0i',$b[$i][0]) & ' : ' & StringFormat ('%02i',$a[$f1][2]) & ' > ' & StringFormat ('%02i',$b[$i][2]) & ' : ' & $b[$i][1] & @CRLF)
            EndIf
        Next
        ; Сравниваем старый массив ($a) с новым ($b)
        For $i=1 To $a[0][0]
            $f1 = _ArraySearch($b1, $a1[$i], 1)
            If $f1<0 Then
                ConsoleWrite('Исчез процесс: ' & StringFormat ('%4.0i',$a[$i][0]) & ' : ' & $a[$i][1] & @CRLF)
            EndIf
        Next
    EndIf
EndFunc

Цитата:

сделал типа юмористичесукую напоминалку для бездельника
забавно, хотя Random имхо лишний... по крайней мере для бездельника :)

Creat0R 11-03-2007 12:33 560196

amel27
Цитата:

тут кажись только двумерные
Упс.. точно... но тоже путает (особенно подстановка самого массива в элемент этого же массива в каждом месте :wacko: ).

Цитата:

может этот пример поможет:
О! это точно поможет, попробую его адаптировать в утилитку. Спасибо!

Цитата:

забавно, хотя Random имхо лишний... по крайней мере для бездельника
Ну это больше для прикола чем для точного определения безделья... я например брату на компьютер поставлю, и пусть в определённый промежуток времени выскакивает сообщение что он бездельник, и при чём не в один и тот же промежуток, а каждый раз (почти) по разному, чтобы было интереснее :) ...

Кстати, я вот ещё что придумал... заносим в массив (можно из файла) разные сообщения (с разной характеристикой и контекстом), и тоже случайным перебором выводим в TrayTip'е, а также можно занести в массив все файлы из папки мелодии Windows - C:\windows\media (можно даже свою папку с мелодиями указать), и тоже в момент вывода сообщения случайно (в смысле в случайном порядке :) ) их проигрывать...

Creat0R 11-03-2007 17:28 560280

Ура!!! я это сделал, немного помучался, но всё же сделал!

Вместо использования звуков системы, я использовал её персонажа - старый добрый волшебник “Merlin” :)...

Если в системе не найден персонаж, то выводится TrayTip. А и ещё, чтобы персонаж ещё и говорил, в системе должен быть установлен голосовой движёк.

При простое более 5-ти секунд, иконка трея меняется на неактивного юзера, при активности иконка обратно меняется на что-то вроде юзера в движении (не смог в системе найти более походящей иконки).

Также при простое в переменную $TotalTime накапливается общее время простоя (секунды), а при активности эта переменная сбрасывается на ноль (0)...
Также удалось заносить в массив отдельные заготовки сообщении, если есть файл сообщении (LazyMessages.dat), то с него считываются строки, если его нет, то в скрипте уже заготовлены 10 сообщении (на английском)...
Для выхода из скрипта в любое время, нужно нажать Ctrl E (при английской раскладке).

В общем, на мой взгляд получилось довольно неплохо... правда есть пару моментов, например, как можно проверить закончил ли персонаж читать текст, и соответственно убить его? :) ... вот скрипт:

Код:

HotKeySet("^e", "Quit")
TraySetIcon("shell32.dll", 160)
TraySetToolTip("Laziness Detecter (!)")

Dim $MessagesArr[11]
$MessagesArr[0] = 10
$MessagesArr[1] = "You are been lazy for a long time <%n>"
$MessagesArr[2] = "This is enough, start doing something >:( - you are lazy to much (%n)"
$MessagesArr[3] = "Hello!? Any one is home? why you are so lazy so long time? <%n> do somthing!"
$MessagesArr[4] = "Hi! Don't you fill like cow? Laziness is reason number 1 of why people die"
$MessagesArr[5] = "It's been over a <%n> time sense you touch your computer, touch it now!"
$MessagesArr[6] = "I can not wait for you so long (%n), I am going to shutdown myself.... beep.. beeep.. beeeeeep"
$MessagesArr[7] = "Hey man, are you forgot about me? Fine! I want to divorced"
$MessagesArr[8] = "You have no check your email for <%n> time, maybe there something intersteing?"
$MessagesArr[9] = "There is a virus on your computer! (it exists there for a long time <%n>) perform virus checking immediately!"
$MessagesArr[10] = "Hi! What's up dog? Don't pay attention; I am just stupid character that doesn't need attention! >:("

$MessagesFile = "LazyMessages.dat"
If FileExists($MessagesFile) And FileRead($MessagesFile) <> "" Then $MessagesArr = StringSplit(FileRead($MessagesFile), @LF)

$Idle = 0
$TotalTime = 0
$MinLaziness = 10
$MaxLaziness = 60
$LazyLimit = Random($MinLaziness, $MaxLaziness, 1)
$TimeStamp = TimerInit()

AdlibEnable("CheckLaziness", 10)

While 1
        $Idle = _IdleWaitCommit(0)
        TraySetIcon("shell32.dll", 160)
        TrayTip("", "", 0)
        $TimeStamp = TimerInit()
        $Idle = 0
        $TotalTime = 0
WEnd

Func CheckLaziness()
        $TimeDiff = Round(TimerDiff($TimeStamp)/1000)
        If $TimeDiff > $LazyLimit And $Idle = 0 Then
                TraySetIcon("shell32.dll", 111)
                $TotalTime += $TimeDiff
                $LazyTime = _SecsToTime($TotalTime, ":")
                $TextToSay = StringReplace($MessagesArr[Random(1, $MessagesArr[0], 1)], "%n", $LazyTime)
                $SleepTime = Round((StringLen($TextToSay)/7)*1000)
                If StringLen($TextToSay) < 7 Then $SleepTime = 5000
                CharacterMsg($TextToSay, Random(100, @DesktopWidth-100, 1), Random(10, @DesktopHeight-150, 1), $SleepTime)
                If @error Then TrayTip("You are lazy", $TextToSay, 5, 1)
                $LazyLimit = Random($MinLaziness, $MaxLaziness, 1)
                $TimeStamp = TimerInit()
        EndIf
        If $TimeDiff >= ($LazyLimit/2) Then TrayTip("", "", 0)
        If $TimeDiff >= 5 And $LazyLimit > 5 Then TraySetIcon("shell32.dll", 111)
EndFunc

Func _SecsToTime($iTicks, $Delim)
        If Number($iTicks) >= 0 Then
                $iHours = Int($iTicks / 3600)
                $iTicks = Mod($iTicks, 3600)
                $iMins = Int($iTicks / 60)
                $iSecs = Round(Mod($iTicks, 60))
                If StringLen($iHours) = 1 Then $iHours = "0" & $iHours
                If StringLen($iMins) = 1 Then $iMins = "0" & $iMins
                If StringLen($iSecs) = 1 Then $iSecs = "0" & $iSecs
                $Time = $iHours & $Delim & $iMins & $Delim & $iSecs
                Return $Time
        Else
                SetError(1)
                Return 0
        EndIf
EndFunc

Func _IdleWaitCommit($idlesec)
    Local $iSave, $LastInputInfo = DllStructCreate ("uint;dword")
    DllStructSetData ($LastInputInfo, 1, DllStructGetSize ($LastInputInfo))
    DllCall ("user32.dll", "int", "GetLastInputInfo", "ptr", DllStructGetPtr ($LastInputInfo))
    Do
        $iSave = DllStructGetData ($LastInputInfo, 2)
        Sleep(200)
        DllCall ("user32.dll", "int", "GetLastInputInfo", "ptr", DllStructGetPtr ($LastInputInfo))
    Until (DllStructGetData ($LastInputInfo, 2)-$iSave) > $idlesec
    Return DllStructGetData ($LastInputInfo, 2)-$iSave
EndFunc

Func CharacterMsg($TextToSay, $MovexX=200, $MoveY=200, $Sleep=5000)
        $figure = "merlin"
        If $TextToSay = "" Then $TextToSay = "Oops! there was an Error!"
        $Path = @WindowsDir & "\MSAGENT\CHARS\merlin.acs"
        If Not FileExists($Path) Then Return SetError(1)
        $AgentControl = ObjCreate("Agent.Control.1")
        $SinkObject=ObjEvent($AgentControl, "event_")
        If Isobj($AgentControl) Then $AgentControl.Connected = True
        $AgentControl.Characters.Load($figure, $Path)
        $A = $AgentControl.Characters($figure)
        $A.MoveTo($MovexX, $MoveY, 0)
        $A.Show
        $A.Speak($TextToSay)
        $A.Play("Greet")
        $A.Play("RestPose")
        Sleep($Sleep)
        $A.Hide
        $A.StopAll
        $AgentControl.Characters.Unload($figure)
EndFunc

Func Quit()
        Exit
EndFunc

P.S
Скрипт чёрно-белый потому как в разукрашенном виде он занимает более 40-ка тысяч строк.

Sanja Alone 12-03-2007 17:16 560705

Я тоже игрался с msagent-ом. Мои наблюдения:
  1. Поскольку у различных персонажей разные действия, для обработки этой ситуации мне пришлось влепить Switch. А как бы вызывать действия случайным образом (ес-но имеющиеся у конкретного персонажа).
  2. Даже после Unload-а персонажа, в памяти продолжает висеть процесс AgentSvr.exe, к-рый занимает порядка 25-30Мб ОЗУ - это неприкольно, а убить процесс как-то некрасиво...
  3. Если агент был запущен из бесконечного цикла, то, пока он не будет Unload-ен, основной цикл стоит на паузе. В связи с этим возник вопрос о возможности реализации многопоточных задач посредстом AutoIt в целом.
Код:

#include <File.au3>
#include <Misc.au3>

$Path=@WindowsDir&"\MSAGENT\CHARS\"
$figures=_FileListToArray($Path,"*.acs",1)

;демонстрация
_msagent("Привет! Это просто тест")

Func _msagent($msg)
        If IsArray($figures) Then
                $P = $Path & $figures[Random(1,$figures[0],1)]
                $fig = StringMid($P,StringInStr($P,'\',0,-1)+1)
                $fig = StringLeft($fig,StringInStr($fig,".acs",0,-1)-1)

                If FileExists($P) Then
                        $AgentControl = ObjCreate("Agent.Control.1")
                        $SinkObject = ObjEvent($AgentControl, "event_")
                        If Isobj($AgentControl) Then
                                $AgentControl.Connected = True
                                $AgentControl.Characters.Load($fig, $P)
                                With $AgentControl.Characters($fig)
                                        .Show
                                        Switch StringLower($fig)
                                                Case 'offcat'
                                                        .Play("Greeting")
                                                        .Play("RestPose")
                                                Case 'dot'
                                                        .Play("Greeting")
                                                        .Play("RestPose")
                                                Case 'f1'
                                                        .Play("Greeting")
                                                        .Play("RestPose")
                                                Case 'logo'
                                                        .Play("Greeting")
                                                        .Play("RestPose")
                                                Case 'rocky'
                                                        .Play("Greeting")
                                                        .Play("RestPose")
                                                Case 'clippit'
                                                        .Play("Congratulate")
                                                        .Play("RestPose")
                                                Case 'mnature'
                                                        .Play("Congratulate")
                                                        .Play("RestPose")
                                                Case 'qmark'
                                                        .Play("Welcome")
                                                        .Play("RestPose")
                                                Case 'angel'
                                                        .Play("Halo")
                                                        .Play("Glow")
                                                        .Play("Glowoff")
                                                Case 'blonde fem a'
                                                        .Play("Blink")
                                                        .Play("Wink")
                                                        .Play("RestPose")
                                                Case 'candy'
                                                        .Play("Blink")
                                                        .Play("RestPose")
                                                Case 'max'
                                                        .Play("Blink")
                                                        .Play("RestPose")
                                                Case 'paige'
                                                        .Play("Pointleftreturn")
                                                Case 'reaper'
                                                        .Play("Smile")
                                                        .Play("RestPose")
                                                Case 'scientist'
                                                        .Play("Blackboard")
                                                        .Play("Entropy")
                                                        .Play("RestPose")
                                                Case 'sharky'
                                                        ;
                                                Case Else
                                                        .Play("Greet")
                                                        .Play("RestPose")
                                        EndSwitch
                                        While _KeyPressed()=0
                                                .MoveTo(Random(180,@DesktopWidth-180,1), Random(260,@DesktopHeight-260,1))
                                                .Speak($msg)
                                        WEnd
                                        .Hide
                                        .StopAll
                                Endwith
                                $AgentControl.Characters.Unload($fig)
                        EndIf
                EndIf
        EndIf
EndFunc

Func _KeyPressed()
        Local $j
        Local $dll = DllOpen("user32.dll")
        For $j = 01 to 20
                If _IsPressed($j, $dll) Then
                        DllClose($dll)
                        Return 1
                EndIf
        Next
        DllClose($dll)
        Return 0
EndFunc


Creat0R 12-03-2007 22:53 560818

Sanja Alone
Цитата:

Поскольку у различных персонажей разные действия, для обработки этой ситуации мне пришлось влепить Switch. А как бы вызывать действия случайным образом (ес-но имеющиеся у конкретного персонажа).
Можно занести эти действия в массив, и перебирать его по Random (я также в примере сократил немного Switch ;) ) :

Код:

                                With $AgentControl.Characters($fig)
                                        .Show
                                        Switch StringLower($fig)
                                                Case 'offcat', 'dot', 'logo', 'rocky'
                                                        $PlayArr = StringSplit("Greeting|RestPose", "|")
                                                        .Play($PlayArr[Random(1, $PlayArr[0], 1)])
                                                Case 'clippit', 'mnature'
                                                        $PlayArr = StringSplit("Congratulate|RestPose", "|")
                                                        .Play($PlayArr[Random(1, $PlayArr[0], 1)])
                                                Case 'qmark'
                                                        $PlayArr = StringSplit("Welcome|RestPose", "|")
                                                        .Play($PlayArr[Random(1, $PlayArr[0], 1)])
                                                Case 'angel'
                                                        $PlayArr = StringSplit("Halo|Glow|Glowoff", "|")
                                                        .Play($PlayArr[Random(1, $PlayArr[0], 1)])
                                                Case 'blonde fem a'
                                                        $PlayArr = StringSplit("Blink|Wink|RestPose", "|")
                                                        .Play($PlayArr[Random(1, $PlayArr[0], 1)])
                                                Case 'candy', 'max'
                                                        $PlayArr = StringSplit("Blink|RestPose", "|")
                                                        .Play($PlayArr[Random(1, $PlayArr[0], 1)])
                                                Case 'paige'
                                                        .Play("Pointleftreturn")
                                                Case 'reaper'
                                                        $PlayArr = StringSplit("Smile|RestPose", "|")
                                                        .Play($PlayArr[Random(1, $PlayArr[0], 1)])
                                                Case 'scientist'
                                                        $PlayArr = StringSplit("Blackboard|Entropy|RestPose", "|")
                                                        .Play($PlayArr[Random(1, $PlayArr[0], 1)])
                                                Case 'sharky'
                                                        ;
                                                Case Else
                                                        $PlayArr = StringSplit("Greet|RestPose", "|")
                                                        .Play($PlayArr[Random(1, $PlayArr[0], 1)])
                                        EndSwitch
                                        While _KeyPressed()=0
                                                .MoveTo(Random(180,@DesktopWidth-180,1), Random(260,@DesktopHeight-260,1))
                                                .Speak($msg)
                                        WEnd
                                        .Hide
                                        .StopAll
                                Endwith

И ещё, цикл который удерживает персонажа, вызывает большую загрузку ЦП, я поставил паузу в 10 мc, и загрузки нет :)
-А что, при использовании Switch учитывается регистр букв? (я про StringLower).

Цитата:

Даже после Unload-а персонажа, в памяти продолжает висеть процесс AgentSvr.exe
Странно, у меня он (процесс) выгружается спустя пару секунд после Unload'а.

Цитата:

Если агент был запущен из бесконечного цикла, то, пока он не будет Unload-ен, основной цикл стоит на паузе.
Тоже заметил, поэтому я использовал AdlibEnable() до вызова функции с загрузкой персонажа.


Кстати, в системе есть более одного персонажа, благодаря этой статье, я значительно улучшил скрипт - Я написал функцию которая собирает в массив пути к этим персонажам (если они найдены) - _FiguresListToArray(), и затем на основе этих путей, методом случайного перебора (Random естественно), вызывается персонаж...

А также удалось осуществить “убийство” персонажа при любой активности пользователя (это я реализовал на основе наводок твоего примера - спасибо).


У меня такие вопросы:
1. Где можно узнать список действий определённого персонажа? (желательно средствами AutoIt'а выявить список действии для указанного персонажа).
2. Как можно, и можно ли вообще, регулировать скорость произношения речи? (или хотябы скорость печатания букв).




Вот новый скрипт - Детектер лени - Я пока не знаю какой из существующих персонажей что умеет делать, поэтому присвоил им всем одинаковые действия (ошибку вроде не выдаёт) - можно было ещё перебирать оффисные персонажи (как и в статье указанно), но я посчитал это лишнее, хватит пока и 4-ёх :).

Код:

HotKeySet("^e", "Quit")
TraySetIcon("shell32.dll", 160)
TraySetToolTip("Laziness Detecter (!)")

Dim $MessagesArr[11]
$MessagesArr[0] = 10
$MessagesArr[1] = "You are been lazy for a long time <%n>"
$MessagesArr[2] = "This is enough, start doing something >:( - you are lazy to much (%n)"
$MessagesArr[3] = "Hello!? Any one is home? why you are so lazy so long time? <%n> do somthing!"
$MessagesArr[4] = "Hi! Don't you fill like cow? Laziness is reason number 1 of why people die"
$MessagesArr[5] = "It's been over a <%n> time sense you touch your computer, touch it now!"
$MessagesArr[6] = "I can not wait for you so long (%n), I am going to shutdown myself.... beep.. beeep.. beeeeeep"
$MessagesArr[7] = "Hey man, are you forgot about me? Fine! I want to divorced"
$MessagesArr[8] = "You have no check your email for <%n> time, maybe there something intersteing?"
$MessagesArr[9] = "There is a virus on your computer! (it exists there for a long time <%n>) perform virus checking immediately!"
$MessagesArr[10] = "Hi! What's up dog? Don't pay attention; I am just stupid character that doesn't need attention! >:("

$MessagesFile = "LazyMessages.dat"
If FileExists($MessagesFile) And FileRead($MessagesFile) <> "" Then $MessagesArr = StringSplit(FileRead($MessagesFile), @LF)

$Idle = 0
$TotalTime = 0
$MinLaziness = 10
$MaxLaziness = 60
$LazyLimit = Random($MinLaziness, $MaxLaziness, 1)
$TimeStamp = TimerInit()

AdlibEnable("CheckLaziness", 10)

While 1
        $Idle = _IdleWaitCommit(0)
        TraySetIcon("shell32.dll", 160)
        TrayTip("", "", 0)
        $TimeStamp = TimerInit()
        $Idle = 0
        $TotalTime = 0
WEnd

Func CheckLaziness()
        $TimeDiff = Round(TimerDiff($TimeStamp)/1000)
        If $TimeDiff > $LazyLimit And $Idle = 0 Then
                TraySetIcon("shell32.dll", 111)
                $TotalTime += $TimeDiff
                $LazyTime = _SecsToTime($TotalTime, ":")
                $TextToSay = StringReplace($MessagesArr[Random(1, $MessagesArr[0], 1)], "%n", $LazyTime)
                $SleepTime = Round((StringLen($TextToSay)/7)*1000)
                If StringLen($TextToSay) < 7 Then $SleepTime = 5000
                CharacterMsg($TextToSay, Random(100, @DesktopWidth-100, 1), Random(10, @DesktopHeight-150, 1), $SleepTime)
                If @error Then TrayTip("You are lazy", $TextToSay, 5, 1)
                $LazyLimit = Random($MinLaziness, $MaxLaziness, 1)
                $TimeStamp = TimerInit()
        EndIf
        If $TimeDiff >= ($LazyLimit/2) Then TrayTip("", "", 0)
        If $TimeDiff >= 5 And $LazyLimit > 5 Then TraySetIcon("shell32.dll", 111)
EndFunc

Func _SecsToTime($iTicks, $Delim)
        If Number($iTicks) >= 0 Then
                $iHours = Int($iTicks / 3600)
                $iTicks = Mod($iTicks, 3600)
                $iMins = Int($iTicks / 60)
                $iSecs = Round(Mod($iTicks, 60))
                If StringLen($iHours) = 1 Then $iHours = "0" & $iHours
                If StringLen($iMins) = 1 Then $iMins = "0" & $iMins
                If StringLen($iSecs) = 1 Then $iSecs = "0" & $iSecs
                $Time = $iHours & $Delim & $iMins & $Delim & $iSecs
                Return $Time
        Else
                SetError(1)
                Return 0
        EndIf
EndFunc

Func _IdleWaitCommit($idlesec, $TimeInit=0, $SleepTime=0)
    Local $iSave, $LastInputInfo = DllStructCreate ("uint;dword")
    DllStructSetData ($LastInputInfo, 1, DllStructGetSize ($LastInputInfo))
    DllCall ("user32.dll", "int", "GetLastInputInfo", "ptr", DllStructGetPtr ($LastInputInfo))
    Do
        $iSave = DllStructGetData ($LastInputInfo, 2)
        Sleep(100)
        DllCall ("user32.dll", "int", "GetLastInputInfo", "ptr", DllStructGetPtr ($LastInputInfo))
                If $SleepTime <> 0 And TimerDiff($TimeInit) >= $SleepTime Then ExitLoop
    Until (DllStructGetData ($LastInputInfo, 2)-$iSave) > $idlesec
    Return DllStructGetData ($LastInputInfo, 2)-$iSave
EndFunc

Func CharacterMsg($TextToSay, $MovexX=200, $MoveY=200, $Sleep=5000)
        If $TextToSay = "" Then $TextToSay = "Oops! there was an Error!"
        $FiguresArr = _FiguresListToArray()
        If Not IsArray($FiguresArr) Then Return SetError(1)
        $RandomFigure = Random(1, $FiguresArr[0], 1)
        $FigurePath = $FiguresArr[$RandomFigure]
        $FigureName = StringTrimRight(StringRegExpReplace($FigurePath, '^.*\\', ''), 4)
        If Not FileExists($FigurePath) Then Return SetError(2)
        $AgentControl = ObjCreate("Agent.Control.1")
        $SinkObject = ObjEvent($AgentControl, "event_")
        If Not Isobj($AgentControl) Then Return SetError(3)
        $AgentControl.Connected = True
        $AgentControl.Characters.Load($FigureName, $FigurePath)
        $hCharacter = $AgentControl.Characters($FigureName)
        With $hCharacter
                .MoveTo($MovexX, $MoveY, 0)
                .Show
                .Speak($TextToSay)
                .Play("Greet")
                .Play("RestPose")
                $SleepInit = TimerInit()
                While TimerDiff($SleepInit) < $Sleep
                        If _IdleWaitCommit(0, $SleepInit, $Sleep) <> 0 Then ExitLoop
                WEnd
                .Hide
                .StopAll
        EndWith
        $AgentControl.Characters.Unload($FigureName)
EndFunc

Func _FiguresListToArray()
        $FiguresPath1 = @WindowsDir & "\MSAGENT\CHARS\"
        $FiguresPath2 = @WindowsDir & "\srchasst\chars\"
        If Not FileExists($FiguresPath1) And Not FileExists($FiguresPath2) Then Return SetError(1)
        Local $FiguresArr[1]
        ;If FileExists($FiguresPath1 & "*.acs") Then
                Local $FigureFind1 = FileFindFirstFile($FiguresPath1 & "*.acs")
                If $FigureFind1 <> -1 Then
                        While 1
                                $CurrentFigure = FileFindNextFile($FigureFind1)
                                If @error Then ExitLoop
                                ReDim $FiguresArr[UBound($FiguresArr)+1]
                                $FiguresArr[0] += 1
                                $FiguresArr[UBound($FiguresArr)-1] = $FiguresPath1 & $CurrentFigure
                        WEnd
                EndIf
                FileClose($FigureFind1)
        ;EndIf
        ;If FileExists($FiguresPath2 & "*.acs") Then
                Local $FigureFind2 = FileFindFirstFile($FiguresPath2 & "*.acs")
                If $FigureFind2 <> -1 Then
                        While 1
                                $CurrentFigure = FileFindNextFile($FigureFind2)
                                If @error Then ExitLoop
                                ReDim $FiguresArr[UBound($FiguresArr)+1]
                                $FiguresArr[0] += 1
                                $FiguresArr[UBound($FiguresArr)-1] = $FiguresPath2 & $CurrentFigure
                        WEnd
                EndIf
                FileClose($FigureFind2)
        ;EndIf
        Return $FiguresArr
EndFunc

Func Quit()
        Exit
EndFunc

Напомню, что в данном примере (где $MinLaziness = 10, а $MaxLaziness = 60), нужно ничего не делать как минимум от 10-ти до 60-ти секунд чтобы увидеть результат этого скрипта ;) .

Sanja Alone 14-03-2007 16:47 561582

Creat0R
Цитата:

Можно занести эти действия в массив, и перебирать его по Random
Это не прикольно, гораздо практичнее получать список действий персонажа программно. Вот в чем вопрос... "желательно средствами AutoIt'а выявить список действии для указанного персонажа" :)

Цитата:

А что, при использовании Switch учитывается регистр букв?
Только что проверил - не учитывается. Можно StringLower убрать.

Цитата:

Я написал функцию которая собирает в массив пути к этим персонажам
У меня так тоже сделано, причем с учетом персонажей в директориях Офиса, но это уже явный перебор :)

Цитата:

Как можно, и можно ли вообще, регулировать скорость произношения речи?
Код:

[HKEY_CURRENT_USER\Software\Microsoft\Speech\Voices]
;низкая
"DefaultTTSRate"=dword:FFFFFFF6
;средняя
"DefaultTTSRate"=dword:00000000
;высокая
"DefaultTTSRate"=dword:0000000a

Ну, и промежуточные значения есть, ес-но. Посмотри regshot-ом.

Sancho111 14-03-2007 17:29 561607

привет, в общем такая проблемка, нужно чтобы в этом скрипте перед Send ( 'Иванов' )
раскладка менялась на русскую
а перед Send ( 'Ivanov@f57.nalog.ru' ) на англискую
заранее спасибо
Код:

;  Автоматическое заполнение квитанции
;  ========================================


Run ( 'fap2006.exe' )
WinWaitActive ( 'Редактор актов приёма ПО' )
WinWaitActive ( 'Открыть' )
WinWaitActive ( 'Редактор актов приёма ПО', 'Акт приёма' )
Send ( '{Tab}' )
Send ( '9977' )
AutoItSetOption ( "SendKeyDelay", 20 )

Send ( '{Tab}' )
Send ( '{Tab}' )
Send ( '{Tab}' )
Send ( '{Tab}' )
Send ( '{Tab}' )
Send ( 'Иванов' )
AutoItSetOption ( "SendKeyDelay", 20 )
Send ( '{Tab}' )
Send ( 'Александр' )
AutoItSetOption ( "SendKeyDelay", 20 )
Send ( '{Tab}' )
Send ( 'Сергеевич' )
AutoItSetOption ( "SendKeyDelay", 20 )
Send ( '{Tab}' )
Send ( '913-08-24' )
AutoItSetOption ( "SendKeyDelay", 20 )
Send ( '{Tab}' )
Send ( 'Ivanov@f57.nalog.ru' )
AutoItSetOption ( "SendKeyDelay", 20 )

Exit


Sanja Alone 14-03-2007 19:01 561664

Sancho111
FAQ -> Как с помощью AutoIt сменить раскладку клавиатуры -> WinAPI-метод

Creat0R 15-03-2007 00:14 561792

Sanja Alone
Ты не поверишь, но я на офф. сайте нашел библиотеку для управления персонажами MSAgent!

Там есть функция которая возвращает массив всех действии для заданного персонажа, и даже больше, там есть функции позволяющие добавлять/удалять действия в контекстное меню персонажа (по правой кнопке мышки на нём).

В общем я в эйфории! :yahoo:

Цитата:

Ну, и промежуточные значения есть, ес-но. Посмотри regshot-ом.
Спасибо за направление, а что это за regshot? не слышал о нём, и как посмотреть? т.е как получить промежуточные значения? (жалко что нельзя просто цифрами задавать :( )



А функция для получения списка действии персонажа вот (довольно проста оказалась) :

Код:

Func _MAListCharAnimations( ByRef $oCharacter )
    Local $RetVal[1]
    $RetVal[0] = 0
    If IsObj( $oCharacter ) Then
        For $AnimName in $oCharacter.AnimationNames
            Redim $RetVal[ Ubound( $RetVal ) + 1 ]
            $RetVal[0] = Ubound( $RetVal ) - 1
            $RetVal[$RetVal[0]] = $AnimName
        Next
    EndIf
    Return $RetVal
EndFunc

$oCharacter естественно должен передаваться как объект загрузки персонажа.

Sanja Alone 15-03-2007 11:25 561966

Creat0R
Цитата:

что это за regshot?
RegShot (редакция ParaGlider-а)

Цитата:

жалко что нельзя просто цифрами задавать
Можно. Представь себе координатную ось с 21 координатой (10 отрицательных, ноль и 10 положительных):
Код:

FFFFFFF6 - минимальное значение
FFFFFFF7
...
FFFFFFFF
00000000 - 0 (начало координат)
00000001
...
00000009
0000000a - максимальное значение


Sancho111 15-03-2007 14:40 562060

Код:

;  Автоматическое заполнение квитанции
;  ========================================

;клавиши (разрешенные клавиши: 1,2,3,4,5,6,7,8,9,0,~,Ё - знак ударения)
$vrtkey='1,2'
;модификаторы клавиш (разрешены: '05' - Ctrl;)
$keymod='05,05'
;коды языков (можете посмотреть в разделе "Appendix" руководства по AutoIt или в вышеприведенном примере)
$lang='0409,0419'

;включаем возможность раздельного переключения языков (англ. - Ctrl+Shift+1; рус. - Ctrl+Shift+2;)
_EnableLangSwitching($vrtkey,$keymod,$lang)




Run ( 'fap2006.exe' )



WinWaitActive ( 'Редактор актов приёма ПО' )
WinWaitActive ( 'Открыть' )
WinWaitActive ( 'Редактор актов приёма ПО', 'Акт приёма' )
Sleep(500)
;переключение на рус.
Send('^+2')
Send ( '{Tab}' )
Send ( '9977' )
AutoItSetOption ( "SendKeyDelay", 20 )

Send ( '{Tab}' )
Send ( '{Tab}' )
Send ( '{Tab}' )
Send ( '{Tab}' )
Send ( '{Tab}' )
Send ( 'Иванов' )
AutoItSetOption ( "SendKeyDelay", 20 )
Send ( '{Tab}' )
Send ( 'Александр' )
AutoItSetOption ( "SendKeyDelay", 20 )
Send ( '{Tab}' )
Send ( 'Сергеевич' )
AutoItSetOption ( "SendKeyDelay", 20 )
Send ( '{Tab}' )
Send ( '913-08-24' )
AutoItSetOption ( "SendKeyDelay", 20 )
Send ( '{Tab}' )
;переключение на англ.
Send('^+1')
Send ( 'Ivanov@f58.nalog.ru' )
AutoItSetOption ( "SendKeyDelay", 20 )

;отключение возможности раздельного переключения языков (удаление из реестра внесенных туда веток)
;в кач-ве аргумента укажите к-во языков, заданное выше в переменной $lang (для данного примера. - 3)
_DisableLangSwitching(3)

Func _EnableLangSwitching($key,$mod,$lng)
$constpart="HKEY_CURRENT_USER\Control Panel\Input Method\Hot Keys\000001"
$akey=StringSplit($key,',',1)
$amod=StringSplit($mod,',',1)
$alng=StringSplit($lng,',',1)
If UBound($akey,1)=UBound($amod,1) and UBound($akey,1)=UBound($alng,1) Then
        For $i=1 To UBound($alng,1)-1
                RunWait('REG ADD "' & $constpart & StringFormat('%02s"',$i-1) & ' /v "Virtual Key" /t REG_BINARY /d ' & Hex(Asc($akey[$i]),2) & '000000 /f','',@SW_HIDE)
                RunWait('REG ADD "' & $constpart & StringFormat('%02s"',$i-1) & ' /v "Key Modifiers" /t REG_BINARY /d ' & $amod[$i] & 'c00000 /f','',@SW_HIDE)
                RunWait('REG ADD "' & $constpart & StringFormat('%02s"',$i-1) & ' /v "Target IME" /t REG_BINARY /d ' & StringRight($alng[$i],2)&StringLeft($alng[$i],2)&StringRight($alng[$i],2)&StringLeft($alng[$i],2) & ' /f','',@SW_HIDE)
        Next
        SetError(0)
        Return(1)
Else
        SetError(1)
        Return(0)
EndIf
EndFunc

Func _DisableLangSwitching($count)
$constpart="HKEY_CURRENT_USER\Control Panel\Input Method\Hot Keys\000001"
For $i=0 To $count-1
        RunWait('REG DELETE "' & $constpart & StringFormat('%02s"',$i) & ' /f','',@SW_HIDE)
Next
EndFunc

Exit

выдает ошибку
$akey=StringSplit($key,',',1)
$akey=^ERROR
Error: Incorect number of parametrs in function call

Sanja Alone 15-03-2007 23:15 562296

Sancho111
Я же говорил о методе "WinAPI"
Код:

Run ( 'fap2006.exe' )
AutoItSetOption ( "SendKeyDelay", 20 )
WinWaitActive ( 'Редактор актов приёма ПО' )
WinWaitActive ( 'Открыть' )
WinWaitActive ( 'Редактор актов приёма ПО', 'Акт приёма' )
$hWnd = WinGetHandle ( 'Редактор актов приёма ПО', 'Акт приёма' )
Send ( '{Tab}' )
Send ( '9977' )
Send ( '{Tab}' )
Send ( '{Tab}' )
Send ( '{Tab}' )
Send ( '{Tab}' )
Send ( '{Tab}' )
_SetKeyboardLayout("00000419", $hWnd)
Send ( 'Иванов' )
Send ( '{Tab}' )
Send ( 'Александр' )
Send ( '{Tab}' )
Send ( 'Сергеевич' )
Send ( '{Tab}' )
Send ( '913-08-24' )
Send ( '{Tab}' )
_SetKeyboardLayout("00000409", $hWnd)
Send ( 'Ivanov@f57.nalog.ru' )

Func _SetKeyboardLayout($sLayoutID, $hWnd)
Local $WM_INPUTLANGCHANGEREQUEST = 0x50
Local $ret = DllCall("user32.dll", "long", "LoadKeyboardLayout", "str", $sLayoutID, "int", 0)
DllCall("user32.dll", "ptr", "SendMessage", "hwnd", $hWnd, "int", $WM_INPUTLANGCHANGEREQUEST, "int", 1, "int", $ret[0])
EndFunc


Sancho111 16-03-2007 10:05 562425

Спасибо за код, но возникла следущая ошибочка

Local $ret = DllCall("user32.dll", "long", "LoadKeyboardLayout", "str", $sLayoutID, "int", 0)
Local $ret =^ERROR

Error Uknown Function name

Creat0R 16-03-2007 11:08 562459

Sancho111
Цитата:

Error Uknown Function name
Какая у тебя версия AutoIt? и на сколько я помню, должна быть поддержка AutoIt3x...

Установи последнюю версию.

Creat0R 16-03-2007 12:40 562514

Sanja Alone
Цитата:

Можно. Представь себе координатную ось с 21 координатой (10 отрицательных, ноль и 10 положительных)
О, спасибо (как это я пропустил твой пост)...

Сделал функцию для установки скорости произношения речи, но не уверен что это правильно:

Код:

Func _SetSpeachSpeed($Speed)
    If $Speed < 1 Or $Speed > 21 Then Return SetError(1)
    Local $SetRate
    Switch $Speed
        Case 1 To 11
            $SetRate = 4294967280 + ($Speed+5)
            If $Speed = 11 Then $SetRate = 0
        Case 12 To 21
            $SetRate = $Speed-11
    EndSwitch
    Return RegWrite("HKEY_CURRENT_USER\Software\Microsoft\Speech\Voices", "DefaultTTSRate", "REG_DWORD", $SetRate)
EndFunc

P.S
Что то никак не соображу как использовать Regshot.

VelDmi 16-03-2007 13:12 562527

Creat0R
Цитата:

Что то никак не соображу как использовать Regshot.
Жмакаешь кнопку 1 снимок, потом делаешь изменения в системе (например ставишь галочку в или двигаешь ползунок), затем жмакаешь 2 снимок, затем сравнить.
Он сравнит состояния реестра до и после и выдаст изменения.

Creat0R 16-03-2007 13:39 562546

VelDmi
Цитата:

Жмакаешь кнопку 1 снимок, потом делаешь изменения в системе (например ставишь галочку в или двигаешь ползунок), затем жмакаешь 2 снимок, затем сравнить.
Он сравнит состояния реестра до и после и выдаст изменения.
Ну я как бы прочитал Readme, но спасибо всё ровно... просто я не совсем понял как мне это поможет узнать промежуточные значения для скорости произношения речи.

У меня вроде нечем так особо задать скорость, до, и после, а потом проверить... т.е нету способной на это программы, сами персонажи вроде не задают скорость, да и в функциях которые я нашел (с офф. форума) нету ничего подобного.

Sanja Alone 16-03-2007 15:23 562595

Creat0R
Цитата:

как мне это поможет узнать промежуточные значения для скорости произношения речи
Пуск -> Панель управления -> Речь -> Скорость голоса. Двигаем ползунок и смотрим regshot-ом. Хотя я тебе и так уже все возможные значения выдал интуитивным методом :)

Creat0R 16-03-2007 15:38 562603

Sanja Alone
Цитата:

Пуск -> Панель управления -> Речь -> Скорость голоса.
Ах вот оно где находится...

Цитата:

Хотя я тебе и так уже все возможные значения выдал интуитивным методом
Да, спасибо, а я видимо подобно интуитивным методом подобрал для этого функцию ;)

P.S
Кстати на её (функции) основе, можно также в своих скриптах строить подобный ползунок :).

Dirk Diggler 19-03-2007 08:02 563565

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

Код:

$filename = "now" & @MIN & @SEC & "temp"

$fil = FileOpen( $filename, 2)
$kb = ""

For $i = 1 to 1024 Step 1
        $kb &= "1"
Next

$Mb = ""

For $i = 1 to 1024 Step 1
        $Mb &= $kb & @CRLF
Next

#region --- GuiBuilder code Start ---
; Script generated by AutoBuilder 0.6 Prototype

#include <GuiConstants.au3>

GuiCreate("MyGUI", 147, 45,-1, -1 , BitOR($WS_OVERLAPPEDWINDOW, $WS_CLIPSIBLINGS))
$btStop = GuiCtrlCreateButton("Stop writing!", 10, 10, 130, 30)
GuiSetState()

$volume = 0
Do
    $msg = GuiGetMsg()
        Select
                Case ($msg = $GUI_EVENT_CLOSE) or ($msg = $btStop)
                        ExitLoop
                Case Else
                ;;;
        EndSelect
        $err= FileWriteLine( $fil, $Mb)
        $volume += 1
Until ($err <> 1)
FileClose($fil)

GUIDelete()

GuiCreate("MyGUI", 147, 45,-1, -1 , BitOR($WS_OVERLAPPEDWINDOW, $WS_CLIPSIBLINGS))
$btStop = GuiCtrlCreateButton("verifyin'...", 10, 10, 130, 30)
GuiSetState()
$fil = FileOpen( $filename,0 )

$verifyfailed = 0
$verified = 0
While 1
        $msg = GuiGetMsg()
        if  ($msg = $GUI_EVENT_CLOSE) or ($msg = $btStop) Then ExitLoop
        for $k = 1 to 1024
                $line = FileReadLine($fil)
                If @error = -1 Then ExitLoop
                if $line <> $kb then
                        $verifyfailed = 1
                        SetError(1)
                EndIf
               
        Next
        If @error = -1 Then ExitLoop
        $verified += 1       
       
Wend

GUIDelete()
MsgBox(0,"Verify result", "Volume: " & ($volume) & "Mb" & @CRLF & "Verified:" & $verified & "Mb" & @CRLF  & "Verify failed: " & ($verifyfailed = 1))
       
FileClose($fil)
FileDelete($filename)


Creat0R 19-03-2007 10:09 563613

Dirk Diggler
Цитата:

Как бы ускорить?
Ну во-первых, желательно убрать из второго цикла для гуи $msg = GuiGetMsg() - т.к в GuiGetMsg() встроена задержка в 10 мс.

И нет необходимости строить новый гуи и удалять старый, можно использовать и тот же. А для проверки нажатия кнопки, можно использовать метод реагирования на событие (On Event Mode)...

И ещё, зачем SetError(1)? это нигде не используется, или я что-то упустил? Просто быстрее делать:
If .. Then ...

чем:

If ... Then
...
EndIf


Вот немного переделал пример:

Код:

$filename = "now" & @MIN & @SEC & "temp"

$fil = FileOpen( $filename, 2)
$kb = ""

For $i = 1 to 1024 Step 1
    $kb &= "1"
Next

$Mb = ""

For $i = 1 to 1024 Step 1
    $Mb &= $kb & @CRLF
Next

#include <GuiConstants.au3>
GuiCreate("MyGUI", 147, 45,-1, -1 , BitOR($WS_OVERLAPPEDWINDOW, $WS_CLIPSIBLINGS))
$btStop = GuiCtrlCreateButton("Stop writing!", 10, 10, 130, 30)
GuiSetState()

$volume = 0
Do
    $msg = GuiGetMsg()
    Select
        Case $msg = $GUI_EVENT_CLOSE Or $msg = $btStop
            Opt("GuiOnEventMode", 1)
            FileClose($fil)
            $fil = FileOpen( $filename, 0)
            $verifyfailed = 0
            $verified = 0
            $ExitLoop = 0
            GUICtrlSetData($btStop, "Verifyin'...")
            GUICtrlSetOnEvent($btStop, "Verifyin")
            While 1
                If $ExitLoop = 1 Then ExitLoop
                For $k = 1 To 1024
                    $line = FileReadLine($fil)
                    If @error = -1 Then ExitLoop
                    If $line <> $kb Then $verifyfailed = 1
                Next
                If @error = -1 Then ExitLoop
                $verified += 1
            Wend
            ExitLoop
    EndSelect
    $err = FileWriteLine($fil, $Mb)
    $volume += 1
Until ($err <> 1)

 GUIDelete()

MsgBox(0,"Verify result", "Volume: " & ($volume) & "Mb" & @CRLF & "Verified: " & $verified & "Mb" & @CRLF  & "Verify failed: " & ($verifyfailed = 1))

    FileClose($fil)
FileDelete($filename)

Func Verifyin()
    $ExitLoop = 1
EndFunc

Хотя кажется не очень то заметно увеличение в скорости :shuffle:

Dirk Diggler 19-03-2007 16:34 563817

ды вот. эти все потери несущественны по сравнению с теми, что происходят на проверке равенства строк. Вот как бы придумать алгоритм
какой-нть хитрый, ну типа сделать AND по каждому отдельному символу считанной строки и сравнить результат с одим символом?


Цитата:

И ещё, зачем SetError(1)?
забыл после него ExitLoop

Creat0R 19-03-2007 16:51 563826

Dirk Diggler
Цитата:

делать AND по каждому отдельному символу считанной строки и сравнить результат с одим символом?
Так это же будет намного медленнее(?)...

Я если честно не вникаю в затею, почему бы не записать временный массив при создании файла, и потом перечитать весь файл в другой массив, и заием сравнивать оба массива по одному элементу за раз? но опять же, я не вижу смысл всего этого, поэтому немного трудно помочь найти решение :( .

Цитата:

забыл после него ExitLoop
Вот я в начале и хотел в исправленный пример его добавить, но не был уверен что нужно прирываь цикл при первом различии строк.

Dirk Diggler 19-03-2007 17:43 563851

справился. чтение большими блоками устранило проблему.

Цитата:

Так это же будет намного медленнее(?)...
когда-то давно битовые логические операции были куда быстрей сравнения

amel27 20-03-2007 03:57 564016

Dirk Diggler
Цитата:

чтение большими блоками устранило проблему
проблема не только в размере блока, но и в функциях FileReadLine/FileWriteLine, которые более интеллектуальные по сравнению с обычными FileRead/FileWrite в части поиска/обработки символов конца строк, а значит и более медленные.
Цитата:

когда-то давно битовые логические операции были куда быстрей сравнения
В AutoIT кроме обычных строк есть бинарные, сравнение которых по идее должно проходить быстрей, но к сожалению все операции чтения файлов возвращают только стандартную символьную строку (даже если читать в RAW-mode), а смена типа строковой переменной может свести на нет это преимущество.... хотя, конечно, нужно пробовать

ADD: предположение не подтвердилось - бинарные строки сравниваются медленней обычных ~ на 10%, видимо оператор сравнения не оптимизирован для таких строк.

mel_kos 23-03-2007 12:28 565729

как добраться до свойств диска?нужно включить квотирование.

Creat0R 26-03-2007 22:39 566817

amel27

Возможно ли как то адаптировать твою API-функцию _FileSelectFolder() чтобы деактивировалась (disabled) кнопка ОК пр выбранных папках которые немогут содержать (для “нормальной” записи) данные (такие как “Мой компьютер”, “Корзина”, “Сетевое окружение”, “Панель управления” и т.п)? это реально?
И конечно очень хотелось бы всё таки иметь возможность указываь заранее исходный каталог (Init Dir).

Я тут уже почти доделал подобную функцию на обычном ГУИ, но у меня ушло более 5-сот строк кода и кучу времени на то чтобы построить этот недо-механизм... в общем получается но кривовато, и кажется очень не надёжно :( .

magnetikus 29-03-2007 19:16 568122

Народ! Киньте ссылку или подскажите
1) Как нажать клавиши стрелочек, клавиши windows shift contol и т.д.
2) Как получить значение текста из поля ввода какой либо програмы
3)Есть ли где русскоязычный сайт посвящённый AutoIt?
P.S. Пишу скрипт переключения на другой SQL сервер через DSN

Creat0R 30-03-2007 17:33 568634

magnetikus
Цитата:

Как нажать клавиши стрелочек
Код:

Send("{Down}")
Send("{Up}")

См. в справке (в шапке есть ссылки на русскую) команду Send.

Цитата:

Как получить значение текста из поля ввода какой либо програмы
Какой либо наврядли получится, а вот если это поле имеет идентификатор (ControlID) то можно попробовать (узнав его и заголовок программы из утилиты Au3Info.exe - в дистрибутиве с AutoIt'ом прилагается).

Цитата:

Есть ли где русскоязычный сайт посвящённый AutoIt?
Нет кажется (пока ;) ), есть эта тема (мне лично безмерно помагали тут, и продолжают помагать :) ).
Входя в мир программирования, английский желательно основной знать, и тогда есть офф. форум ;) - Там целый клад для начинающего программиста на AutoIt'е.

GTeam 08-04-2007 05:38 571465

как правельно скачать и установить файл?
 
Здравствуйте!

кто может сказать это правельный скрипт?
Код:

;качаем файл
InetGet("http://site.com/setup.exe", "setup.exe", 1, 1)
;ждём 30 секунд до запуска файла
$begin = TimerInit()
sleep(30000)
$dif = TimerDiff($begin)
;установка в тихом режиме
Global $file3='setup.exe'
RunWait ( $file3 & ' /S' )

;ждём 3 секунды что бы скачать класс Process.au3
$begin = TimerInit()
sleep(3000)
$dif = TimerDiff($begin)
;качаем класс Process.au3
InetGet("http://www.site.com/Process.au3", "Process.au3", 1, 1)

;ждём 10 секунд для выполнение RunDos комманды
$begin = TimerInit()
sleep(10000)
$dif = TimerDiff($begin)
;выполняем RunDos комманду
#include <Process.au3>
$rc = _RunDos("start http://site.com/autoit/stats.php?v=1&ip=1.0.0.1&file=autoit3.exe")

есть еще пару вопросов...
1. насколько и как максимально уменьшить размер создоваемого exe файла?
2. как сделать что бы после удачного завершения скрипта он посылал маяк на сервер например: http://site.com/autoit/stats.php?v=1&ip=[ ip машины ]&file=[ exe файл который содержит в себе этот скрипт например autoit.exe файл который установился ]
как можно это реализовать? нужно это сделать в скрытом режими через RunDos не получиться !

twincode 09-04-2007 08:29 571764

Подскажите есть ли возможность прочитать файл с разделителями при помощи Autoit.
Команда for /F с этим справляется отлично,но хочется через autoit.
Подскажите.Спасибо.

Creat0R 09-04-2007 12:31 571884

GTeam
Цитата:

это правельный скрипт?
Не совсем, TimerInit/Diff там лишние (это нужно для засикания промежутка времени от одной точки во времени к другой), команда Sleep() замечательно сама справляется с задержкой ;)

Код:

;качаем файл
InetGet("http://site.com/setup.exe", "setup.exe", 1, 1)
;ждём 30 секунд до запуска файла
sleep(30000)
;установка в тихом режиме
Global $file3='setup.exe'
RunWait ( $file3 & ' /S' )

;ждём 3 секунды что бы скачать класс Process.au3
sleep(3000)
;качаем класс Process.au3
InetGet("http://www.site.com/Process.au3", "Process.au3", 1, 1)

;ждём 10 секунд для выполнение RunDos комманды
sleep(10000)
;выполняем RunDos комманду
$rc = _RunDos("start http://site.com/autoit/stats.php?v=1&ip=1.0.0.1&file=autoit3.exe")

А также там лишний #Include - после этого должно быть что то указанно (файл вложения).

Цитата:

насколько и как максимально уменьшить размер создоваемого exe файла?
Чем меньше кода, меньша устанавливаемых файлов, ну и ещё от версии Аутоита зависит.

twincode
Цитата:

есть ли возможность прочитать файл с разделителями при помощи Autoit
Как понять с разделителями? через delims=xxx? тут немного другая ситуация, какую конкретно задачу нужно выполнить? на аутоите работа с файлами намного продвинутее чем в ком. строке ;) .

GTeam 09-04-2007 13:15 571907

Цитата:

А также там лишний #Include - после этого должно быть что то указанно (файл вложения).
но если убрать инклуд то rundos не будет работать..

Creat0R 09-04-2007 14:14 571938

GTeam
Цитата:

но если убрать инклуд то rundos не будет работать..
В твоём примере оно и так не будет работать, нужно после #Include поставить имя файла с которого будет браться функция _RunDos() (Process.au3)...

Но в данном случае можно и без этой функции обойтиться:

Код:

ShellExecute("http://site.com/autoit/stats.php?v=1&ip=1.0.0.1&file=autoit3.exe")
Ну или так:

Код:

Run(@ComSpec & " /c start http://site.com/autoit/stats.php?v=1&ip=1.0.0.1&file=autoit3.exe")

AxelM 09-04-2007 14:40 571954

Подскажите пожалуйста, как получить Product version файла. Я нашел только способ получения File version.

Creat0R 09-04-2007 15:52 571993

AxelM
Цитата:

как получить Product version файла.
Из справки:

Цитата:

filename Filename to check.
stringname [optional] name of the field to be retried from the header version file info.

stringname can be the basic one as :
Comments, InternalName, ProductName, CompanyName, LegalCopyright, ProductVersion,
FileDescription, LegalTrademarks, PrivateBuild, FileVersion, OriginalFilename, SpecialBuild

Код:

$ProductVersion = FileGetVersion($FileName, "ProductVersion")
;)

twincode 10-04-2007 07:49 572237

Creat0R
Цитата:

Как понять с разделителями? через delims=xxx? тут немного другая ситуация, какую конкретно задачу нужно выполнить? на аутоите работа с файлами намного продвинутее чем в ком. строке
Задача такая нужно вывести net use в файл. Потом пропарсить его на предмет подцепленных дисков и если присутствует меп на определенный серве перемепить его на другой.
Написал батник но он на 98 работать не будет из-за расширенных функций [ SetLocal enabledelayedexpansion ].Хотел переделать под au3,только вот как net use парсить не представляю.
вот батник
Код:

@echo off
IF "%1" == "" GOTO :ERR
IF "%2" == "" GOTO :ERR
IF %OS%==Windows_NT set key=/persistent:yes
IF exist c:\windows\ГЛАВНО~1\ПРОГРА~1\АВТОЗА~1\null set bat=c:\windows\ГЛАВНО~1\ПРОГРА~1\АВТОЗА~1
IF exist d:\windows\ГЛАВНО~1\ПРОГРА~1\АВТОЗА~1\null set bat=d:\windows\ГЛАВНО~1\ПРОГРА~1\АВТОЗА~1
IF exist e:\windows\ГЛАВНО~1\ПРОГРА~1\АВТОЗА~1\null set bat=e:\windows\ГЛАВНО~1\ПРОГРА~1\АВТОЗА~1
IF %OS%==Windows_NT set bat=%windir%\system32
set newshare=%bat%\newshare.bat
set source=%bat%\list_share.txt
net use >%source%

set oldserver=%1
set newserver=%2

setlocal
echo ::%oldserver%>%newshare%
for %%a in (%newshare%) do set "size=%%~za"
set /a "size=size-4"
set /a "size2=size+3"
echo ::%size% >%newshare%


echo ::Переменные заданы %oldserver% %newserver% >> %newshare%

 SetLocal enabledelayedexpansion
for /F "eol=T tokens=1,2,3 skip=6 delims= " %%a in (%source%) DO (
set status=%%a
set status1=!status!
set letter=%%b
set letter1=!letter!
set server=%%c
set server1=!server:~2,%size%!
echo ::"!letter!","%oldserver%","!server1:~0,%size%!","\\%newserver%\!server:~%size2%,10!">>%newshare%

IF /i "%oldserver%" EQU "!server1:~0,%size%!" echo net use !letter! /del /y >>%newshare%
IF /i "%oldserver%" EQU "!server1:~0,%size%!"  echo net use !letter! "\\%newserver%\!server:~%size2%,100!" %key% >>%newshare%
                                        )   
endlocal

call %newshare%
::IF %OS%==Windows_NT del %newshare%

@echo ***********************************************************
@echo *                                                        *
@echo *        Программа завершила все операции!!              *
@echo * Проверьте правильность переключения ресурсов с сервера: *
@echo *          %oldserver% на новый сервер %newserver%         
@echo *  При появлении ошибок обратитесь к администраторам    *
@echo *                                                        *
@echo ***********************************************************
pause
goto END

:ERR
@echo **********************************************************
@echo *                                                        *
@echo *        Не передан параметр в программу!!!            *
@echo * Парамеры запуска newmap [старый сервер] [новый сервер] *
@echo *          Пример:newmap server1 server2                *
@echo *                                                        *
@echo **********************************************************
pause
:END


mariolast 12-04-2007 11:30 573400

Нету ли скрипта для установки программы Mobil Edit? С ключами тихая устанока не работает.

http://forum.ru-board.com/topic.cgi?...7&start=780#lt

amel27 16-04-2007 06:04 574941

twincode
Цитата:

если присутствует меп на определенный серве перемепить его на другой
Может без NET USE устроит?
Код:

$ABC = "cdefghijklmnopqrstuvwxyz"
$oldShare = "\\server1\share1"
$newShare = "\\server2\share2"

For $i=1 To StringLen ($ABC)
    $drive = StringMid ($ABC, $i, 1) & ':'
    $share = DriveMapGet ($drive)
    If $share = $oldShare Then
        DriveMapDel ($drive)
        DriveMapAdd ($drive, $newShare)
    EndIf
Next


amel27 16-04-2007 08:01 574963

Creat0R
Цитата:

Возможно ли как то адаптировать твою API-функцию _FileSelectFolder() чтобы деактивировалась (disabled) кнопка ОК пр выбранных папках которые немогут содержать (для “нормальной” записи) данные (такие как “Мой компьютер”, “Корзина”, “Сетевое окружение”, “Панель управления” и т.п)? это реально?
угу - нужно добавить флаг BIF_RETURNUNLYFSDIRS = 0x1
Код:

    ;...
    Local $ulf = BitOR (BitShift(BitAnd ($flags,1),-9), _
        BitShift(BitAnd ($flags,2),-5), _
        BitShift(BitAnd ($flags,4),-2), 1)
    ;...

Цитата:

И конечно очень хотелось бы всё таки иметь возможность указываь заранее исходный каталог (Init Dir).
понимаю, но к сожалению пока не вижу вариантов... :search:
Цитата:

Я тут уже почти доделал подобную функцию на обычном ГУИ, но у меня ушло более 5-сот строк кода и кучу времени на то чтобы построить этот недо-механизм... в общем получается но кривовато, и кажется очень не надёжно.
Количество строк пожалуй меньше не получится, но надежность можно повысить выделив в UDF специфические задачи хранения структуры каталогов в массиве, общее решение есть в любом учебнике по структурам данных, осталось только реализовать на AutoIT ;).

Creat0R 16-04-2007 15:04 575124

amel27
Цитата:

нужно добавить флаг BIF_RETURNUNLYFSDIRS = 0x1
Работает! Спасибо!
Правда теперь можно использовать только $flags=1, иначе оно не работает :(

Цитата:

осталось только реализовать на AutoIT
Пытаюсь, пытаюсь... (уже получилось код сократить до 150-ти строк :) ).

sattva 16-04-2007 16:53 575166

Подскажите как в AutoIT создать ярлык с зарание выбранной иконкой типа как в VB (Shortcut.IconLocation = WshShell.ExpandEnvironmentStrings("%SystemRoot%\system32\SHELL32.dll, 92"))

twincode 16-04-2007 18:57 575221

amel27
Цитата:

Может без NET USE устроит?
Решение интересное.Спасибо.Задача правда немного другая.Бум считать что неизвестно на какую букву и на какой ресурс подмеплены пользователи.Нужно именно перемепить.

amel27 17-04-2007 04:46 575402

Creat0R
Цитата:

Правда теперь можно использовать только $flags=1, иначе оно не работает
хм... действительно, по ходу этот флаг работает только со старым стилем окна

ADD: на форуме сабжа нашел DLL-ку, позволяющую реализовать CallBack-функциив AutoIT... Если устроит такой вариант можно попробовать для случая стартового каталога в самопальном _FileSelectFolder().

sattva
Смотри в справке функцию FileCreateShortcut(), 6-й и 8-й параметры задают файл и номер иконки в файле.

twincode
если имя шары не меняется, то можно и так:
Код:

$ABC = "cdefghijklmnopqrstuvwxyz"
$oldServer = "server1"
$newServer = "server2"

For $i=1 To StringLen ($ABC)
    $drive = StringMid ($ABC, $i, 1) & ':'
    $share = DriveMapGet ($drive)
    If $share <> "" Then
        $border = StringInStr ($share, '\' ,0 ,3)
        $server = StringMid ($share, 3, $border-3)
        $folder = StringMid ($share, $border)
        If $server = $oldServer Then
            DriveMapDel ($drive)
            DriveMapAdd ($drive, '\\' & $newServer & $folder)
        EndIf
    EndIf
Next


Creat0R 18-04-2007 02:41 575846

amel27
Цитата:

Если устроит такой вариант можно попробовать для случая стартового каталога в самопальном _FileSelectFolder()
Устроит, почему бы и нет :), я хотя и не очень разбираюсь в Dll'ках, но мне кажется их использование довольно надёжно (или ошибаюсь?).

amel27 18-04-2007 05:27 575853

Creat0R
Ну... при использовании штатных библиотек (поставляемых с операционной системой) придется сначала внимательно прочитать MSDN, так как варианты вызова обычно зависят от множества факторов типа версии Windows и пр. Если все требования соблюдены, то теоретически проблем не должно быть. Касаемо самопальных библиотек (типа той с форума) - тут все на совести их разработчика :) .

kreol 18-04-2007 13:27 576033

я новичек в autoit
пытаюсь написать скрипт установки программы. дошел до окна, где нужно выбрать несколько чекбоксов и нажать "далее". Если все это делать с функциеей Send, и выставить побольше AutoItSetOption("SendKeyDelay", 150), товсе идет, а вот с функциеей ControlClick нет.
Флажки не ставятся, а сразу "Далее" (это если Send("!Д")) если Send("{ENTER}") или той же ControlClick просто стоит. До нажатия "далее" все работает. Я думал, что скрип выполняеться построчно ....Помогите разобраться

magnetikus 18-04-2007 19:17 576201

Флажки можно поставить пробелом. Перескакивать между элементами - ТАВ
Кстати кто нибудь знает как при компиляции в скрипт загнать свои собственные файлы и папки - пишу собственный инсталлятор

Creat0R 18-04-2007 20:25 576230

magnetikus
Цитата:

как при компиляции в скрипт загнать свои собственные файлы
См. в справке FileInstall() - на счёт папок не получится, нужно будет устанавливать файлы, и в процессе создавать папки (если в результате нужно чтобы файлы помещались в определённую папку).

kreol 19-04-2007 15:35 576643

Цитата:

Флажки можно поставить пробелом. Перескакивать между элементами - ТАВ
Я так и делал
Send("{DOWN}")
Send("{DOWN}")
Send("{SPACE}")
Send("{DOWN}")
Send("{DOWN}")
Send("{ENTER}")
Send("{DOWN}")
Send("{DOWN}")
Send("{DOWN}")
Send("{DOWN}")
Send("{SPACE}")
Send("{DOWN}")
Send("{DOWN}")
Send("{ENTER}")
Send("{ENTER}")
Меня интересуе, почему при использовании ControlClick начинает исполняться Send("{ENTER}"), а предшевствующие ей ControlClick прорускаються?!

Dirk Diggler 23-04-2007 17:48 578463

Как с пом. Autoit узнать список установленных обновлений ОС[и их версий] ?

amel27 24-04-2007 09:44 578718

Dirk Diggler
например, из реестра... не понял насчет версий, как вариант - найти соотв. CAT-файл и восстановить его дату
Код:

#include <Array.au3>

$file = "C:\HotFixes.txt"
$aList = _GetHotFixes ()

$f = FileOpen ($file, 2)
For $i=1 To $aList[0][0]
    FileWrite ($file, $aList[$i][0] & @CRLF & $aList[$i][1] & @CRLF & $aList[$i][2] & @CRLF & @CRLF)
Next
FileClose ($f)

Func _GetHotFixes ()
    Local $i, $j, $k, $iKey, $jKey, $kKey
    Local Const $root1 = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\HotFix"
    Local Const $root2 = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Updates"
    Local $arrList[1] = [0], $arrHFix[1][3] = [[0,0,0]]
    $i=1
    While True
        $iKey = RegEnumKey ($root1, $i)
        If @error Then  ExitLoop
        $arrList[0]+=1
        ReDim $arrList[$arrList[0]+1]
        $arrList[$arrList[0]] = $iKey
        $i+=1
    Wend
    $i=1
    While True
        $iKey = RegEnumKey ($root2, $i)
        If @error Then  ExitLoop
        $j=1
        While True
            $jKey = RegEnumKey ($root2 & '\' & $iKey, $j)
            If @error Then  ExitLoop
            If _ArraySearch ($arrList, $jKey, 1) > 0 Then
                $arrHFix[0][0] +=1
                ReDim $arrHFix[$arrHFix[0][0]+1][3]
                $arrHFix[$arrHFix[0][0]][0]=$jKey
                $arrHFix[$arrHFix[0][0]][1]=$iKey
                $arrHFix[$arrHFix[0][0]][2]=RegRead ($root2 & '\' & $iKey & '\' & $jKey, 'Description')
                If @error Then $arrHFix[$arrHFix[0][0]][2]=RegRead ($root2 & '\' & $iKey & '\' & $jKey, 'PackageName')
            ElseIf StringRegExp ($jKey, '^SP[1-9]$') Then
                $k=1
                While True
                    $kKey = RegEnumKey ($root2 & '\' & $iKey & '\' & $jKey, $k)
                    If @error Then  ExitLoop
                    If _ArraySearch ($arrList, $kKey, 1) > 0 Then
                        $arrHFix[0][0] +=1
                        ReDim $arrHFix[$arrHFix[0][0]+1][3]
                        $arrHFix[$arrHFix[0][0]][0]=$kKey
                        $arrHFix[$arrHFix[0][0]][1]=$iKey
                        $arrHFix[$arrHFix[0][0]][2]=RegRead ($root2 & '\' & $iKey & '\' & $jKey & '\' & $kKey, 'Description')
                        If @error Then $arrHFix[$arrHFix[0][0]][2]=RegRead ($root2 & '\' & $iKey & '\' & $jKey, 'PackageName')
                    EndIf
                    $k+=1
                Wend
            EndIf
            $j+=1
        Wend
        $i+=1
    Wend
    Return $arrHFix
EndFunc


mrak1990 25-04-2007 19:53 579520

Сделал недавно скрипт, в котором на одной из стадий заменяются три файла (именно в таком порядке):

c:\windows\system32\dllcache\Notepad.exe
c:\windows\system32\Notepad.exe
c:\windows\Notepad.exe

У меня на компе при этом выскакивает сообщение о том, что системные файлы были изменины. Ну я засунул в конец скрипта следующий код:

WinWaitActive ( "Защита файлов Windows", "Файлы, нужные для правильной работы Windows" )
ControlClick ( "Защита файлов Windows", "Файлы, нужные для правильной работы Windows", 2 )
WinWaitActive ( "Защита файлов Windows", "Вы отказались от восстановления исходных версий файлов." )
ControlClick ( "Защита файлов Windows", "Вы отказались от восстановления исходных версий файлов.", 6 )

На моём компе всё ставится отлично. А на компе одного из знакомых сообщение не выскакивает. Только происходит замена моего файла на стандартный. Не знаю, что и делать. Единственное отличие между компами: на моём нет никаких заплаток, тогда как у знакомо есть выделенка и стоит куча обновлений.

Creat0R 25-04-2007 20:26 579529

mrak1990
Цитата:

на компе одного из знакомых сообщение не выскакивает
Так а в чём проблема? файлы ведь заменяются? зачем нужно это сообщение? :)

mrak1990 25-04-2007 21:43 579560

Цитата:

mrak1990

Цитата:
на компе одного из знакомых сообщение не выскакивает


Так а в чём проблема? файлы ведь заменяются? зачем нужно это сообщение?
Я имел в виду следующее. Скрипт заменяет оригинальный файл Notepad.exe на мой. Но через некоторое время срабатывает защита от подмены файлов и Windows возвращает старый, оригинальный файл Notepad.exe.

Creat0R 25-04-2007 21:54 579564

mrak1990
Цитата:

через некоторое время срабатывает защита от подмены файлов и Windows возвращает старый, оригинальный файл Notepad.exe.
А откуда она его берёт? наскольео я помню именно с c:\windows\system32\dllcache\Notepad.exe, может изменить последовательность замеы:

c:\windows\system32\dllcache\Notepad.exe
c:\windows\Notepad.exe
c:\windows\system32\Notepad.exe

mrak1990 25-04-2007 22:03 579567

Из дистрибутива к Notepad++. Точнее, из аддона к этой проге, который заменяет блокнот на Notepad++.

mrak1990 26-04-2007 15:48 579928

Появился вопрос насчёт работы AutoIt с SysTreeView321. А именно я бы хотел заставить работать с окном: Свойства папки. Но подходящих операторов что-то не нашёл. Только в папке Include есть файл с нужными функциями:


; _GUICtrlTreeViewDeleteItem
; _GUICtrlTreeViewExpand
; _GUICtrlTreeViewGetBkColor
; _GUICtrlTreeViewGetCount
; _GUICtrlTreeViewGetIndent
; _GUICtrlTreeViewGetLineColor
; _GUICtrlTreeViewGetParentHandle
; _GUICtrlTreeViewGetParentID
; _GUICtrlTreeViewGetState
; _GUICtrlTreeViewGetText
; _GUICtrlTreeViewGetTextColor
; _GUICtrlTreeViewGetTree
; _GUICtrlTreeViewInsertItem
; _GUICtrlTreeViewSelectItem
; _GUICtrlTreeViewSetBkColor
; _GUICtrlTreeViewSetIcon
; _GUICtrlTreeViewSetIndent
; _GUICtrlTreeViewSetLineColor
; _GUICtrlTreeViewSetState
; _GUICtrlTreeViewSetText
; _GUICtrlTreeViewSetTextColor
; _GUICtrlTreeViewSort


Но у меня такое ощущение, что они работают только с создаными GUI.

Creat0R 26-04-2007 16:39 579952

mrak1990
Цитата:

Но у меня такое ощущение, что они работают только с создаными GUI.
Угу, эти функции предназначены только для работы с AutoIt'овским GUI.

Для управления внешними элементами, нужно пробовать ControlClick(), ControlCommand(), и им подобные.
Но именно со случаем Свойства папки будет сложновато, я как то пытался управлять элементами, но там идентификатор управляющих (Control ID) почти не распознаётся (программой Au3Info).

mrak1990 26-04-2007 17:01 579972

Цитата:

mrak1990

Цитата:
Но у меня такое ощущение, что они работают только с создаными GUI.


Угу, эти функции предназначены только для работы с AutoIt'овским GUI.

Для управления внешними элементами, нужно пробовать ControlClick(), ControlCommand(), и им подобные.
Но именно со случаем Свойства папки будет сложновато, я как то пытался управлять элементами, но там идентификатор управляющих (Control ID) почти не распознаётся (программой Au3Info).
А ты какой Control ID имеешь ввиду? Всего дерева или отдельных пунктов? У всего дерева я знаю какой код: 30120
Сейчас попробовал повозиться с прогой Winspector. В конце концов нашёл команду, которая ставит или убирает галочку: TVM_SETITEMW

И плюс к этому прога выдаёт ещё какую-то инфу:

Item: 0*00094d88
Mask: TVIF_HANDLE | TVIF_IMAGE | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_TEXT
IParam: 0*000ee458
Text: Отображать "Панель управления" в папке "Мой компьютер"



Это вообще может как-то пригодиться?

Creat0R 26-04-2007 17:34 579989

mrak1990
Цитата:

В конце концов нашёл команду, которая ставит или убирает галочку: TVM_SETITEMW
Как то так может:

Код:

Opt("WinTitleMatchMode", 4)
$hWnd = WinGetHandle("Свойства папки")

DllCall("user32.dll", "long", "SendMessage", "hwnd", $hWnd, "int", "TVM_SETITEMW", "int", "0*00094d88", "int", 0)

Это неверно, но направление кажется верное :)...

Все эти опции можно редактировать из реестра - HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced

mrak1990 26-04-2007 18:47 580004

Цитата:

Как то так может:


Код:
Opt("WinTitleMatchMode", 4)
$hWnd = WinGetHandle("Свойства папки")

DllCall("user32.dll", "long", "SendMessage", "hwnd", $hWnd, "int", "TVM_SETITEMW", "int", "0*00094d88", "int", 0)

Это неверно, но направление кажется верное ...

А можно где-нибудь поподробнее узнать о синтаксисе?



Цитата:

Все эти опции можно редактировать из реестра - HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced
Просто уменя не пашет через реестр одна из опций: Скрывать защищённые системные файлы.

mrak1990 26-04-2007 19:37 580023

В общем раскопал справочник по WinAPI. Но мне от него толку маловато:


Код:

Функция SendMessage

    Описание:
 function SendMessage(Wnd: HWnd; Msg, wParam: Word; lParam: Longint): Longint;

    Посылает сообщение оконной функции указанного окна. Возвpат из функции осуществляется только после обpаботки сообщения.

    Паpаметpы:
    Wnd: Окно, пpинимающее сообщение или $FFFF для посылки всем всплывающим окнам в системе.
    Msg: Тип сообщения.
    wParam: Дополнительная инфоpмация о сообщении.
    lParam: Дополнительная инфоpмация о сообщении.

    Возвpащаемое значение:
    Значение, возвpащенное пpинимающей оконной функцией.

 функция находится в файле user32.dll

Ну а это, я думаю все разобрались что такое:

Код:

DllCall ( "dll", "return type", "function" [, "type1", param1 [, "type n", param n]] )

В общем, кто хоть что-то в этом деле смыслит помогите разобраться.


Creat0R 26-04-2007 21:12 580054

mrak1990
Цитата:

Просто уменя не пашет через реестр одна из опций: Скрывать защищённые системные файлы.
Всё очень просто:

Код:

RegWrite("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced", "ShowSuperHidden", "REG_DWORD", 1) ;если 0, тогда файлы будут показываться.
Если нужно обновить программно все папки и даже рабочий стол, см. мою утилитку для отката расширении файлов и скрытых папок тут (исходники естественно в архиве прилагаются ;) ).

Цитата:

раскопал справочник по WinAPI
На русском? можно ссылку на источник?

qeraser 27-04-2007 10:11 580263

Задача - запуск и работа 1с с конкретной конфигурацией с флэш-диска на любом компьютере.
Платформа + база находятся на флэш.
Т.е подключив флэшку и запустив 1с с нее же, загружалась нужная конфигурация.
Чтобы 1с видел базы пути к ним должны быть прописаны пути в реестре.

Я могу написать bat, au3 файл который вносил бы соотв. записи в реестр, но в путях к базам нужно указать букву диска. Проблема в том, что компьютеры разные, соответственно флэш-диск будет иметь разные буквы в системе.

Как можно поэлегантнее реализовать?

amel27 27-04-2007 11:12 580280

qeraser

для BAT подстановка %~d0 возвращает букву диска, откуда запущен скрипт
для AU3 выражение StringLeft (@ScriptDir, 2) работает аналогично

qeraser 27-04-2007 11:49 580306

amel27
Спасибо, разобрался :)

TERMINAL 27-04-2007 13:47 580353

Как определить - есть ли на диске свободных 1 гиг, если есть то вывести сообщений №1, если нет-вывести сообщение №2?!

amel27
А возможно чтобы обновления записывальсь в текстовый файл?
где изменения сделать?

mrak1990 27-04-2007 14:51 580380

Цитата:

На русском? можно ссылку на источник?
Без проблем:

http://foxpopuli.narod.ru/books/api_help.zip

mrak1990 27-04-2007 15:49 580413

Creat0R
Код:

Func UpdateExplorer()
        Local $WinExpListArr = _ExplWinGetList()
        Local $OldOpt = Opt("WinTitleMatchMode", 4)
        Local $GetWinState, $Hwnd
        If IsArray($WinExpListArr) Then
                For $iWin = 1 To $WinExpListArr[0]
                        $GetWinState = WinGetState($WinExpListArr[$iWin])
                        $Hwnd = WinGetHandle($WinExpListArr[$iWin])
                        DllCall("user32.dll", "long", "SendMessage", "hwnd", $hWnd, "int", 0x111, "int", 28931, "int", 0)
                Next
        EndIf
       
        $Hwnd = WinGetHandle("classname=Progman")
        DllCall("user32.dll", "long", "SendMessage", "hwnd", $hWnd, "int", 0x111, "int", 28931, "int", 0)
        Opt("WinTitleMatchMode", $OldOpt)
EndFunc

Func _ExplWinGetList()
        Local $OldOpt = Opt("WinTitleMatchMode", 4)
        Local $WinList = WinList("classname=CabinetWClass")
        Opt("WinTitleMatchMode", $OldOpt)
        If IsArray($WinList) Then
                Local $WinListArr[$WinList[0][0]+1]
                For $iW = 1 To $WinList[0][0]
                        $WinListArr[$iW] = $WinList[$iW][0]
                Next
                $WinListArr[0] = $WinList[0][0]
                Return $WinListArr
        Else
                Return ""
        EndIf
EndFunc

У меня вопрос вот по этому коду. Можешь просто описать в общих чертах, как он работает?

Creat0R 27-04-2007 17:49 580464

TERMINAL
Цитата:

Как определить - есть ли на диске свободных 1 гиг, если есть то вывести сообщений №1, если нет-вывести сообщение №2?!
Код:

$CD = "C:\"
$FreeSpace = DriveSpaceFree($CD)
If $FreeSpace >= 1024 Then
    MsgBox(64, "", "Ok, есть на диске <" & $CD & "> " & $FreeSpace & " мб свободного места.")
Else
  MsgBox(48, "", "На диске <" & $CD & "> не хватает свободного места (" & $FreeSpace & " мб).")
EndIf

mrak1990

Цитата:

Без проблем:
Спасибо!

Цитата:

Можешь просто описать в общих чертах, как он работает?
Конечно...

Первая функция ( UpdateExplorer() ), в начале использует вторую ( _ExplWinGetList() ), чтобы получить список заголовок всех окон которые являются папками (мы же не хотим обновлять к примеру Internet Explorer :) ).
Затем для каждого найденого окна (из полученного списка в массиве), происходит обновление (это делает вызов Dll), всё это в принципе для одной цели - обновить программно все открытые эксплореровские окна (в том числе и рабочий стол), не активируя их и не используя никаких посылании клавишь типа F5 :) , а просто прямой вызов функции (для конкретного окна) обновления окна (та же функция которая выполняется Windows после нажатия F5).

mrak1990 27-04-2007 17:53 580465

Creat0R
Остался один вопрос. Для чего ты вызываешь два раза функцию DllCall? Один раз для папок, а другой для рабочего стола?

Creat0R 27-04-2007 18:10 580473

mrak1990
Цитата:

Для чего ты вызываешь два раза функцию DllCall? Один раз для папок, а другой для рабочего стола?
Да, для рабочего стола класс заголовка окнка немного другой, поэтому получить его из списка одновременно не получается... хотя можно было конечно во второй функции добавить последний элемент в массив который содержал бы заголовок окна для рабочего стола, но так тоже нормально работает :)

И ещё, $GetWinState = WinGetState($WinExpListArr[$iWin]) там уже лишнее, это раньше у меня не получалось напрямую обновлять окна, поэтому приходилось активировать их, посылать им обновление, и затем возвращать окно в исходное положение (свёрнутое/развёрнутое, активное/не активное).

Вот обновил функции, теперь список всех окон возвращается средствами функции _ExplWinGetList(), а также убрал лишние строчки:

Код:

Func UpdateExplorer()
    Local $OldOpt = Opt("WinTitleMatchMode", 4)
    Local $WinExpListArr = _ExplWinGetList()
    Local $Hwnd
    If IsArray($WinExpListArr) Then
        For $iWin = 1 To $WinExpListArr[0]
            $Hwnd = WinGetHandle($WinExpListArr[$iWin])
            DllCall("user32.dll", "long", "SendMessage", "hwnd", $hWnd, "int", 0x111, "int", 28931, "int", 0)
        Next
    EndIf
    Opt("WinTitleMatchMode", $OldOpt)
EndFunc

Func _ExplWinGetList()
    Local $WinList = WinList("classname=CabinetWClass")
    If IsArray($WinList) Then
        Local $WinListArr[$WinList[0][0]+2]
        For $iW = 1 To $WinList[0][0]
            $WinListArr[$iW] = $WinList[$iW][0]
        Next
        $WinListArr[0] = $WinList[0][0]+1
        $WinListArr[$WinListArr[0]] = "classname=Progman"
        Return $WinListArr
    Else
        Return ""
    EndIf
EndFunc


mrak1990 27-04-2007 23:20 580601

Creat0R
Разобрался наконец с твоим скриптом. Но остался один маленький вопросик:
Код:

Local $WinListArr[$WinList[0][0]+2]
В скриптах AutoIT нужно при объявлении массива указывать в квадратных скобках число элементов? Если так, то почему ты приписываешь "+2", а не "+1"?

Creat0R 27-04-2007 23:49 580609

mrak1990
Цитата:

почему ты приписываешь "+2", а не "+1"?
Функция WinList возвращает массив заголовок окон, но в этом массиве нет заголовка для рабочего стола, поэтому при объявлении массива требуется увеличить его на один элемент, в момент обработки массива он остаётся пустым, но в конце функции я задаю этому пустому элементу значение ровняющееся заголовку рабочего стола ($WinListArr[$WinListArr[0]] = "classname=Progman"), чтобы в родительской функции ( UpdateExplorer() ) небыло необходимости в определении заголовка для рабочего стола, он будет браться их возвращённого массива (последний элемент).

mrak1990 27-04-2007 23:57 580614

Creat0R
Я всё это понял. Просто для чего два дополнительных элемента?

Creat0R 28-04-2007 01:36 580642

mrak1990
Цитата:

для чего два дополнительных элемента?
Когда объявляем массив, нужно добавлять ещё один элемент, который будет содержать общее число элементов, в данном случае, нужно два (т.е тоже число элемнтов как и у массива возвращённого от WinList, плюс один элемент (WinList[0][0] содержит общее число элементов этого массива)), а дополнительный для того чтобы поместить в него ещё один заголовок окна (рабочего стола)...

Можно конечно и обойтиться +2, вот так:

Код:

Func _ExplWinGetList()
    Local $WinList = WinList("classname=CabinetWClass")
    If IsArray($WinList) Then
        Local $WinListArr[UBound($WinList)+1]
        For $iW = 1 To $WinList[0][0]
            $WinListArr[$iW] = $WinList[$iW][0]
        Next
        $WinListArr[0] = $WinList[0][0]+1
        $WinListArr[$WinListArr[0]] = "classname=Progman"
        Return $WinListArr
    Else
        Return ""
    EndIf
EndFunc

В этом случае Ubound($WinList) ровняется WinList[0][0]+1 (нуливой элемент содержащий общее количество элементов, и все остальные элементы), поэтому мы добавляем только +1.

amel27 28-04-2007 11:42 580778

TERMINAL
Цитата:

А возможно чтобы обновления записывальсь в текстовый файл?
где изменения сделать?
подправил скрипт для случая файла и исправил один недочет в скрипте...

З.Ы. имхо скрипт не очень практичен, но не если есть интерес принимаются любые предложения по доработке... заодно можно придать более внятный вид - по аналогии с энумераторами RegEnum* с индексом... типа HotFixEnum

Diamond 28-04-2007 14:25 580829

Защита от повторного запуска
P.S. Просьба, не тестировать этот скрипт из редактора.
Код:

$objService=ObjGet("winmgmts:{impersonationLevel=impersonate}!\\.\root\CIMV2")
$colProc=$objService.ExecQuery("SELECT * FROM Win32_Process WHERE CommandLine LIKE '%" & @ScriptName & "%'")
If $colProc.Count > 1 Then
    Msgbox(0+48,"Совпадений: " & $colProc.Count,"Скрипт уже запущен")
    Exit(1)
EndIf
;~ --== Здесь должен быть код Вашего скрипта ==--

Отслеживание вновь запущенных процессов:
Код:

$strComputer = "."
$objWMIService = ObjGet("winmgmts:" & _
"{impersonationLevel=impersonate}!\\" & $strComputer & "\root\cimv2")
$colMonitoredProcesses=$objWMIService.ExecNotificationQuery("select * from __instancecreationevent " & _ 
" within 1 where TargetInstance isa 'Win32_Process'")
While 1
$objLatestProcess = $colMonitoredProcesses.NextEvent
MsgBox(0,"Обнаружен запуск",$objLatestProcess.TargetInstance.Name)
WEnd

Отслеживание завершающихся процессов:
Код:

$strComputer = "."
$objWMIService = ObjGet("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & $strComputer & "\root\cimv2")
$colMonitoredProcesses = $objWMIService.ExecNotificationQuery("select * from __instancedeletionevent " _ 
& "within 1 where TargetInstance isa 'Win32_Process'")
While 1
$objLatestProcess = $colMonitoredProcesses.NextEvent
MsgBox(0,"Обнаружено завершение",$objLatestProcess.TargetInstance.Name)
WEnd

Отследить запуск определённого процесса:
Код:

$process='notepad.exe'
$strComputer = "."
$objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2")
$objEvents = $objWMIService.ExecNotificationQuery _
("SELECT * FROM Win32_ProcessStartTrace WHERE ProcessName = '" & $process & "'")
MsgBox(0,"","Ожидание событий ...")
While 1
    $objReceivedEvent = $objEvents.NextEvent
    MsgBox(0,"",$process & " запущен")
WEnd

Отследить завершение определённого процесса:
Код:

$process='notepad.exe'
$strComputer = "."
$objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2")
$objEvents = $objWMIService.ExecNotificationQuery _
("SELECT * FROM Win32_ProcessStopTrace WHERE ProcessName = '" & $process & "'")
MsgBox(0,"","Ожидание событий ...")
While 1
    $objReceivedEvent = $objEvents.NextEvent
    MsgBox(0,"",$process & " завершён")
WEnd

А этот скрипт я как-то писал для отслеживания вируса по его PID (долгая история...)
С его помощью можно определить, какие программы запускали на компьютере в ваше отсутствие,
остаётся только перенаправить информацию в текстовой файл...
Код:

#Include <date.au3>
$strComputer = "."
$objWMIService = ObjGet("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & $strComputer & "\root\cimv2")
$colMonitoredProcesses = $objWMIService.ExecNotificationQuery("select * from __instancedeletionevent " _ 
& "within 1 where TargetInstance isa 'Win32_Process'")
While 1
$objLatestProcess = $colMonitoredProcesses.NextEvent
$pdel = _Now()
MsgBox(0,"", "Имя: " & $objLatestProcess.TargetInstance.Name  & @CRLF & _
"Расположение: " & $objLatestProcess.TargetInstance.ExecutablePath & @CRLF & _
"Командная строка: " & $objLatestProcess.TargetInstance.CommandLine & @CRLF & _
"PID: " & $objLatestProcess.TargetInstance.ProcessId & @CRLF & _
"Приоритет: " & $objLatestProcess.TargetInstance.Priority & @CRLF & _
"Время запуска:        " & WMIDateStringToDate($objLatestProcess.TargetInstance.CreationDate) & @CRLF & _
"Время завершения: " & $pdel & @CRLF & _
"____________________________________")
WEnd

;###########################################
Func WMIDateStringToDate($str)
Local $WMIDateStringToDate
If not $str = "" Then
        $WMIDateStringToDate=StringMid($str,7,2) & '.' & StringMid($str,5,2) & '.' & _
        StringLeft($str,4) & chr(32) & StringMid($str,9,2) & ':' & _
        StringMid($str,11,2) & ':' & StringMid($str,13,2)
EndIf
Return $WMIDateStringToDate
EndFunc

З.Ы.
Не мешало бы скрыть присутствие скрипта в списке процессов.
Слышал, что это можно сделать через WinApi, но я не знаю как...

Creat0R 28-04-2007 15:34 580855

Diamond
Хорошие функции!

Правда с первой что-то не получается :(
При первом запуске выдаёт два совпадения и что скрипт уже запущен, хотя это не так.

P.S
Это только если имя скрипта test.au3, в других случаях вроде всё нормально.

Кстати, а можно ли как то получить список скрытых процессов?

mrak1990 28-04-2007 17:33 580901

Creat0R
Я тут переписал твой скрипт в таком виде, в каком, как мне кажется проще его понять начинающим. Плюс добавил комментарии. Вот что из этого получилось.
Код:

#cs
;~ Toogle Hidden folders and files program - This is AutoIt source code (AutoIt vesrion 3.2.2.0).
;~ Author: G.Sandler a.k.a CreatoR - http://creator-lab.ucoz.ru
;~ ICQ: 5607655
#ce

#NoTrayIcon

$RegKey = "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced"
If RegRead($RegKey, "Hidden") = 1 Then
        RegWrite($RegKey, "Hidden", "REG_DWORD", 2)
Else
        RegWrite($RegKey, "Hidden", "REG_DWORD", 1)
EndIf

UpdateExplorer()

Func UpdateExplorer()
    Local $OldOpt = Opt("WinTitleMatchMode", 4) ;Устанавливаем параметр AutoIT, отвечающий за идендификацию окон
    Local $WinExpListArr = _ExplWinGetList() ;Получаем массив, возвратённый функцией "_ExplWinGetList"
    Local $Hwnd
    If IsArray($WinExpListArr) Then
        For $iWin = 1 To $WinExpListArr[0]
            $Hwnd = WinGetHandle($WinExpListArr[$iWin])
            DllCall("user32.dll", "long", "SendMessage", "hwnd", $hWnd, "int", 0x111, "int", 28931, "int", 0) ;Посылаем команду на обновление всех папок и Рабочего стола
        Next
    EndIf
    Opt("WinTitleMatchMode", $OldOpt) ;Устанавливаем старое значение параметра AutoIT, отвечающего за идендификацию окон
EndFunc

Func _ExplWinGetList()
    Local $WinList = WinList("classname=CabinetWClass")  ;Получаем массив, содержащий список открытых папок и их HWND
    If IsArray($WinList) Then
        Local $WinListArr[UBound($WinList)+1] ;Создаём новый массив, который будет содержать ТОЛЬКО ИМЕНА папок, CLASSNAME Рабочего стола и кол-во элементов в массиве
                $WinListArr[0] = $WinList[0][0]+1 ;Присваеваем нулевому элементу массива число, содержащее кол-во элементов в массиве
        $WinListArr[$WinListArr[0]-1] = "classname=Progman" ;Присваиваем последнему элементу массива "Classname" Рабочего стола
        For $iW = 1 To $WinListArr[0]-2 ;Вычесть двойку нужно из-за того, что первый и последний элемент массива не содержат имен папок
            $WinListArr[$iW] = $WinList[$iW][0] ;Присваиваем первому и всем последующим элементам массива названия открытых окон
        Next
        Return $WinListArr ;Возвращаем массив, содержащий список всех окон, "Classname" Рабочего стола и кол-во элементов в массиве
    Else
        Return ""
    EndIf
EndFunc


Creat0R 28-04-2007 20:33 580969

mrak1990
Цитата:

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

Правда комментарии немного не точные, так будет правильнее (также немного изменил функции, раньше если небыло найдено окон, то рабочий стол тоже не обновлялся, а также во второй функции сразу помещаются в массив уникальные идентификаторы (hWnd), чтобы не нужно было их определять в первой функции - они ведь возвращаются от WinList() ):

Код:

Func _UpdateExplorer()
    ;Устанавливаем параметр, отвечающий за метод распознвания заголовок окон (4 - самый чувствительный),
    ;и помещаем в переменную $OldOpt исходное значение этого параетра.
    Local $OldOpt = Opt("WinTitleMatchMode", 4)
    ;Получаем массив содержащий заголовки окон проводника Windows вкдючая Рабочего стола (по средствам функции _ExplWinGetList).
    Local $WinExpListArr = _ExplWinGetList()
    ;Если возвратился массив (а значит найдены заголовки окон),
    ;то перебираем весь массив, с целью обновления каждого окна (по его заголовку из элементов массива).
    If IsArray($WinExpListArr) Then
        For $iWin = 1 To $WinExpListArr[0]
            ;Вызов функции для обновления текущего окна
            ;(по уникальному идентификатору который содержится в текущем элементе массива).
            DllCall("user32.dll", "long", "SendMessage", "hwnd", $WinExpListArr[$iWin], "int", 0x111, "int", 28931, "int", 0)
        Next
    Else
        ;Если не вернулся массив (значит небыли найдены окна проводника), тогда обновляем только Рабочий стол
        ;(переменная $WinExpListArr теперь содержит только один уникальный идентификатор Рабочего стола).
        DllCall("user32.dll", "long", "SendMessage", "hwnd", $WinExpListArr, "int", 0x111, "int", 28931, "int", 0)
    EndIf
    ;Устанавливаем исходное значение (заданное значение при входе в функцию) параметра,
    ;отвечающего за метод распознвания заголовок окон.
    Opt("WinTitleMatchMode", $OldOpt)
EndFunc

Func _ExplWinGetList()
    ;Получаем массив, содержащий список существующих заголовок окон проводника Windows (Explorer),
    ;и их уникальный идентификатор (hWnd).
    Local $WinList = WinList("classname=CabinetWClass")
    ;Если вернулся массив (а значит найдено одно или более окон), тогда делаем перебор по массиву,
    ;в целях отсеивания только уникальных идентификаторов существующих окон (проводника Windows).
    If IsArray($WinList) Then
        ;Объявляем массив, который будет собдержать список уникальных идентификаторов существующих окон.
        Local $WinListArr[UBound($WinList)+1]
        ;Перебираем полученный массив $WinList, и отсеиваем в новый массив $WinListArr
        ;только уникальные идентификаторы окон Explorer.
        For $iW = 1 To $WinList[0][0]
            $WinListArr[$iW] = $WinList[$iW][1]
        Next
        ;Присваеваем нулевому элементу нового массива ($WinListArr), значение ровняющееся общему количеству элементов в этом массиве.
        $WinListArr[0] = UBound($WinListArr)-1
        ;Присваиваем последнему элементу этого же массива, уникальный идентификатор (основываясь на "Classname") Рабочего стола.
        $WinListArr[$WinListArr[0]] = WinGetHandle("classname=Progman")
        ;Возвращаем массив, содержащий список идентификаторов всех существующих окон проводника (вкючая Рабочего стола).
        Return $WinListArr
    Else
        ;Если функция WinList() не "вернула" массив (а значит небыло найдено окон проводника),
        ;тогда возвращаем только один уникальный идентификатор Рабочего стола.
        Return WinGetHandle("classname=Progman")
    EndIf
EndFunc


amel27 29-04-2007 09:08 581060

Diamond
Цитата:

Не мешало бы скрыть присутствие скрипта в списке процессов.
Слышал, что это можно сделать через WinApi, но я не знаю как...
вот вариант на основе скрипта с оффсайта, к сожалению он полезен только в учебных целях...
с другой стороны, все остальные способы будут оффтопом для этой ветки. ;)
Код:

$process = "script.exe"

While 1
    WinWait ("Диспетчер задач Windows")
    $index = ControlListView ("Диспетчер задач Windows", "", 1009, "FindItem", $process)
    If $index = -1 Then
        Sleep(5)
    Else
        $hwnd = ControlGetHandle ("Диспетчер задач Windows", "", 1009)
        DllCall("user32.dll", "int", "SendMessage", "hwnd", $hwnd, "int", 0x1008, "int", $index, "int", 0)
    EndIf
Wend


Diamond 29-04-2007 11:39 581085

Creat0R
Цитата:

При первом запуске выдаёт два совпадения и что скрипт уже запущен, хотя это не так.
У меня всё нормально, хотя если запускать его из редактора то обнаруживается лишнее "совпадение".
Цитата:

Кстати, а можно ли как то получить список скрытых процессов?
Думаю, что процесс будет скрыт только от "Диспетчера задач Windows" и подобных ему, т.е. от WMI он не скроется.

amel27
Цитата:

к сожалению он полезен только в учебных целях...
Действительно к сожалению...
Наверное что-то вроде этого я и искал, но не ожидал что это будет работать именно так...
В любом случае, Спасибо!
Цитата:

все остальные способы будут оффтопом для этой ветки.
Любой способ который можно использовать в AutoIT, или который имеет прямое отношение к скрипту AutoIT, разве это оффтоп? Хотя...

Скажем, я хочу знать какие программы запускали на моём компьютере в моё отсутствие.
Проблема в том, что более опытный юзер может легко обнаружить и завершить мой "шпионский" процесс.
У меня возникла идея не скрывать, а просто сделать невозможным его завершение, т.е. скомпилировать скрипт и назвать его к примеру lsass.exe.
Хотя и примитивно - зато надёжно. ;)


Diamond 29-04-2007 13:40 581113

Creat0R
Я понял почему обнаруживается совпадение. Если открыть скрипт в редакторе (даже незапускать) то командная строка редактора будет содержать путь к скрипту, а это уже одно "совпадение".
Попробуй закрыть редактор и запустить скрипт снова. ;)

Creat0R 29-04-2007 15:25 581144

Diamond
Цитата:

если запускать его из редактора то обнаруживается лишнее "совпадение"
Я запускал сам скрипт, редактор вовсе не открывал (с браузера сразу скрипт пишется на рабочий стол ;) - кстати если интересно, могу выложить тут небольшой код). Но как я упоминул, скрипт именуется как test.au3, при другом имени всё вроде ок, даже и не знаю почему так (может у меня уже запущен подобный скрипт, и он не виден в диспетчере задач :idontnow: ).




Есть у меня один вопрос - как можно проверить определённое окно, на наличие ControlID, но способ нужен надёжный, я написиал вот такую функцию (см. далее), но она не везде срабатывает, к примеру в браузере Opera, возвращаются не все ControlID, хотя в Au3Info.exe нужные (мне, для проверки) ControlID видны:

Код:

Func _ControlIDIsExists($hWnd, $ControlID)
    If Not IsHWnd($hWnd) Then $hWnd = WinGetHandle($hWnd)
    If Not WinExists($hWnd) Then Return SetError(1, 0, 0)
    Local $ClassesArr = StringSplit(WinGetClassList($hWnd), @LF)
    If IsArray($ClassesArr) Then
        For $i = 1 To UBound($ClassesArr)-1
            If $ClassesArr[$i] = $ControlID Then Return True
        Next
    EndIf
    Return False
EndFunc


amel27 29-04-2007 18:06 581178

Diamond
Цитата:

Скажем, я хочу знать какие программы запускали на моём компьютере в моё отсутствие.
Проблема в том, что более опытный юзер может легко обнаружить и завершить мой "шпионский" процесс.
У меня возникла идея не скрывать, а просто сделать невозможным его завершение, т.е. скомпилировать скрипт и назвать его к примеру lsass.exe.
угу, типичное поведение трояна... Проблема в том, что "мимикрия", хуки и прочие фокусы могут конфликтовать с настройками безопасности системы, а также перехватываться антивирусами и файерволами. На самом деле задача регистрации запускаемых файлов решается штатными средствами администрирования, без привлечения программ-шпионов и прочих ухищрений - прежде всего это средства аудита файловой системы, кроме того можно оформить подписку на любые системные WMI-события... никаких "левых" процессов при этом не создается, т.к. все выполняется средствами системы. Именно это я и имел ввиду говоря про оффтоп...

Creat0R
Цитата:

Есть у меня один вопрос - как можно проверить определённое окно, на наличие ControlID
ControlGetHandle() не устраивает? Кстати, почему именно ControlID?.. а если скажем ClassName?

Creat0R 29-04-2007 22:18 581263

amel27
Цитата:

ControlGetHandle() не устраивает?
Я не уверен что понял... ControlGetHandle() вернёт hWnd, а мне нужно проверить наличие Control.

Цитата:

почему именно ControlID?.. а если скажем ClassName?
Мне не важно, мне нужно проверить существование Control...
Дело в том, что в разных версиях определённой программы (в этом случае браузер Opera), меняются постоянно(?) ClassNameNN/ControlID, вот мне нужно как то проверить, существует ли в текущей версии определённый Control, если нет, то я буду перебирать их последовательность (обычно меняется только цифра).
К примеру вот такой класс - "OperaWindowClass14" - нужно проверить, есть ли он в программе (в окне), не смистился ли.

amel27 30-04-2007 04:52 581306

Creat0R
Цитата:

Я не уверен что понял... ControlGetHandle() вернёт hWnd, а мне нужно проверить наличие Control.
…ну, в смысле если контрола нет, то и не вернет hwid... Зачем тянуть весь список, если нужно проверить только один?

Цитата:

Мне не важно, мне нужно проверить существование Control...
есть такой фокус, когда для поиска контролов используется функция поиска окон... так как контрол по сути то же окно, только дочернее. К сожалению штатный "AutoIt Window Info" не показывает информацию о "хозяине" для дочерних окон, я использовал HwndSpy... жаль он шароварный. :(
Код:

; Поиск Control по его классу (аналогично можно сделать и по заголовку)
; штатными средствами и через API, на примере CsiTE4

$WinClass = "SciTEWindow"          ; Класс головного окна
$CtrlClass1 = "SciTEWindowContent" ; Класс дочернего окна 1-го уровня
$CtrlClass2 = "Scintilla"          ; Класс дочернего окна 2-го уровня

; Поиск средствами API
$hAPI0 = DLLCall ("user32.dll", "hwnd", "FindWindow", _
    "str", $WinClass, _
    "int", 0 )
$hAPI1 = DllCall ("user32.dll", "hwnd", "FindWindowEx", _
    "hwnd", $hAPI0 [0], _
    "int", 0 , _
    "str", $CtrlClass1, _
    "int", 0 )
$hAPI2 = DllCall ("user32.dll", "hwnd", "FindWindowEx", _
    "hwnd", $hAPI1 [0], _
    "int", 0 , _
    "str", $CtrlClass2, _
    "int", 0 )

; Поиск штатными средствами AutoIT через поиск контрола
$BakWTM = Opt ("WinTitleMatchMode", 4) ; Включаем поиск по классам
$hCtrl = ControlGetHandle("classname=" & $WinClass, '', 350)

; Поиск штатными средствами AutoIT через поиск окна
$BakWSC = Opt ("WinSearchChildren", 1) ; Включаем поиск по вложенным окнам
$hWind = WinGetHandle ("classname=" & $CtrlClass2)

; Вывод результата:
MsgBox (0, 'Test',  'WinAPI:' & @TAB & 'ClassName' & @TAB & $hAPI2 [0] & @CRLF & _
                    'AutoIT:' & @TAB & 'ControlID ' & @TAB & $hCtrl & @CRLF & _
                    'AutoIT:' & @TAB & 'ClassName'  & @TAB & $hWind & @CRLF )
; Возвращаем настройки
Opt ("WinTitleMatchMode", $BakWTM)
Opt ("WinSearchChildren", $BakWSC)


Creat0R 30-04-2007 06:28 581309

amel27
Цитата:

…ну, в смысле если контрола нет, то и не вернет hwid... Зачем тянуть весь список, если нужно проверить только один?
Хм, а я как то не подумал в эту сторону (видимо нужно раньше ложиться спать :biggrin: ), спасибо!

Цитата:

есть такой фокус, когда для поиска контролов используется функция поиска окон... так как контрол по сути то же окно, только дочернее.
Вот за эту инфу тоже спасибо, не знал что контроли могут распознваться используя функции поиска окон, и также не знал (из самой функции) что можно подбирать ControlID через classname=....

Цитата:

я использовал HwndSpy... жаль он шароварный.
Есть WinSpy... бесплатный вроде, но не уверен что он отдаёт нужную инфу.

Спасибо ещё раз большое за пример/инфу, буду пробовать это использовать :) .

Diamond 30-04-2007 07:48 581311

Creat0R
Процесс в котором обнаруживается совпадение, скорее всего виден в Диспетчере задач.
Попробуй индифицировать его по параметрам командной строки:
Код:

$CommandString='Test.au3'

;~ Соединяемся с WMI
$objService = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\.\root\CIMV2")
;~ Задаём параметры объекта
$colProc = $objService.ExecQuery("SELECT * FROM Win32_Process WHERE CommandLine LIKE '%" & $CommandString & "%'")
;~ Цикл по элементам объекта-коллекции
For $Proc In $colProc
Msgbox(0+48,"Обнаружен процесс: " & $Proc.name,"Командная строка запуска:" & @CR & $Proc.CommandLine)
Next


amel27 30-04-2007 17:44 581419

Creat0R

Краткий (промежуточный) отчет о самопальных _FileSelectFolder и подобных функций… На время их активности действительно прерывается любая работа AutoIT-скрипта, причем отключаются все механизмы диспетчеризации вызовов, включая AdLib и GUIRegisterMsg. Впрочем, это вполне логично, так как управление полностью передается системной функции. Отсюда становится понятно, почему разработчики не внесли функциональность HWID в свои функции выбора… просто они не стали заморачиваться разработкой своих функций, а взяли те же системные API-функции (aka wrapper).

Особенность _FileSelectFolder (и аналогичных) в том, что ее поведение управляется набором специальных сообщений SendMessage, которые:
- функция может инициализировать себе сама через вызов специальной (CallBack) функции,
- окно выбора может получить извне.

Первый случай не реализуем средствами AutoIT по причине отсутствия поддержки указателей на функцию. Это ограничение можно обойти подключением внешних DLL, содержащих требуемые функции и способных возвращать их указатели. Одна из таких реализаций предложена на форуме оффсайта, к сожалению, она не подходит для нашего случая по указанным ранее причинам, так как опирается на механизм GUIRegisterMsg… Поэтому потребуется писать свою специфическую DLL, либо расширить функциональность предложенной – в любом случае это придется делать на чем-то другом, отличном от AutoIT - способном компилировать DLL, дружить с GUI и обязательно фриварном.

Второй случай в принципе можно реализовать на AutoIT, но потребуется дополнительный скрипт, управляющий поведением основного на время выполнения системных функций выбора… при этом придется решить ряд вопросов по синхронизации этих процессов. Кроме того, этот вариант очень ограничен по функциональности, так как управляющий скрипт не будет получать информации о состоянии окна главного скрипта (оперативные сообщения). Например, можно попытаться задать начальную папку или текст статусной строки, но управлять кнопкой «Ok» или реагировать на ошибки ввода не получится.

mrak1990 30-04-2007 19:59 581457

Creat0R
Взял на себя смелость собрать дистрибутив этой проги (выглядит он точно так же), чтобы ты его у себя на сайте обновил. В коде ничего не мнеял. Только опечатки убрал:
Код:

#cs
;~ Toogle Hidden folders and files program - This is AutoIt source code (AutoIt vesrion 3.2.2.0).
;~ Author: G.Sandler a.k.a CreatoR - http://creator-lab.ucoz.ru
;~ ICQ: 5607655
#ce

#NoTrayIcon

$RegKey = "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced"
If RegRead($RegKey, "Hidden") = 1 Then
        RegWrite($RegKey, "Hidden", "REG_DWORD", 2)
Else
        RegWrite($RegKey, "Hidden", "REG_DWORD", 1)
EndIf

UpdateExplorer()

Func _UpdateExplorer()
    ;Устанавливаем параметр, отвечающий за метод распознавания заголовок окон (4 - самый чувствительный),
    ;и помещаем в переменную $OldOpt исходное значение этого параметра.
    Local $OldOpt = Opt("WinTitleMatchMode", 4)
    ;Получаем массив, содержащий заголовки окон проводника Windows (включая Рабочего стола), по средствам функции _ExplWinGetList.
    Local $WinExpListArr = _ExplWinGetList()
    ;Если возвратился массив (а значит найдены заголовки окон),
    ;то перебираем весь массив, с целью обновления каждого окна (по его hWnd из элементов массива).
    If IsArray($WinExpListArr) Then
        For $iWin = 1 To $WinExpListArr[0]
            ;Вызов функции для обновления текущего окна
            ;(по уникальному идентификатору, который содержится в текущем элементе массива).
            DllCall("user32.dll", "long", "SendMessage", "hwnd", $WinExpListArr[$iWin], "int", 0x111, "int", 28931, "int", 0)
        Next
    Else
        ;Если не вернулся массив (значит не были найдены окна проводника), тогда обновляем только Рабочий стол
        ;(переменная $WinExpListArr теперь содержит только один уникальный идентификатор Рабочего стола).
        DllCall("user32.dll", "long", "SendMessage", "hwnd", $WinExpListArr, "int", 0x111, "int", 28931, "int", 0)
    EndIf
    ;Устанавливаем исходное значение (заданное значение при входе в функцию) параметра,
    ;отвечающего за метод распознавания заголовок окон.
    Opt("WinTitleMatchMode", $OldOpt)
EndFunc

Func _ExplWinGetList()
    ;Получаем массив, содержащий список существующих заголовок окон проводника Windows (Explorer),
    ;и их уникальный идентификатор (hWnd).
    Local $WinList = WinList("classname=CabinetWClass")
    ;Если вернулся массив (а значит найдено одно или более окон), тогда делаем перебор по массиву,
    ;в целях отсеивания только уникальных идентификаторов существующих окон (проводника Windows).
    If IsArray($WinList) Then
        ;Объявляем массив, который будет содержать список уникальных идентификаторов существующих окон.
        Local $WinListArr[UBound($WinList)+1]
        ;Перебираем полученный массив $WinList, и отсеиваем в новый массив $WinListArr
        ;только уникальные идентификаторы окон Explorer.
        For $iW = 1 To $WinList[0][0]
            $WinListArr[$iW] = $WinList[$iW][1]
        Next
        ;Присваиваем нулевому элементу нового массива ($WinListArr), значение ровняющееся общему количеству элементов в этом массиве.
        $WinListArr[0] = UBound($WinListArr)-1
        ;Присваиваем последнему элементу этого же массива, уникальный идентификатор (основываясь на "Classname") Рабочего стола.
        $WinListArr[$WinListArr[0]] = WinGetHandle("classname=Progman")
        ;Возвращаем массив, содержащий список идентификаторов всех существующих окон проводника (включая Рабочего стола) и
        ;общее кол-во элементов в этом массиве
        Return $WinListArr
    Else
        ;Если функция WinList() не "вернула" массив (а значит не было найдено окон проводника),
        ;тогда возвращаем только один уникальный идентификатор Рабочего стола.
        Return WinGetHandle("classname=Progman")
    EndIf
EndFunc

Вот ссылка: http://ifolder.ru/1856047

P.S. Единственное, что я не смог изменить, это информацию о файле (вкладка "Версия"). Одна программа при изменении коверкает, другая не хочет сохранять.

Creat0R 30-04-2007 22:39 581487

Diamond
Цитата:

Процесс в котором обнаруживается совпадение, скорее всего виден в Диспетчере задач.
Неа, не видно :)

Цитата:

Попробуй индифицировать его по параметрам командной строки:
Тоже нету :idontnow:
Я не уверен что это корректный способ проверять вторичный запуск скрипта, ведь подобных процессов может быть запущено несколько, и тогда проверка провалится (выдаст что уже запущен процесс)... вроде _Singleton() хорошо справляется с этой задачей.


amel27
Цитата:

Второй случай в принципе можно реализовать на AutoIT, но потребуется дополнительный скрипт, управляющий поведением основного на время выполнения системных функций выбора
Можно использовать тот же скрпт, но запускать его (до/в процессе вызова функции) с параметрами ком. строки, в которых кстати можно и передавать разного рода информацию нужную для идентификации запускаемого окна. А в начале скрипта поставить распознавание этой самой ком. строки - один минус, будет запущено два процесса одного скрипта.

Цитата:

можно попытаться задать начальную папку или текст статусной строки
Смутно себе представляю как можно извне задать начальную папку (речь ведь идёт о функции _FileSelectFolder() ?), я ещё не встречал функции которые способны раскрывать дерево папок во внешних приложениях (окон) основываясь на обычных данных (имя папки в данном случае), не на основе идентификаторов (типа ControlID).

mrak1990
Цитата:

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

mrak1990 30-04-2007 23:17 581495

Creat0R
Цитата:

Там установщик для каких целей? помещает ярлыки? хотелось бы реализовать помещение пункта в контекстное меню проводника, тогда это было бы весьма полезно.
Если честно, то я просто сделал архив подобный тому, что висит у тебя на сайте... Но идея, предложенная тобой кажется мне очень удачной. Сегодня же возьмусь за её реализацию.


P.S. Так что пока можешь не скачивать выложенный мною архив.

amel27 01-05-2007 05:29 581535

Creat0R
Цитата:

Смутно себе представляю как можно извне задать начальную папку (речь ведь идёт о функции _FileSelectFolder() ?), я ещё не встречал функции которые способны раскрывать дерево папок во внешних приложениях (окон) основываясь на обычных данных (имя папки в данном случае), не на основе идентификаторов (типа ControlID)
все гораздо проще... :) API-функция SHBrowseForFolder сама на многое способна, нужно только отправить ей нужное сообщение, полный список поддерживаемых сообщений смотри в "Remarks" к Callback-функции: http://msdn2.microsoft.com/en-us/library/ms649522.aspx

Creat0R 01-05-2007 06:27 581537

amel27
Цитата:

API-функция SHBrowseForFolder сама на многое способна, нужно только отправить ей нужное сообщение
Ох... еслиб я ещё знал как теперь всё это реализовать :sorry: ... как вообще изначально вызвать эту функцию? (я уже не говорю/спрашиваю о том как ей что то передать).

amel27 01-05-2007 09:19 581552

Creat0R

К сожалению, CallBack-функция ничем не сможет помочь, зато в мануале к ней перечислены все сообщения, которые она может отправлять... В первом приближении все достаточно просто - запускаем _FileSelectFolder, открывается окно выбора каталога, уравляющий (фоновый) скрипт распознает это окно и отправляет ему сообщение (SendMessage или PostMessage) о переходе в нужное место дерева каталогов

mrak1990 01-05-2007 17:52 581711

У меня такой вопрос. Как можно по средствам AutoIT удалить ветку реестра? Стандартными командами, как я понял нельзя.

Creat0R
Кстати помещение пункта в контекстное меню проводника у меня получилось.

amel27 01-05-2007 18:22 581739

mrak1990
Цитата:

У меня такой вопрос. Как можно по средствам AutoIT удалить ветку реестра? Стандартными командами, как я понял нельзя.
цитата из справки:
Цитата:

RegDelete
--------------------------------------------------------------------------------

Deletes a key or value from the registry.
FYI: key - ветка, value - параметр

mrak1990 01-05-2007 18:38 581754

Цитата:

цитата из справки:
Цитата:
RegDelete
--------------------------------------------------------------------------------

Deletes a key or value from the registry.

FYI: key - ветка, value - параметр
Это я всё знаю. Но как я понял, с её помощью можно удалять только ключи. Пробовал удалять с её помощью разделы. Никак не получается.
Допустим, мне нужно удалить следующий раздел рестра: "HKEY_CLASSES_ROOT\*\shell\Toogle Hidden Files&Folders\command" Как будет выглядеть команда в этом случае?

mrak1990 01-05-2007 18:52 581763

Пробовал вводить команду: REG DELETE "HKCR\*\shell\Toogle Hidden Files&Folders" Но что-то не очень помогает.

amel27 01-05-2007 20:22 581823

mrak1990
все удаляет - и через AutoIT, и через CMD... какие сообщения?

mrak1990 01-05-2007 21:46 581868

Цитата:

mrak1990
все удаляет - и через AutoIT, и через CMD... какие сообщения?
Как оказалось, у меня были временные заскоки в реестром. Может быть из-за того, что я просматривал его через RegWorks. Хотя сейчас всё нормально.

amel27
Можешь всё таки написать, как удалить раздел реестра, только через RegDelete?

Creat0R 01-05-2007 22:46 581895

amel27
Цитата:

запускаем _FileSelectFolder, открывается окно выбора каталога, уравляющий (фоновый) скрипт распознает это окно и отправляет ему сообщение (SendMessage или PostMessage)
а вот как его послать? полагаю нужно вызвать как то Dll (User32.dll?), но как, с какими именно параметрами... для меня эта сфера пока ещё тёмный лес... даже боюсь туда зайти :not-me:

mrak1990
Цитата:

помещение пункта в контекстное меню проводника у меня получилось.
Если не трудно, раскажи в чём секрет? :) (в ПМ наверно, а то как то оффтоп получается).

Цитата:

как удалить раздел реестра, только через RegDelete?
Код:

RegDelete("HKCR\*\shell\Toogle Hidden Files&Folders")

mrak1990 02-05-2007 17:51 582231

Цитата:

Цитата:
как удалить раздел реестра, только через RegDelete?




Код:
RegDelete("HKCR\*\shell\Toogle Hidden Files&Folders")
Извиниясь за этот тупой вопрос. Я же до этого сам написал, что проблема была в заскоках моей Винды.



Creat0R
Закончил я с обещанным скриптом. Я думаю ты и сам разберёшься как он работает. Запускай только СКОМПИЛИРОВАННЫЙ скрипт.
Вот ссылка на скачку: http://ifolder.ru/1876076



P.S. Описание в самом начале скрипта я немного изменил (авторские права)... :mellow:

Creat0R 02-05-2007 19:55 582274

mrak1990
Цитата:

Закончил я с обещанным скриптом
Спасибо.

Но пару примечании...

Не совсем верно переименовывать файл скриптом из самого себя :) - это иногда может и не сработать. Лучше сначала прописать в реестре данные, а потом перед самым выходом скрипта послать командную строку с ожиданим в одну секунду, и переименовыванием скрипта... примерно так:

Код:

Run(@ComSpec & ' /c ping -n 1 localhost > nul & Ren "' & @ScriptFullPath & '" "' & @ScriptDir & '\Выключить Fast Toogle Hidden Files&Folders.exe"', '', @SW_HIDE)
Exit

И ещё, это не совсем то что я имел в виду, мне нужен способ поместить пункт не в контекстное меню файлов и папок (кстати с этим методом в меню папок пункт так и не помещается), а в меню которое появляется при нажатии правой кнопкой мышки в пустом месте проводника (даже на рабочем столе) или нажатием Ctrl Shift F10 - См. мой пост тут - Пока что никто так и не знает как это сделать :(.

mrak1990 02-05-2007 20:05 582276

Цитата:

Не совсем верно переименовывать файл скриптом из самого себя - это иногда может и не сработать. Лучше сначала прописать в реестре данные, а потом перед самым выходом скрипта послать командную строку с ожиданим в одну секунду, и переименовыванием скрипта... примерно так:
А с чем это связано? Как я понял, при запуске скрипа он первым делом обрабатывается интерпретатором и висит в памяти. И он уже не обращается к файлу. Возможно, что я и не прав. У кого есть мысли по этому поводу - пишите.

mrak1990 02-05-2007 23:07 582338

Creat0R
Цитата:

Пока что никто так и не знает как это сделать .
Покопался я насчёт этого вопроса. Но только начал копать в сторону меню у папок и файлов и пришёл к выводу, что такие пункты как "WinRAR", "Проверить на вирусы" (Kaspersky) добавляются из .dll-файлов. Потом даже открыл какой-то из файлов WinRAR,а и нашёл там строки из контекстного меню.
А у меня на рабочем столе в меню есть пункт "Панель управления NVIDIA", которую можно убирать через настройки. Я думаю с этим пунктом таже история, что и с WinRAR - как-то через DLL. Короче на данном этапе врядли что-то получится сделать.

amel27 03-05-2007 16:11 582620

Creat0R
Цитата:

полагаю нужно вызвать как то Dll (User32.dll?), но как, с какими именно параметрами... для меня эта сфера пока ещё тёмный лес...
вот пример, проверил - вроде работает:
Код:

$hwnd = WinGetHandle ("Обзор папок")

$ret = DllCall ("user32.dll", "int", "SendMessage", _
    "hwnd", $hwnd, _
    "int", 0x400 + 101, _ ; код сообщения BFFM_SETOKTEXT
    "int", 0, _
    "int", 0 ) ; 0/1 - выключить/включить кнопку "OK"


Creat0R 04-05-2007 04:45 582850

amel27
Цитата:

вот пример
Спасибо, но вроде в функции уже есть возможность автоотключения кнопки ОК в нужный момент (если использовать $flag=1), но вот как быть с Init Dir? какой код у параметра BFFM_SETEXPANDED (или может нужен BFFM_SETSELECTION?)?

Creat0R 04-05-2007 13:34 582998

Такой вопрос:
Как можно средставми RegExp осуществлять массовую замену в переменной?

Т.е к примеру, имеем такое значение - $Var = "Test%20My/Test" - тут нужно одним махом заменить %20 на пробел, а / (перевёрнуты слэш) на \ (прямой слэш)....

Пробую так:

Код:

$NewVar = StringRegExpReplace($Var, "%20|/", " |\\")
Но замена осуществляется всех вхождении (из набора разделённого через |) на вот это - |\
Как такую замену можно произвести? или это не предусмотрено?

TERMINAL 04-05-2007 18:15 583135

Вопрос !
Кто-то может помочь?

Например винт разбит на С, D, E, F - CD-ROM, нужно скриптом определить эти диски и отформатить D,E без всяких визуальных эфектов (тихий режим).

Creat0R 05-05-2007 00:51 583250

TERMINAL
Цитата:

нужно скриптом определить эти диски и отформатить D,E
Что значит определить? по каким параметрам их определять?

Чтобы отформатировать диск, можно использовать ком. строку:

Код:

$DriveToFormat = 'Z:'
$Confirm = 'no'; 'yes' для подтверждения удаления

$FOpen = FileOpen(@TempDir & '\Answer.tmp', 2)
FileWrite($FOpen, $Confirm)
FileClose($FOpen)

$CmdPid = Run(@ComSpec & ' /c formart ' & $DriveToFormat & ' < "' & @TempDir & '\Answer.tmp"')

While Not ProcessExists($CmdPid)
    Sleep(10)
WEnd

FileDelete(@TempDir & '\Answer.tmp')

На всякий случай я специально подставил переменной $DriveToFormat значение буквы диска Z, и переменной $Confirm значениие 'no' (не подтверждать форматирование), запускать этот скрипт очень осторожно, если у переменной $Confirm поставить значение 'yes', то следует полагать что диск будет отформатирован без подтверждения - сам не проверял :) (проверял метод на реестре).

Системны диск отформатировать из запущенной Windows не получится :no:.

amel27 05-05-2007 08:53 583308

Creat0R
Цитата:

вроде в функции уже есть возможность автоотключения кнопки ОК в нужный момент (если использовать $flag=1)
это в качестве примера использования SendMessage... кстати, с помощью этого сообщения можно ограничить возможность выбора файлов по определенному признаку - имени, типу, etc. Но для этого придется наладить "диалог" с окном выбора, а без CallBack-функций этого не осуществить.
Цитата:

какой код у параметра
На оффсайте есть очень полезная тулза, возвращающая коды по всем (или почти всем) GUI-сообщениям:
http://www.autoitscript.com/forum/in...howtopic=32691
Цитата:

BFFM_SETEXPANDED (или может нужен BFFM_SETSELECTION?)
Естественно BFFM_SETSELECTION... BFFM_SETEXPANDED служит для раскрытия определенной ветки (+) без перемещения курсора. С сообщением BFFM_SETSELECTION есть одна тонкость - дело в том, что оно на самом деле передает не строку пути, а указатель на эту строку, т.е. адрес... но у разных процессов разные адресные пространства, если управляющий скрипт создаст строку и передаст ее адрес, то главный скрипт при попытке обращения по этому адресу скорее всего вывалится с ошибкой доступа памяти или типа того. Поэтому строку должен создать главный скрипт, сообщить ее адрес управляющему скрипту, а тот уже отправит корректное сообщение BFFM_SETSELECTION. Вот один из вариантов реализации, главный скрипт:
Код:

#include <GUIConstants.au3>
Global Const $BFFM_SETSELECTION = $WM_USER + 102 ; BFFM_SETSELECTION

$initDir = "C:\Windows\System32" ; Стартовый каталог
; Создаем и заполняем структуру для $initDir
$str = DllStructCreate ("char[260]")
DllStructSetData ($str, 1, $initDir)
; Ищем окно управляющего скрипта
$hOpenDialogControl = WinGetHandle ("_FileOpenDialogControl")
; Если найдено, отправляем сообщение с указателем
If Not @error  Then
    $ret = DllCall ("user32.dll", "int", "SendMessage", _
        "hwnd", $hOpenDialogControl, _
        "int", $BFFM_SETSELECTION, _
        "int", 1, _
        "ptr", DllStructGetPtr ($str) )
EndIf
; Открываем главное окно выбора
 $files = _FileSelectFolder ('Тестирование выбора каталога')

Управляющий скрипт:
Код:

#include <GUIConstants.au3>
Global Const $BFFM_SETSELECTION = $WM_USER + 102 ; BFFM_SETSELECTION

Global $arrMsgSend [1][4]=[[0,0,0,0]] ; Массив сообщений для отправки
; Создаем фиктивное окно (для приема сообщений)
$hWndMain = GUICreate("_FileOpenDialogControl")
; Регистрируем наше пользовательское сообщение
GUIRegisterMsg ($BFFM_SETSELECTION, "_SaveMsgParms")
; Ждем открытия главного окна
WinWait ("Обзор папок")
; Обработка полученных сообщений
If $arrMsgSend[0][0] Then
    $hMsgWnd = WinGetHandle ("Обзор папок")
    For $i=1 To $arrMsgSend[0][0]
        $ret = DllCall ("user32.dll", "int", "SendMessage", _
            "hwnd",$hMsgWnd, _
            "int", $arrMsgSend[$i][1], _
            "int", $arrMsgSend[$i][2], _
            "ptr", $arrMsgSend[$i][3] )
    Next
EndIf
; Функция обработки входящих сообщений
Func _SaveMsgParms($hWnd, $iMsg, $WParam, $LParam)
    Switch $iMsg
        Case $BFFM_SETSELECTION
            $arrMsgSend[0][0]+=1
            ReDim $arrMsgSend[$arrMsgSend[0][0]+1][4]
            $arrMsgSend[$arrMsgSend[0][0]][1] = $BFFM_SETSELECTION
            $arrMsgSend[$arrMsgSend[0][0]][2] = $WParam
            $arrMsgSend[$arrMsgSend[0][0]][3] = $LParam
    EndSwitch
EndFunc


amel27 05-05-2007 09:15 583312

Creat0R
Цитата:

Как можно средставми RegExp осуществлять массовую замену в переменной?
RegExp подерживает только одну заменяющую строку (3-й параметр), причем она даже не является регулярным выражением (за исключением групповых подстановок)... а в чем собственно проблема?.. неужели так существенна одна лишняя строка кода?

Creat0R 05-05-2007 11:52 583352

amel27
Цитата:

На оффсайте есть очень полезная тулза, возвращающая коды по всем (или почти всем) GUI-сообщениям:
Класс, именно это я давно(?) и искал, спасибо.

Цитата:

Поэтому строку должен создать главный скрипт, сообщить ее адрес управляющему скрипту, а тот уже отправит корректное сообщение BFFM_SETSELECTION
А обязательно создавать фиктивное окно, пмещать в массив данные и передавать обратно в окно выбора каталога? :wacko:
Может можно как то передавать нужные данные через ком. строку? (в этот же скрипт к примеру).

Но вообще, оно работает, огромнейшее спасибо за пример - спустя полтора часа колдования над ним, мне наконец удалось поместить всё это в более или менее юзабельные UDF'ы :biggrin: (см. ниже пример).

Правда есть один момент - Не получается нормально определить заголовок окна выбора каталога (Обзор папок), хотелось сделать универсально, но даже при попытке использовать класс имени окна ("classname=#32770"), почему то вместо окна обзора папок находит окно диспетчера задач... и кстати, интересно, в английской версии Windows как это окно называется, я предположил что Select folder, но не уверен.

Вот собственно адаптированные функции и пример использования:

Пример:

Код:

#include <GUIConstants.au3>
#NoTrayIcon

Global Const $BFFM_SETSELECTION = $WM_USER + 102

_FileSelFolderHandler()

$hWnd = WinGetHandle(WinGetTitle(""))
$InitDir = @WindowsDir
$FileNeeded = "Notepad.exe"

While 1
    $Ret = _FileSelectFolder('Select Folder', 0, 1, $InitDir, $hWnd)
    If @error Then ExitLoop
    If FileExists($Ret & "\" & $FileNeeded) Then ExitLoop

        MsgBox(48, "Error", "Please select folder that contain " & $FileNeeded, 3)
    $InitDir = $Ret
WEnd

If Not @error Then MsgBox(64, "Results", "File <" & $FileNeeded & "> was found in selected directory (" & $Ret & ")")

На заметку - В начале примера присутствие функции _FileSelFolderHandler() жизнено необходимо, иначе вас ждёт весьма неприятная учесть (которая постигла меня) - скрипт “начнёт запускать себя” бесконечно, я наверно минут 5 боролся с его процессами вооружившись ProcessKiller'ом :moderator

Функции:

Код:

Func _FileSelectFolder($title, $root = 0, $flags = 0, $InitDir = '', $hwnd = 0)
    Local $ret, $pidl, $res = ''
    ; Создание структур данных
    Local $ubi = DllStructCreate ("hwnd;ptr;ptr;ptr;int;ptr;ptr;int") ; управляющая структура BROWSEINFO
    Local $utl = DllStructCreate ("char[512],char") ; заголовок окна
    Local $urs = DllStructCreate ("char[260]") ; буфер для возвращаемого пути (длиной MAX_PATH)
    Local $ulf = BitOR (BitShift(BitAnd ($flags,1),-9), _ ; 1: не позволять создавать новые каталоги
        BitShift(BitAnd ($flags,2),-5), _ ; 2: использовать новый стиль диалога
        BitShift(BitAnd ($flags,4),-2), 1) ; 4: включить cтроку редактирования ;Последняя единица для деактивирования кнопки OK.
    ; Заполнение структур данных
    DllStructSetData ($utl, 1, $title)
    DllStructSetData ($ubi, 1, $hwnd)
    DllStructSetData ($ubi, 3, DllStructGetPtr($urs))
    DllStructSetData ($ubi, 4, DllStructGetPtr($utl))
    DllStructSetData ($ubi, 5, $ulf)
    $ret = DllCall ("shell32.dll", "ptr", "SHGetSpecialFolderLocation", _
        "int", 0 , _
        "int", $root , _
        "ptr", DllStructGetPtr($ubi, 2))
    If $ret[0] Then Return $res
   
        ;Запуск управляющего скрипта
        Local $RunLine = '"' & @ScriptFullPath
        If Not @Compiled Then $RunLine = @AutoItExe & ' "' & @ScriptFullPath
        Run($RunLine & '" /SetInitDir')
       
    WinWait("_FileOpenDialogControl", "", 3)
       
        ; Создаем и заполняем структуру для $initDir
        $str = DllStructCreate ("char[260]")
        DllStructSetData ($str, 1, $initDir)
        ; Ищем окно управляющего скрипта
        $hOpenDialogControl = WinGetHandle("_FileOpenDialogControl")
        ; Если найдено, отправляем сообщение с указателем
        If Not @error  Then
                $ret = DllCall ("user32.dll", "int", "SendMessage", _
                        "hwnd", $hOpenDialogControl, _
                        "int", $BFFM_SETSELECTION, _
                        "int", 1, _
                        "ptr", DllStructGetPtr ($str) )
        EndIf
       
        ; Открытие окна выбора каталога
        $pidl = DllCall ("shell32.dll", "ptr", "SHBrowseForFolder", "ptr", DllStructGetPtr ($ubi))
    If $pidl[0] Then
        $ret = DllCall ("shell32.dll", "int", "SHGetPathFromIDList", _
            "ptr", $pidl[0], _
            "ptr", DllStructGetPtr ($urs))
        If $ret[0] Then $res = DllStructGetData ($urs, 1)
        DllCall ("ole32.dll", "int", "CoTaskMemFree", "ptr", $pidl[0]) ; чистим за собой
    Else
                Return SetError(1)
        EndIf
    DllCall ("ole32.dll", "int", "CoTaskMemFree", "ptr", DllStructGetData ($ubi, 2))
    Return $res ; Вывод результата
EndFunc

Func _FileSelFolderHandler()
        If $CmdLine[0] > 0 And $CmdLine[1] = "/SetInitDir" Then
                Local $FSFTitle = "Обзор папок", $hMsgWnd
                If @OSLang <> 0419 Then $FSFTitle = "Select Folder"
                Global $arrMsgSend [1][4]=[[0,0,0,0]]
               
                Local $hWndMain = GUICreate("_FileOpenDialogControl")
                GUIRegisterMsg ($BFFM_SETSELECTION, "_SaveMsgParms")
               
                WinWait($FSFTitle, "", 3)
               
                If $arrMsgSend[0][0] Then
                        $hMsgWnd = WinGetHandle($FSFTitle)
                        For $i=1 To $arrMsgSend[0][0]
                                DllCall ("user32.dll", "int", "SendMessage", _
                                        "hwnd",$hMsgWnd, _
                                        "int", $arrMsgSend[$i][1], _
                                        "int", $arrMsgSend[$i][2], _
                                        "ptr", $arrMsgSend[$i][3] )
                        Next
                EndIf
                Exit
        EndIf
EndFunc

Func _SaveMsgParms($hWnd, $iMsg, $WParam, $LParam)
    Switch $iMsg
        Case $BFFM_SETSELECTION
            $arrMsgSend[0][0]+=1
            ReDim $arrMsgSend[$arrMsgSend[0][0]+1][4]
            $arrMsgSend[$arrMsgSend[0][0]][1] = $BFFM_SETSELECTION
            $arrMsgSend[$arrMsgSend[0][0]][2] = $WParam
            $arrMsgSend[$arrMsgSend[0][0]][3] = $LParam
    EndSwitch
EndFunc


Creat0R 05-05-2007 12:37 583364

amel27
Цитата:

в чем собственно проблема?.. неужели так существенна одна лишняя строка кода?
Эх, если-бы одна... иногда такие замены приходится делать по 10, а то и 20 раз...

В общем решил я эту задачку UDF'ным путём ;) ...

Код:

$String = 'file://localhost/%22c:/my%20test/test.zip%22'
$Patern = 'file://localhost/|/|%20|%22'
$Replace = '|\\| |"'

$Results = _StringRexExpReplaceEx($String,

MsgBox(64, "Results", $Results) ;На выходе имеем это: "c:\my test\test.zip"

Func _StringRexExpReplaceEx($String, $Patern, $Replace)
    If StringInStr($Patern, '|') And StringInStr($Replace, '|') Then
        Local $PaternArr = StringSplit($Patern, '|')
        Local $ReplaceArr = StringSplit($Replace, '|')
        Local $Ret = $String
        Local $Ubound = UBound($ReplaceArr)
        If UBound($PaternArr) <= UBound($ReplaceArr) Then $Ubound = UBound($PaternArr)
        For $i = 1 To $Ubound-1
            $Ret = StringRegExpReplace($Ret, $PaternArr[$i], $ReplaceArr[$i])
        Next
        Return $Ret
    Else
        Return StringRegExpReplace($String, $Patern, $Replace)
    EndIf
EndFunc

Правда не удаётся сделать замену по ссимволу | - но мне пока что это не нужно :)

amel27 06-05-2007 09:02 583629

Creat0R
Цитата:

А обязательно создавать фиктивное окно, пмещать в массив данные и передавать обратно в окно выбора каталога?
- Без GUI-окна некому будет отправлять GUI-сообщение... Конечно, в Windows есть и другие способы межпроцессного обмена, просто я не мудрствуя использовал тот же метод доставки, что и для окна "Обзор папок" (через SendMessage). Альтернативный способ - расшарить именованный кусок памяти, но для этого придется опять колдовать с API-функциями... Через консоль наверно тоже можно, но без "извращений" не обойдется, так как строго говоря AutoIT-приложения не являются консольными;
- для одного сообщения массив понятно не нужен, это я с запасом на обработку нескольких сообщений зарядил SWITCH, ну и соответственно массив;
Цитата:

Не получается нормально определить заголовок окна выбора каталога (Обзор папок)
ну да, проблематично определить HWID окна, которое еще не создано :) ... тем более, что класс у него вполне стандартный, как вариант - использовать для идентификации кроме заголовка - текст окна, переданный первым параметром функции.

ADD:помнится, я еще практиковал межскриптовый обмен через ключи рееестра... скажем, один меняет значение извеcтного параметра, а второй в цикле отслеживает эти значения и делает свои выводы (по SWITH)... хотя это было вызвано совсем другими причинами - оба скрипта крутились под разными учетками, один под SYSTEM, а второй под рядовым пользователем.

amel27 07-05-2007 11:30 583972

Creat0R

Вроде разобрался с DLL-кой, проблема была не в GUIRegisterMsg (она-то как раз работает), а в самой DLL-ке... Нашел где подправить чтобы запустилась, осталось только состыковаться с автором и перекомпилить как надо. :)

Все-таки через CallBack все выглядит намного круче - можно по ходу получать инфу о выбранных файлах/каталогах, фильтрах, контролировать правильность ввода в Edit-Boxе и на основании этого менять подстветку, текст кнопок или текст статус-бара.

mrak1990 07-05-2007 16:30 584100

Цитата:

Покопался я насчёт этого вопроса. Но только начал копать в сторону меню у папок и файлов и пришёл к выводу, что такие пункты как "WinRAR", "Проверить на вирусы" (Kaspersky) добавляются из .dll-файлов. Потом даже открыл какой-то из файлов WinRAR,а и нашёл там строки из контекстного меню.
А у меня на рабочем столе в меню есть пункт "Панель управления NVIDIA", которую можно убирать через настройки. Я думаю с этим пунктом таже история, что и с WinRAR - как-то через DLL. Короче на данном этапе врядли что-то получится сделать.
Я в общем покопался ещё с этой всей фигнёй. И у меня получилось всё ьаки добавить свой пункт в меню. Проблема в том что на неё нельзя повесить команду, а только ID.
Код:

MENUITEM "Мой пункт", 29640
Где можно узнать или где содержится этот список команд и соответствующих им ID?

Нашёл ссылку, вроде бы относящуюся к делу: http://msdn2.microsoft.com/en-us/library/aa381023.aspx

amel27 10-05-2007 13:00 585083

Creat0R

Автор DLL-ки подкинул идею, как можно попробовать реализовать средствами AutoIT... К сожалению, фокус прокатил только с классическим интерфейсом, но это уже большой плюс!.. Для окна в стиле Explorer без сторонних модулей видимо не обойтись.
Код:

#include <GUIConstants.au3>

Global Const $BFFM_SETSELECTION = $WM_USER + 102

Global Const $BIF_BROWSEFORCOMPUTER = 0x1000 ; Выбирать только компьютеры в сетевом окружении
Global Const $BIF_BROWSEFORPRINTER = 0x2000 ; Выбирать только принтеры в сетевом окружении
Global Const $BIF_BROWSEINCLUDEFILES = 0x4000 ; Позволить выбирать файлы
Global Const $BIF_DONTGOBELOWDOMAIN = 0x2 ; Не открывать домены в сетевом окружении
Global Const $BIF_EDITBOX = 0x10 ; Включить строку редактирования
Global Const $BIF_RETURNONLYFSDIRS = 0x1 ; Выбирать только объекты файловой системы

Global Const $BIF_OLDSTYLEFLAGS = BitOR ($BIF_BROWSEFORCOMPUTER, $BIF_BROWSEFORPRINTER, $BIF_BROWSEINCLUDEFILES, _
    $BIF_DONTGOBELOWDOMAIN, $BIF_EDITBOX, $BIF_RETURNONLYFSDIRS)

; Примитивный ГУИ для примера
$hWndMain = GUICreate ("Тест", 200, 45, -1, -1)
$Button_1 = GUICtrlCreateButton ("Выбрать папку",  55, 10)
GUISetState()
While 1
    $msg = GUIGetMsg()
    Select
        Case $msg = $GUI_EVENT_CLOSE
            ExitLoop
        Case $msg = $Button_1
            $res = _FileSelectFolderOldStyle ('Выбор объекта:', 0, $BIF_RETURNONLYFSDIRS, 'C:\Windows', $hWndMain)
            MsgBox (0, "Выбран объект:", $res)
    EndSelect
Wend

; Процедура инициализации стартового каталога
Func _FileSelectFolderOldStyleProc ($hWnd, $Msg, $wParam, $lParam)
    $ret = DllCall ("user32.dll", "int", "SendMessage", _
        "hwnd",$hWnd, _
        "int", $BFFM_SETSELECTION, _
        "int", 1, _
        "ptr", $lParam )
EndFunc

Func _FileSelectFolderOldStyle ($text = '', $root = 0, $flags = 0, $iniDir = '', $hwnd = 0)
    Local $ret, $pidl, $res = ''
    ; Создание структур данных
    Local $ubi = DllStructCreate ("hwnd;ptr;ptr;ptr;int;ptr;ptr;int") ; управляющая структура BROWSEINFO
    Local $utl = DllStructCreate ("char[512],char") ; текст окна
    Local $urs = DllStructCreate ("char[260]") ; буфер для возвращаемого пути (длиной MAX_PATH)
    Local $ulf = BitAnd ($flags, $BIF_OLDSTYLEFLAGS) ; фильтруем только разрешенные флаги
    ; Заполнение структур данных
    DllStructSetData ($utl, 1, $text)
    DllStructSetData ($ubi, 1, $hwnd)
    DllStructSetData ($ubi, 3, DllStructGetPtr($urs))
    DllStructSetData ($ubi, 4, DllStructGetPtr($utl))
    DllStructSetData ($ubi, 5, $ulf)
    If ($iniDir <> '') And ($hwnd <> 0) Then
        Local $udr = DllStructCreate ("char[" & StringLen ($iniDir)+1 & "]")
        DllStructSetData ($udr, 1, $iniDir)
        $ret = DllCall ("user32.dll", "ptr", "GetWindowLong", "hwnd", $hwnd,  "int", -4)
        DllStructSetData ($ubi, 6, $ret[0])
        DllStructSetData ($ubi, 7, DllStructGetPtr($udr))
    EndIf
    $ret = DllCall ("shell32.dll", "ptr", "SHGetSpecialFolderLocation", _
        "int", 0 , "int", $root , "ptr", DllStructGetPtr($ubi, 2) )
    If $ret[0] Then Return $res
    GUIRegisterMsg (1, "_FileSelectFolderOldStyleProc") ; регистрируем событие для перехвата
    ; Открытие окна выбора каталога
    $pidl = DllCall ("shell32.dll", "ptr", "SHBrowseForFolder", "ptr", DllStructGetPtr ($ubi))
    GUIRegisterMsg (1, "") ; разрегистрируем событие
    If $pidl[0] Then
        $ret = DllCall ("shell32.dll", "int", "SHGetPathFromIDList", _
            "ptr", $pidl[0], "ptr", DllStructGetPtr ($urs))
        If $ret[0] Then $res = DllStructGetData ($urs, 1)
        DllCall ("ole32.dll", "int", "CoTaskMemFree", "ptr", $pidl[0]) ; чистим за собой
    EndIf
    DllCall ("ole32.dll", "int", "CoTaskMemFree", "ptr", DllStructGetData ($ubi, 2))
    Return $res ; Вывод результата
EndFunc


Creat0R 10-05-2007 14:45 585139

amel27
Цитата:

К сожалению, фокус прокатил только с классическим интерфейсом, но это уже большой плюс!
Это огромный плюс!!! а зачем больше, классика есть классика :) - Тем более что строка состояния есть, возможность выбора только объектов файловой системы есть, "родительский/дочерний статус" есть :), и даже есть опция выбора не только каталогов, но и файлов!!! (о чём я лично, вообще и не подозревал в подобном диалоге)... что ещё нужно?

Большое спасибо тебе, и автору идеи!

Diamond 11-05-2007 03:20 585427

Завершение процессов и служб
Некоторые процессы невозможно завершить с помощью ProcessClose() т.к. они имеют отношение к службам.
А если такой просесс завершить принудительно, (например с помощью консольной команды TASKKILL) то в журнал системных событий записывается сообщение об ошибке, и потом что либо найти в нём с каждым разом становится всё труднее...
Всё это навело меня на мысль написать скрипт:

Код:

$ProcessName="oodag.exe" ; имя завершаемого процесса
;~ Подключаемся к WMI:
$WMI = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\.\root\CIMV2")
$PID = ProcessExists($ProcessName) ;Определяем PID
If $PID Then ProcessClose($PID) ; Если существует - пытаемся убить
If ProcessExists($PID) Then ; Если процесс всё ещё существует тогда
        $OutputName=CheckService($PID) ; проверяем принадлежность процесса к службам (проверку можно пропусить!!!)
        If Not $OutputName=0 Then ; Если является службой тогда
        $Pressed=MsgBox(262144+32+4,"", "Не удалось завершить процесс поскольку"& @CR & _
        "он является запущенной службой: " & $OutputName & @CR & _
        "Остановить службу?")
                If $Pressed=6 Then KillService($PID) ; Если "Да" - останавливаем службу
        EndIf
EndIf

;~ ==================================================
;~ Определяет, является ли процесс запущенной службой (Эту функцию можно исключить!!!)
;~ Если является службой - возвращает "Выводное имя" службы, в противном случае 0
Func CheckService($PrPid)
;~ Формируем текст запроса:
$QueryText = "SELECT * FROM Win32_Service WHERE  ProcessId = '" & $PrPid & "'"
;~ Создаём объект-коллекцию:
$CollectionServices = $WMI.ExecQuery($QueryText)
If $CollectionServices.Count > 0 Then ; Если элементов коллекции > 0 Тогда
        ;~ Цикл по элемент(у)ам коллекции:
        For $objItem In $CollectionServices
                Return $objItem.DisplayName
        Next
Else
        Return 0
EndIf
EndFunc

;~ ==================================================
;~ Останавливает службу, в случае успеха возвращает: 0
Func KillService($PrPID)
;~ Формируем текст запроса:
$QueryText = "SELECT * FROM Win32_Service WHERE  ProcessId = '" & $PrPid & "'"
;~ Создаём объект-коллекцию:
$CollectionServices = $WMI.ExecQuery($QueryText)
If $CollectionServices.Count > 0 Then ; Если элементов коллекции > 0 Тогда
        ;~ Цикл по элемент(у)ам коллекции:
        For $objItem In $CollectionServices
                Return $objItem.StopService()
        Next
EndIf
EndFunc


Diamond 11-05-2007 04:34 585434

mrak1990
Цитата:

А с чем это связано? Как я понял, при запуске скрипа он первым делом обрабатывается интерпретатором и висит в памяти. И он уже не обращается к файлу. Возможно, что я и не прав. У кого есть мысли по этому поводу - пишите.
При запуске, скрипт действительно обрабатывается интерпретатором и загружается в память, после чего может быть переименован или удалён.
Я думаю единственным препятствием может быть "блокирующий дескриптор" - а откуда ему там взятся, если только в момент переименования, файл не открыт для записи каким либо другим процессом (естественно, такое "открытие" может произойти только с ведома пользователя).

mrak1990 11-05-2007 20:56 585828

Diamond
Цитата:

При запуске, скрипт действительно обрабатывается интерпретатором и загружается в память, после чего может быть переименован или удалён.
Я думаю единственным препятствием может быть "блокирующий дескриптор" - а откуда ему там взятся, если только в момент переименования, файл не открыт для записи каким либо другим процессом (естественно, такое "открытие" может произойти только с ведома пользователя).
К счастью скрипт такой, что на выполнение не требуется особого времени. Тем более, я им сейчас активно пользуюсь. Вроде всё без глюков.
Единственное, что надо будет дописать, чтобы он обновлял не только открытые окна, рабочий стол, но и диалог выбора\открытия файла. Но в этом нет ничего трудного, к счастью.

VelDmi 13-05-2007 12:06 586283

Почему вот такой батник работает:
fsum.exe -c -r -d%inputdir% %mdfile% > fsum.err
а автоит нет:
RunWait (@ScriptDir& '\fsum.exe -c -r -d' &$inputdir& ' ' &$mdfile& ' > ' &@ScriptDir& '\fsum.err', @ScriptDir)
пробовал так-же
RunWait (@COMSPEC & ' /c fsum.exe -c -r -d' &$inputdir& ' ' &$mdfile& ' > ' &@ScriptDir& '\fsum.err', @ScriptDir)

Как привильно запустить команду?

Creat0R 13-05-2007 16:31 586342

VelDmi
Цитата:

Как привильно запустить команду?
А в чём проявляется проблема с данным примером?

Возможно путь к скрипту содержит пробелы, или служебные символы, в таком случае надёжнее заключать пути в кавычки:

Код:

RunWait ('"' & @ScriptDir & '\fsum.exe" -c -r -d' & $inputdir & ' ' & $mdfile & ' > "' & @ScriptDir & '\fsum.err"', @ScriptDir)

VelDmi 13-05-2007 17:45 586364

не работает > fsum.err, то есть при вызове из автоит не пишет в файл fsum.err

amel27 14-05-2007 06:20 586535

VelDmi
проверил - с @COMSPEC все работает, попробуй вместо /c поставить /k и отследить сообщения

VelDmi 14-05-2007 09:39 586570

amel27
Посмотри пожалуйста пример вживую. http://rapidshare.com/files/31198773/1.rar.html
Батником у меня создается файл, а автоитом нет.

amel27 14-05-2007 12:36 586643

VelDmi
CMD ругался на кавычки после ">", так с кавычками вроде работает:
Код:

$CutDir = '"' &@ScriptDir& '\CutDir' & '"'
$exfile = '"' &@ScriptDir& '\fsum.exe' & '"'
$mdfile = '"' &@ScriptDir& '\sums.md5' & '"'
$erfile = '"' &@ScriptDir& '\fsums.err' & '"'

RunWait (@COMSPEC & ' /c ' & '(' & $exfile & ' -c -r -d' & $CutDir & ' ' & $mdfile & ' >' & $erfile & ')', @ScriptDir)


Creat0R 15-05-2007 06:06 586937

Вышла новая версия - AutoIt v3.2.4.1...

Из глобальных изменении:

*AutoIt теперь скомпилирован для Unicode, AutoIt3.exe для Unicode - AutoIt3A.exe для ANSI. Для более подробной информации смотрите эту страницу.
*Переписан инструмент для работы с окнами (Au3Info tool).
*Функции бинарных данных полностью переписаны - скрипты использующие эти функции будет необходимо изменить.

Справка на русском для AutoIt v3.2.4.0.

storm2005 15-05-2007 16:11 587188

Интересует взлом скомпилированного AutoIt .exe. Можно или нет это сделать, если при компиляции был выставлен пароль или убрана галка позволяющая декомпилировать?

Creat0R 15-05-2007 17:25 587236

storm2005
Цитата:

Можно или нет это сделать, если при компиляции был выставлен пароль или убрана галка позволяющая декомпилировать?
Если был выставлен пароль, то естественно при его наличии это возможно, а вот если была убрана галка позволяющая декомпилировать, то нет.

storm2005 16-05-2007 10:02 587501

Цитата:

Если был выставлен пароль, то естественно при его наличии это возможно, а вот если была убрана галка позволяющая декомпилировать, то нет.
если есть пароль но он неизвестен. можно ли декомпилировать?

интересует этот вопрос т. к. хочу устанавливать некоторый софт через логонный скрипт юзера. но проблема в том, что под юзером большинство софта не ставится т. к. юзер не обладает административными правами. в AutoIt нашел замечательную функцию RunAsSet в которой можно передать пароль в отличие от команды runas. но хотелось быть уверенным, что скомпилировав скрипт под паролем его никто не декомпилирует.

amel27 16-05-2007 17:12 587671

storm2005
Цитата:

если есть пароль но он неизвестен. можно ли декомпилировать?
Можно, причем это ответ не мой, а разработчиков... Говорят есть хакнутый aut2exe, декомпилирующий такие скрипты, хотя сам я его не видел... впрочем и не искал.
Цитата:

проблема в том, что под юзером большинство софта не ставится т. к. юзер не обладает административными правами
такие задачи обычно решаются клиент-серверным методом, когда один модуль работает с правами системы/админа и заточен на выполнение конкретных задач (например, установки софта), а второй - под обычным юзером и дает ему "команды"... Для этого можно использовать технологии COM, WMI или обычный скрипт, запущенный в качестве службы.

NikLok 16-05-2007 22:22 587750

storm2005
Цитата:

но хотелось быть уверенным, что скомпилировав скрипт под паролем его никто не декомпилирует.
Очень хочется примеры таких скриптов узнать! В смысле какую такую инфу ты защищаешь от пользователя.?!
ALL
Последнее время при адаптации скриптов под новые версии программ наталкиваюсь на странное поведение AutoIT.

А именно при выполнении команды ControlClick как бы не происходит отработки нажатия кнопки.
Например это началось в Wintools Net Pro начиная с версии после 8.1.1
Есть такой же проблемный кусок и в установке OutPost (вернее он всегда там был)
Код:

        WinWaitActive("Configuration Wizard","")
        $text = WinGetText("Configuration Wizard","")
        If StringRegExp($text,"Some applications that can cause system stability issues") Then
                If Not WinActive("Configuration Wizard","Some applications that can cause system stability issues") Then WinActivate("Configuration Wizard","Some applications that can cause system stability issues")
                WinWaitActive("Configuration Wizard","Some applications that can cause system stability issues")
                Send("{TAB}{ENTER}")
        EndIF

        If StringRegExp($text,"Advanced security") Then
                If Not WinActive("Configuration Wizard","Advanced security") Then WinActivate("Configuration Wizard","Advanced security")
                WinWaitActive("Configuration Wizard","Advanced security")
                Sleep(30)
                ControlClick("Configuration Wizard","Advanced security","Button3")
                Sleep(30)
                Send("{ENTER}")
        EndIF

Не получается выбрать "Advanced security" и пройти далее.

Может кто-то уже решал такую проблему?!
Может как-то можно задавать длительность нажатия кнопки?!

Angel_19 17-05-2007 20:17 588094

В обсуждаемом продукте вроде есть запись макросов - как это можно осуществить и можно ли?

VelDmi 17-05-2007 20:48 588110

Имеется каталог CutDir. в нем куча файлов. Есть файл (file.txt) содержащий строки вида:
C:\Compare\CutDir\Bin\SD0405.dll
C:\Compare\CutDir\Bin\LOA\SD0434.dll
C:\Compare\CutDir\WEZ\BIGz\erwg.dll

Как правильнее удалить из каталога все файлы, не содержащиеся в списках?
Пробовал

$line = FileReadLine($file)
FileMove ($CutDir & $line2, $DestDir & $line2, 0)
Работает, только для файлов в корне каталога CutDir, т.е. он не создает автоматически вложенные каталоги при копировании. А мне нужно оставить только файлы, перечисленные в списке, причем и во всех вложенных каталогах тоже.

Creat0R 17-05-2007 21:46 588119

VelDmi
amel27 как то написал функцию возвращающую массив дерева каталогов включая подкаталоги, с её помощью эту задачу реализовать довольно просто:

Код:

#include <Array.au3>
#include <File.au3>

;Создаём нужные переменные и массив для содержания списка файлов которые удалять не нужно
$Dir = "CutDir"
$ExcludeListFile = "file.txt"
Dim $ExcludeListArr[1]

;Получаем массив структуры каталогов в папке "CutDir" (из переменной $Dir)
$DirsArray =  _DirListToArray($Dir)

;Получаем массив со списком файлов которые не нужно удалять (из файл от переменной $ExcludeListFile)..
_FileReadToArray($ExcludeListFile, $ExcludeListArr)

;Проходим по массиву структуры каталогов, получаем массив со списком файлов в каждом каталоге, и удаляем файлы не находящиеся в списке.
For $i = 1 To UBound($DirsArray)-1
    ;Получаем массив со списком файлов текущего каталога...
    $InDirFilesArr = _FileListToArray($DirsArray[$i], "*.*", 1)

        ;Если в текущем каталоге найдены файлы, то проходимся по массиву и ищем текущий элемент в массиве списка исключенных файлов.
    If IsArray($InDirFilesArr) Then
        For $iF = 1 To UBound($InDirFilesArr)-1
            ;Поиск элемента (текущего файла включая полный путь)...
            $SearchInArr = _ArraySearch($ExcludeListArr, $DirsArray[$i] & "\" & $InDirFilesArr[$iF])
            ;Если не найден, то удаляем файл...
            If $SearchInArr = -1 Then FileDelete($DirsArray[$i] & "\" & $InDirFilesArr[$iF])
        Next
    EndIf
Next

;Функция возвращает массив структуры подкаталогов
Func _DirListToArray ($sPath)
    Local $i, $j, $rlist[1]=[0], $blist, $alist=_FileListToArray ($sPath, '*', 2)
    If IsArray ($alist) Then
        For $i=1 To $alist [0]
            _ArrayAdd ($rlist, $sPath & "\" & $alist [$i])
            $blist = _DirListToArray ($sPath & "\" & $alist [$i])
            If $blist[0]>0 Then
                For $j=1 To $blist [0]
                    _ArrayAdd ($rlist, $blist [$j])
                Next
            EndIf
        Next
    EndIf
    $rlist [0] = UBound ($rlist) - 1
    Return $rlist
EndFunc

P.S
Я не тестировал скрипт, написал на скорую руку.

VelDmi 17-05-2007 22:30 588132

Creat0R
Уфф, мне не дано такое понять...
Написал сам через попу, но работает вроде:
Код:

RunWait (@COMSPEC & ' /c fsum.exe -r -d".\CutDir" *.* > sums.md5', @ScriptDir, @SW_HIDE)
;через эту прогу создается список файлов
$filesums = FileOpen(@ScriptDir& '\sums.md5', 0)
If $filesums = -1 Then
    MsgBox(0, "Ошибка.", "Не могу открыть файл sums.md5")
    Exit
 EndIf
$filesums2 = FileOpen(@ScriptDir& '\sums2.md5', 0)
If $filesums2 = -1 Then
    MsgBox(0, "Ошибка.", "Не могу открыть файл sums2.md5")
    Exit
 EndIf

While 1
        $i = FileReadLine($filesums2)
        If @error = -1 Then ExitLoop
        $Count2 = $Count2 + 1
WEnd
FileClose($filesums2)

While 1
    $line = FileReadLine($filesums)
        If @error = -1 Then ExitLoop
    If StringLeft ($line, 1) = ';' Then ContinueLoop
                $filesums2 = FileOpen(@ScriptDir& '\sums2.md5', 0)
                $Del = 1
                For $i = 1 To $Count2
                        If $line = FileReadLine($filesums2) Then
                                $Del = 0
                                ExitLoop
                        EndIf
                Next
                If $Del = 1 Then FileDelete ($CutDir & StringTrimLeft( $line, 34 ))
                FileClose($filesums2)
WEnd
FileClose($filesums)

теперь попробую твой способ.

Creat0R 17-05-2007 23:41 588148

VelDmi
Цитата:

Уфф, мне не дано такое понять...
Время покажет, я так тоже раньше думал, если бы мне, где то пол года назад показали подобный код, я бы точно также отреагировал ;)

Вот превратил всё это дело в функцию, теперь проверил работоспособность, вроде работает :)

Переменная $ExcludeList также может иметь сразу список файлов для исключения, вот пример - $ExcludeList = "C:\CutDir\test.txt|C:\CutDir\test2.txt" - файлы C:\CutDir\test.txt и C:\CutDir\test2.txt не будут тронуты функцией. Также можно передать во второй параметр функции _DeleteFilesWithExcludes() массив содержащий список файлов для исключения, ну и как показанно в примере, поддерживается и обычный путь к файлу, с которого будет браться список исключении.

При успешной операции, возвращает @extended, макрос будет содержать число файлов которые были удалены (именно удалены, не просто количество файлов в соответствии со списком исключении).

Код:

#include <Array.au3>
#include <File.au3>

$Dir = @ScriptDir & "\CutDir"

;Эта переменная может быть массивом, полным списком файлов исключении (разделённый через |),
;а так-же это можт быть путь к файлу содержащий список файлов которые будут исключены при удалении.
$ExcludeList = @ScriptDir & "\file.txt" ;Пример переменной - "c:\CutDir\test.txt|c:\CutDir\test2.txt" ... и т.д

_DeleteFilesWithExcludes($Dir, $ExcludeList)

If Not @error Then MsgBox(262144+64, "Finish", "Было удалено <" & @extended & "> файлов")

;Функция для удаления файлов из всех подкаталогов заданного каталога, в соответствии со списком исключении.
Func _DeleteFilesWithExcludes($sPath, $ExcludeList)
    Local $ExcludeListArr[1], $Extended = 0
    ;Если не существует каталога (в котором следует производить удаление) или переменная $sPath не является каталогом,
    ;возвращаем ошибку №1.
    If Not StringInStr(FileGetAttrib($sPath), "D") Then Return SetError(1, 0, 0)
    ;Получаем массив структуры каталогов в папке "CutDir" (из переменной $Dir)
    Local $DirsArray =  _DirListToArray($sPath)

        If Not IsArray($ExcludeList) And FileExists($ExcludeList) Then
        ;Получаем массив со списком файлов которые не нужно удалять (из файл от переменной $ExcludeList)..
        _FileReadToArray($ExcludeList, $ExcludeListArr)
    ElseIf IsString($ExcludeList) And StringInStr($ExcludeList, "|") Then
        ;Превращаем переменную в массив (разделяя этим символом |)
        $ExcludeListArr = StringSplit($ExcludeList, "|")
    ElseIf IsArray($ExcludeList) Then
        ;Присваиваем внутреннему массиву (ранее созданному) то же значение что и у массива $ExcludeList
        $ExcludeListArr = $ExcludeList
    Else
        ;Не предвиденная ошибка, передана пустая переменная или неверный формат массива/переменной - возвращаем ошибку №2.
        Return SetError(2, 0, 0)
    EndIf

        ;Получаем массив со списком файлов корневого каталога ($sPath)...
    $RootFilesArr = _FileListToArray($sPath, "*.*", 1)
    If IsArray($RootFilesArr) Then
        For $iR = 1 To UBound($RootFilesArr)-1
            ;Поиск элемента (текущего файла включая полный путь)...
            $SearchInArr = _ArraySearch($ExcludeListArr, $sPath & "\" & $RootFilesArr[$iR])
            ;Если не найден, то удаляем файл...
            If $SearchInArr = -1 Then $Extended += FileDelete($sPath & "\" & $RootFilesArr[$iR])
        Next
    EndIf

        ;Проходим по массиву структуры каталогов, получаем массив со списком файлов в каждом каталоге,
    ;и удаляем файлы не находящиеся в списке.
    For $i = 1 To UBound($DirsArray)-1
        ;Получаем массив со списком файлов текущего каталога...
        $InDirFilesArr = _FileListToArray($DirsArray[$i], "*.*", 1)

                ;Если в текущем каталоге найдены файлы, то проходимся по массиву и ищем текущий элемент в массиве списка исключенных файлов.
        If IsArray($InDirFilesArr) Then
            For $iF = 1 To UBound($InDirFilesArr)-1
                ;Поиск элемента (текущего файла включая полный путь)...
                $SearchInArr = _ArraySearch($ExcludeListArr, $DirsArray[$i] & "\" & $InDirFilesArr[$iF])
                ;Если не найден, то удаляем файл...
                If $SearchInArr = -1 Then $Extended += FileDelete($DirsArray[$i] & "\" & $InDirFilesArr[$iF])
            Next
        EndIf
    Next
    Return SetError(0, $Extended, 1)
EndFunc

;Функция возвращает массив структуры подкаталогов
Func _DirListToArray ($sPath)
    Local $i, $j, $rlist[1]=[0], $blist, $alist=_FileListToArray ($sPath, '*', 2)
    If IsArray ($alist) Then
        For $i=1 To $alist [0]
            _ArrayAdd ($rlist, $sPath & "\" & $alist [$i])
            $blist = _DirListToArray ($sPath & "\" & $alist [$i])
            If $blist[0]>0 Then
                For $j=1 To $blist [0]
                    _ArrayAdd ($rlist, $blist [$j])
                Next
            EndIf
        Next
    EndIf
    $rlist [0] = UBound ($rlist) - 1
    Return $rlist
EndFunc


Creat0R 19-05-2007 06:42 588620

Я как то сообщил на офф. форуме о серъёзном баге, наверняка многие из вас его заметили, его трудно не заметить...

Разработчики приписали моему репорту NOBUG (не бага), хотя я не согласен :).

Баг заключается в следующем - 1) В момент перетаскивания окна ГУИ скрипта по его заголовку, 2) в момент изменения размера ГУИ окна, 3) при зажатии одной из кнопок закрытия/Сворачивания/Разворачивания окна, 4) а также и при открытии любых меню гуи (как главных так и контекстных), и в добавок, 5) при открытии меню из иконки в левом верхнем углу (значок программы) - Скрпит полностью останавливается на время указанных действии.

Мне кажется что это не должно происходить, разработчики свернули вину на Windows, мол это баг самой ОС, хотя не смотря на это, некоторые программы (и кстати, написанные тоже на C++) умудряются "не останавливать" свою работу на момент перетаскивания их окна или любой другой указанной ранее “дейтяльности” со стороны юзера.

Вобщем я решил эту задачку (надеюсь временно, желательно увидеть решение этой проблеме со стороны разработчиков) вот таким образом:

Код:

#include <GuiDragable.au3>
#include <Guiconstants.au3>

Dim $LeftPos

$GuihWnd = _GuiDragableCreate("Drag GUI Demo", 300, 150, -1, -1)
GUISetBkColor(0xffffff)

$ExampleLabel = GUICtrlCreateLabel("Drag Me (but not by controls) ;)", 0, 60, 250, 20)
GUICtrlSetFont(-1, 12, 600, 0, "Tahoma")
GUICtrlSetColor(-1, 0xDD0000)

AdlibEnable("Example", 50)

DllCall("User32.dll", "long", "AnimateWindow", "hwnd", $GuihWnd, "long", 300, "long", 0x10)
GUISetState()

While 1
    Sleep(10)
WEnd

Func Example()
    $LeftPos += 3
    GUICtrlSetPos($ExampleLabel, $LeftPos, 60)
    If $LeftPos >= 300 Then $LeftPos = -250
EndFunc

Нужно в папке со скриптом иметь этот файл - http://www.autoitscript.com/forum/in...=post&id=14661

При перетаскивании окна (при зажатии мышки в любом места окна за исключением контролов, ведь мы же хотим иметь возможность нажимать на кнопки и т.п.), бегущая строка по прежнему "продолжает бежать" :) - это свидетильствует о том что скрипт не остановлен.

Creat0R 21-05-2007 21:00 589434

Метод позволяющий запускать код VBS не создавая временных файлов:


Код:

$ProcessName = "AutoIt3.exe"

$RetArr = _ProcessExistsVbs($ProcessName)

If IsArray($RetArr) Then MsgBox(64, "", "Process <" & $RetArr[1] & "> exists." & @LF & @LF & _
    "The returned PID is: " & $RetArr[2] & @LF & @LF & _
    "Returned Executable Path is: " & @LF & $RetArr[3] & @LF & @LF & _
    "Command Line of executed process is: " & @LF & $RetArr[4])

;Функция возвращает массив содержащий имя процесса, его уникальный идентификатор (PID), путь запуска, и коммандную строку запуска.
;В случае если указанный процесс не существует, возвращается 0.
Func _ProcessExistsVbs($ProcName)
    Local $Code = ""
    $Code &= 'Function ProcessExists(ProcessName)' & @LF
    $Code &= '  Set Processes = GetObject("winmgmts://localhost")' & @LF
    $Code &= '  Set myProcEnum = Processes.ExecQuery("select * from Win32_Process")' & @LF
    $Code &= '  For Each Proc In myProcEnum' & @LF
    $Code &= '      If StrComp(Proc.Name, ProcessName, 1) = 0 Or StrComp(Proc.ProcessID, ProcessName, 1) = 0 Then' & @LF
    $Code &= '          Dim RetArr' & @LF
    $Code &= '          RetArr = Array(4, Proc.Name, Proc.ProcessID, Proc.ExecutablePath, Proc.CommandLine)' & @LF
    $Code &= '          ProcessExists = RetArr' & @LF
    $Code &= '          Exit Function' & @LF
    $Code &= '      End If' & @LF
    $Code &= '  Next' & @LF
    $Code &= '  ProcessExists = 0' & @LF
    $Code &= 'End Function'

    Local $VbsObj = ObjCreate("ScriptControl")
    If @error Then Return SetError(1, 0, -1)

    $VbsObj.Language = "vbscript"
    $VbsObj.AddCode($Code)
    Local $RetArr = $VbsObj.Run("ProcessExists", $ProcName)
    If $RetArr = 0 Then Return SetError(0, 0, 0)
    Return $RetArr
EndFunc


amel27 22-05-2007 12:44 589627

Creat0R
Цитата:

как то сообщил на офф. форуме о серъёзном баге
Думаю проблема в AdLib, так как это чисто AutoIT-овский планировщик и он отключается на время передачи управления системному коду (через DLLCall), поэтому ИМХО нужно либо избегать таких вызовов, либо использовать модель GUIRegisterMsg, которая поддерживается самой системой... правда в этом случае прорисовку придется выполнять в основном цикле, а обработку нажатий наоборот в процедуре.

Цитата:

Метод позволяющий запускать код VBS не создавая временных файлов:
Весьма забавный трюк, только какая в нем польза, если возможности AutoIT на порядок шире VBS?.. Шутка. ;)

Diamond 22-05-2007 14:31 589669

Creat0R
Отлично! Очень интересный способ! :UP:
Даже не подозревал что существует такой объект...
Я выяснил что "MSScriptControl.ScriptControl" предназначен также и для JavaScript'ов. VbScript'ы у меня запускаются а вот с JavaScript'ами почему-то ничего не выходит.
Привожу два упрощённых примера для сравнения:
vbscript:
Код:

;~ Доступ к контекстному меню папок:
Dim $Code
$Code = 'Set objShellApp = CreateObject ("Shell.Application")' & @LF & _
 'Set objFolderItem = objShellApp.NameSpace("C:\").Self' & @LF & _
 'Set objFIVs = objFolderItem.Verbs' & @LF & _
 'MsgBox objFIVs.Count,0,"Кол-во элементов:"' & @LF & _
 'For Each ThisCheck in objFIVs' & @LF & _
 '        If ThisCheck.Name = "&Найти..." Then' & @LF & _
 '                ThisCheck.DoIt' & @LF & _
 '        End If' & @LF & _
 'MsgBox ThisCheck.Name' & @LF & _
 'Next'

$VbsObj = ObjCreate("MSScriptControl.ScriptControl")
$VbsObj.Language = "VbScript"
$VbsObj.AddCode($Code)

javascript:
Код:

;~ Диалог открытия файлов:
Dim $Code
$Code = 'var WshShell = WScript.CreateObject ("WScript.Shell");' & @LF & _
 'var objDialog = new ActiveXObject("UserAccounts.CommonDialog");' & @LF & _
 'objDialog.Filter = "All Files|*.*";' & @LF & _
 'objDialog.InitialDir = "C:\\";' & @LF & _
 'intResult = objDialog.ShowOpen();' & @LF & _
 'if (intResult) WshShell.PopUp(objDialog.FileName);'

$VbsObj = ObjCreate("MSScriptControl.ScriptControl")
$VbsObj.Language = "JScript"
$VbsObj.AddCode($Code)

Может я что-то делаю не так? :dont-know

Creat0R 22-05-2007 21:54 589824

amel27
Цитата:

Думаю проблема в AdLib
Я в этом не уверен, это не только связанно с этой процедурой, она чисто для демонстрации бага(?). Мне кажется останавливается весь скрипт целиком, и вот вроде этому доказательство...

Код:

Opt("GuiOnEventMode", 1)

GUICreate("Test")
GUISetOnEvent(-3, "Quit")

GUICtrlCreateMenu("Test Menu")

GUISetState()

While 1
    Sleep(10)
    ConsoleWrite("! test")
WEnd

Func Quit()
    Exit
EndFunc

Тащим ГУИ, или просто нажимаем на, вроде полусозданное меню, и в консоль ничего не пишется....

Цитата:

нужно либо избегать таких вызовов, либо использовать модель GUIRegisterMsg, которая поддерживается самой системой
А возможно ли таким методом запустить выполнение определённх операции по заданному интервалу? (аналогично Adlib). Хотя сомневаюсь что это поможет, скрипт всё ровно будет останавливаться (полагаю).

Цитата:

Весьма забавный трюк, только какая в нем польза, если возможности AutoIT на порядок шире VBS?
Динамический код однако ;) - Можно таким образом создавать функции в обычном файле, чтобы даже закомпилированный скрипт мог их обрабатывать - ну это как опция вообще то, а замысел в том, что иногда функция на VBS сработает куда быстрее чем AutoIt'овская (в некоторых случаях), основная идея не моя, это я "украл" на офф. форуме, там для сортировки ListView (при чём очень быстрой) используется именно такой метод. А я всего лишь по такому же методу сделал набросок для функции ProcessExists() (которую недавно написал на VBS), и в качестве демонстрации использовал её в коде :).

Creat0R 22-05-2007 22:07 589832

Diamond
Цитата:

VbScript'ы у меня запускаются а вот с JavaScript'ами почему-то ничего не выходит.
Я если честно с JavaScript никогда не работал, скорее всего нужен либо другой объект, либо другой синтаксис для этого объекта, у меня подобные ошибки выводились когда писал неверный синтаксис в коде VBS, видимо для обработки кода нужен точный синтаксис, иначе действие для объекта не релевантное.

amel27 23-05-2007 04:27 589897

Creat0R
Цитата:

Мне кажется останавливается весь скрипт целиком
а я и не оспаривал, только предложил обходной путь :)
Цитата:

А возможно ли таким методом запустить выполнение определённх операции по заданному интервалу?
из самого скрипта нет, ты веть сам это показал выше ;) ... только извне
Цитата:

сомневаюсь что это поможет, скрипт всё ровно будет останавливаться
не будет, так как вызовы функций выполняет система а не скрипт - проверено!

VelDmi 23-05-2007 04:57 589899

Цитата:

Мне кажется останавливается весь скрипт целиком, и вот вроде этому доказательство...
Если создать в autoit прогресс бар и нажать на него мышкой, то он остановится.
Если во время архивации WINRAR нажать на окно мышкой архивация остановится! Мне кажется тут дело в системе, а не в Autoit.

Creat0R 23-05-2007 05:52 589905

amel27
Цитата:

не будет, так как вызовы функций выполняет система а не скрипт - проверено!
Ок, а как это реализовать? :shuffle: (хотябы набросок того как оно будет запускать к примеру каждые 100 мс определённую функцию).

VelDmi
Цитата:

Если создать в autoit прогресс бар и нажать на него мышкой, то он остановится.
Нажать мышкой на сам прогресс? у меня не останавлвиается :idontnow: .

Цитата:

Если во время архивации WINRAR нажать на окно мышкой архивация остановится!
Это да, видимо когда писали Winrar это не предусмотрели :).

Цитата:

Мне кажется тут дело в системе, а не в Autoit.
Как раз то нет, я об этом и твердил...

Цитата:

разработчики свернули вину на Windows, мол это баг самой ОС, хотя не смотря на это, некоторые программы (и кстати, написанные тоже на C++) умудряются "не останавливать" свою работу на момент перетаскивания их окна или любой другой указанной ранее “дейтяльности” со стороны юзера.
Добавлено:
Т.е получается, что это ответственность программиста предусматривать подобные вещи, а не системы...

TERMINAL 23-05-2007 16:24 590151

Хотел написать автоустановку разных антивирусов-написал, но проблема вот такая- каждый антивирус заканчивает свою установку по разному и у меня проблема с теми которые начинают сразу после установки сканить диски. Паузу ставить безсмыслено, а вот с процессами поработать можно было было. Какой скрипт лучше написать, если при сканировании антивир процесс грузит примерно до 40 процентов, а когда закончен равен нулю =0 (я так думаю) !? Или может кто-то с этим сталкивался? Свои мысли может изложить...

Diamond 24-05-2007 06:35 590343

Creat0R
VelDmi
Мне трудно представить что кто-то, с затёкшим от напряжения пальцем, упорно удерживает панель заголовка, во время работы приложения. :laugh:
Цитата:

Т.е получается, что это ответственность программиста предусматривать подобные вещи, а не системы...
Полностью согласен, но при этом возникает интересный парадокс. :)
Мы требуем от разработчиков исправления бага, но в тоже время забываем что сами являемся в определённой степени разработчиками приложений на AutoIT.
А что нам в свою очередь, мешает исправить этот баг в собственных AutoIT сценариях. Тем более, как уже было сказано amel27 такая возможность есть:
Цитата:

Думаю проблема в AdLib, так как это чисто AutoIT-овский планировщик и он отключается на время передачи управления системному коду (через DLLCall), поэтому ИМХО нужно либо избегать таких вызовов, либо использовать модель GUIRegisterMsg, которая поддерживается самой системой... правда в этом случае прорисовку придется выполнять в основном цикле, а обработку нажатий наоборот в процедуре.
Что... для нас это сложно и не удобно? А уж что говорить о разработчиках AutoIT. Учитывая тот факт что AutoIT бесплатен, сомневаюсь что они захотят что-то глобально поменять.
Получается разработчики AutoIT, свернули вину на разработчиков Windows, а мы в свою очередь свернули вину на разработчиков AutoIT. Но никто из всех трёх (включая и нас), не хочет изменять что-либо в коде. :no:

VelDmi 24-05-2007 07:12 590346

Diamond
Цитата:

Но никто из всех трёх (включая и нас), не хочет изменять что-либо в коде.
Оно, я думаю, не очень то и надо.
Учитывая
Цитата:

Мне трудно представить что кто-то, с затёкшим от напряжения пальцем, упорно удерживает панель заголовка, во время работы приложения.

Creat0R 24-05-2007 07:30 590348

Diamond
Цитата:

Мне трудно представить что кто-то, с затёкшим от напряжения пальцем, упорно удерживает панель заголовка, во время работы приложения
Тут дело не в этом, просто иногда “скрипт вынужден” использовать внешние ресурсы, и для корректного слежения за работой этих ресурсов (что не маловажно), или даже для вывода информации возвращяемой от этих ресурсов, требуется упорное наблюдение (не упуская из виду как говорится). А когда юзеру вдруг приспичет подвигать то или иное окошко (кстати, я на оф. форуме приводил пример, что если на деактивированном меню нажать мышкой, то также весь скрипт останавливается, и юзеру нет необходимости затёкшими пальцами удерживать что либо :) ), то слежка будет нарушена, что может привести к неправильной работе родительского скрипта (я с этим не раз сталкивался, поэтому и начал эту тему).

Цитата:

Мы требуем от разработчиков исправления бага, но в тоже время забываем что сами являемся в определённой степени разработчиками приложений на AutoIT.
Да, но в отличие от остальных полноценных языков программирования, AutoIt обладает многими ограничениями, я не жалуюсь, этот инструмент для меня стал серъёзным шагом в понимании основ программирования, просто иногда хочется подвигать горизонты :) (что вполне могут сделать разработчики, не прикладывая столько усилии сколько уйдёт у нас, у “простых смертных”).

Цитата:

Что... для нас это сложно и не удобно? А уж что говорить о разработчиках AutoIT.
Ну им наверняка проще...


Цитата:

Получается разработчики AutoIT, свернули вину на разработчиков Windows, а мы в свою очередь свернули вину на разработчиков AutoIT.
Я бы так не сказал, я лично не сворачивал на них вину, просто заметил эту проблему, тем самым намекнул на то что желательно бы это поправить :)

Цитата:

Но никто из всех трёх (включая и нас), не хочет изменять что-либо в коде.
Эх, мне бы знания разработчиков AutoIt, при этом оставить свою амбицию и стремление, и о желании речи никакой не будет, оно есть... ну и чуток времени бы свободного ;)

amel27 24-05-2007 08:54 590370

Creat0R
Цитата:

Ок, а как это реализовать?
только двумя процессами:
Код:

#include <GUIConstants.au3>
; Ветвление на "генератор" по параметру командной строки: <time> <hwnd>  TimeDisp_1
If ""&$CmdLine[$CmdLine[0]]='TimeDisp_1' Then TimeDisp_1 ($CmdLine[2], $CmdLine[1])
; Регистрируем свое событие и функцию
GUIRegisterMsg ($WM_USER+1, "TimeProc_1")
$Time_1 = 100 ; период повторения
; Твой ГУИ (без изменений)
Opt("GuiOnEventMode", 1)
$hWndMain=GUICreate("Test")
GUISetOnEvent(-3, "Quit")
GUICtrlCreateMenu("Test Menu")
GUISetState()
; Запускаем генератор событий
ShellExecute (@AutoItExe, '"'& @ScriptFullPath &'" '& $Time_1 &' '& $hWndMain &' TimeDisp_1')
; Пустой цикл
While 1
    Sleep (1000)
Wend
; Код "генератора событий"
Func TimeDisp_1($hWnd, $tWait = 500)
    $hWnd = HWnd($hWnd)
    While WinExists($hWnd)
        Sleep ($tWait)
        $ret = DllCall ("user32.dll", "int", "SendMessage", "hwnd", $hWnd, "int", $WM_USER+1, "int", 0, "ptr", 0 )
    Wend
    Exit
EndFunc
; Функция обработки события
Func TimeProc_1($hWnd, $Msg, $wParam, $lParam)
    ConsoleWrite('*')
EndFunc
; Кусок ГУИ
Func Quit()
    Exit
EndFunc

Цитата:

в отличие от остальных полноценных языков программирования, AutoIt обладает многими ограничениями
все-таки это скриптовый язык, а в своей категории он имхо лучший

NikLok 24-05-2007 17:19 590555

amel27
А как ты код при вставке цветныс делаешь?

Creat0R 24-05-2007 18:29 590581

amel27
Цитата:

только двумя процессами:
Хм.. я думал это будет что-то вроде установки задачи для Windows чтобы она собственными средствами “вызывала” подобное сообщение в моём Гуи (т.е без надобности постоянного вызова вторичного скрипта).

Но оно работает, а значит это решаемо проще чем я думал, спасибо большое!

NikLok
Цитата:

А как ты код при вставке цветныс делаешь?
Вопрос не ко мне, но я всё же отвечу...

Я как то тоже поинтересовался этим вопросом, ответ от amel27 ;).

P.S
Кстати, я немного изменил метод (для себя), в принципе нет особой необходимости сохранять в файл результаты, поэтому при первом открытии Гуи галка для ввода исходного кода вручную сразу устанавлвивается, а также есть возможность после вывода результатов одной кнопкой скопировать результат в буфер обмена и закрыть Гуи.
Скоро выложу обновлённую версию.

amel27 25-05-2007 04:48 590693

Creat0R
Цитата:

я думал это будет что-то вроде установки задачи для Windows чтобы она собственными средствами “вызывала” подобное сообщение
собственными средствами можно только "зашедулить" вызов скрипта/программы, т.е. опять же процесса
Цитата:

без надобности постоянного вызова вторичного скрипта
по аналогии с CallBack можно сваять простенькую DLL-ку и отправлять сообщения из специального потока в том же процессе... если есть интерес могу попробовать на выходных... кстати, с подачи Piccaso (с оффсайта) Dll-ки собираю теперь на FreeBasic

Цитата:

Скоро выложу обновлённую версию
ADD: скрипты выкладывай в форум, интернет-качалками (типа Dounload Master) аттачи нормально берутся

Creat0R 25-05-2007 05:24 590696

amel27
Цитата:

если есть интерес могу попробовать на выходных
Есть :), спасибо.

Цитата:

крипты выкладывай в форум
Ок.

Diamond 25-05-2007 06:22 590698

VelDmi
Ну да, скорее всего так.
У многих приложений наблюдается подобное поведение. Думаю, если это можно назвать "багом", то условно.
Creat0R
Цитата:

Тут дело не в этом, просто иногда “скрипт вынужден” использовать внешние ресурсы, и для корректного слежения за работой этих ресурсов
Если речь идёт об автоматизации управляющих элементов и окон, то да. Случалось и у меня... С другой стороны, можно использовать BlockInput(), ограничится предупреждением пользователя, либо отказаться от использования GUI, ну и в конце концов запустить другой процесс(скрипт), который выполнит необходимые действия и передаст информацию GUI. Думаю, выход можно найти почти из любой ситуации.
Цитата:

Ну им наверняка проще...
Это похоже на сложившийся у многих стереотип, типа: "хорошо там, где нас нет". :)
Цитата:

Я бы так не сказал, я лично не сворачивал на них вину, просто заметил эту проблему, тем самым намекнул на то что желательно бы это поправить :)
Ведь я выразился фигурально, а под словом "мы" подразумевал если не всех, то большинство пользователей AutoIT (включая и меня). Все хотят улучшений и расширений возможностей AutoIT, а в случае обнаружения багов сетуют на разработчиков(было бы странно, если бы всё было наоборот). Но ведь если есть возможность обойти проблему другим путём, то почему бы и не попробовать.
Ну и конечно всегда остаётся второй вариант: "дождаться пока проблему решат разработчики", что кстати вполне возможно, ведь AutoIT от версии к версии набирает силу, и надеюсь что появится больше нововведений которые если даже и не исправят, то по крайней мере с большей вероятностью позволят обойти тот или иной баг.
Цитата:

Эх, мне бы знания разработчиков AutoIt, при этом оставить свою амбицию и стремление, и о желании речи никакой не будет, оно есть... ну и чуток времени бы свободного
Любое программирование требует времени и усилий, и чем больше затрачено усилий на решение поставленной задачи, тем больше радость от победы, разве нет? При этом вопрос нехватки времени уже сам по себе переходит на второй план, ведь здесь важна самоцель и я верю что у тебя она есть. А знания при таком подходе обязательно придут.

Creat0R 25-05-2007 09:41 590746

Вложений: 1
Diamond
Цитата:

можно использовать BlockInput(), ограничится предупреждением пользователя, либо отказаться от использования GUI
Ну это уже крайности, тогда нет смысла что либо говорить о ГУИ, ведь проблема замечена именно с ним ;) - Можно не прибегать к подобным крайностям, и просто деактивировать гуи, но это то самое ограничение, о которм я писал.

Цитата:

выход можно найти почти из любой ситуации.
100% согласен, но думаю в результате важен именно “выход”, и как он будет выполнен :)

Цитата:

если есть возможность обойти проблему другим путём, то почему бы и не попробовать.
От безвыходости именно это мы и делаем, но как оказывается в конце концов, эти “пробы” заканчиваются ещё большими ограничениями и подхрамываниями в работе скрипта чем те о которых я писал.

Цитата:

всегда остаётся второй вариант: "дождаться пока проблему решат разработчики", что кстати вполне возможно, ведь AutoIT от версии к версии набирает силу, и надеюсь что появится больше нововведений которые если даже и не исправят, то по крайней мере с большей вероятностью позволят обойти тот или иной баг.
“Надежда умирает последней” © - Вот поэтому я и пишу баг репорты, потому что знаю что есть шанс на фиксы, кстати, пару моих репортов (1, 2, 3, 4, 5) всё таки пофиксили ;).

Цитата:

чем больше затрачено усилий на решение поставленной задачи, тем больше радость от победы, разве нет?
Конечно да. Просто иногда после “длительных усилии” уже не хватает сил на радости :biggrin:

amel27, NikLok и ВСЕ:

Прикрепил к посту новую версию ГУИ для обработки скрпитов в “цветной вид” (для вставки на форумах).
Теперь в нём все настройки сохраняются, и добавлены многие проверки на ошибочность.

amel27
Чуть не забыл, если пропустить на обработку сам скрипт (иронично получается :) ), то находятся неопознаные стили, я что-то так и не понял, как распознавать и соответственно добавлять неопознанные стили?

amel27 25-05-2007 10:07 590762

Creat0R
Цитата:

что-то так и не понял, как распознавать и соответственно добавлять неопознанные стили
ты разве не понял принцип работы скрипта?.. Если в тексте после всех замен остались XML-теги, то считается что есть неопознанные стили... соответственно, сам себя он не сможет обработать, так как не сможет отличить XML-тег от строки сравнения.

Creat0R 25-05-2007 10:40 590779

amel27
Цитата:

соответственно, сам себя он не сможет обработать, так как не сможет отличить XML-тег от строки сравнения.
Теперь всё ясно, большое спасибо, парадокс однако получается :)

NikLok 25-05-2007 12:06 590812

Creat0R Спасибо!

VadikanМожет этот скрипт прямо к форуму прикурутить. Вставил код и он принулительно разукрасился!?

amel27 25-05-2007 15:57 590929

Вложений: 1
Creat0R
Цитата:

если есть интерес могу попробовать на выходных

Есть , спасибо
как ни странно получилось, и выглядит многообещающе... :)
Код:

#include <GUIConstants.au3>
; ГУИ
Opt("GuiOnEventMode", 1)
$hWndMain=GUICreate("Test")
GUISetOnEvent(-3, "Quit")
GUICtrlCreateMenu("Test Menu")
GUISetState()
; Регистрируем сообщение
GUIRegisterMsg($WM_USER+1, "Tick")
; Открываем DLL и возвращаем указатель на функцию
$hDll = DllOpen("ticker.dll")
$hProc = DllCall($hDll,"int","TickerPtr")
; Структура для параметров "генератора сообщений"
$parms = DllStructCreate ("hwnd;int;long;long" )
  ; Установка требуемых параметров
DllStructSetData ($parms, 1, $hWndMain) ; хэндл главного окна
DllStructSetData ($parms, 2, $WM_USER+1) ; ID сообщения
DllStructSetData ($parms, 3, 300) ; таймаут между сообщениями
DllStructSetData ($parms, 4, 0) ; сколько раз отправить сообщение
; Запускаем поток
$res = DllCall("kernel32.dll","int","CreateThread","int",0,"int",0,"ptr",$hProc[0],"int",DllStructGetPtr($parms),"int",0,"int_ptr",0)
; Пустой цикл
While 1
    Sleep (1000)
Wend
; Функция обработки события
Func Tick ($hWnd, $iMsg, $WParam, $LParam)
    ConsoleWrite (Number($WParam) & @CRLF)
EndFunc
; Снова ГУИ
Func Quit()
    Exit
EndFunc


Creat0R 26-05-2007 00:10 591097

amel27
Цитата:

как ни странно получилось
Я не сомневался :)

Старая проблема со скачакой атачментов всплыла, файл не скачивается :( - Пробовал DMaster'ом, пробовал через IE качалку, через “Сохранить по ссылке как”, но архив скачивается повреждённый (или вовсе не архив а php файл).

amel27 26-05-2007 06:06 591135

Creat0R
Цитата:

Старая проблема со скачакой атачментов всплыла, файл не скачивается
странно, на работе через прокси в IE качает, дома через диалап только DMastrer'ом... так что надежда есть, попробуй FlashGet'ом

линк: http://www.sendspace.com/file/iaq1xh

Creat0R 26-05-2007 23:36 591373

amel27
Спасибо, работает!

Правда при нажатии на кнопку закрытия/сворачивания и её удерживания (на месте, если удерживая и двигать мышку то нормально), то счётчик останавливается :( - но это не критично, а так работает... я так понял это вызваная Dll'ка посылает постоянно зарегистрированное сообщения в окно ГУИ, и этим самым “провоцируя” запуск нужной функции (зарегистрированной), так?
Хорошо что сама Dll'ка не большая, обычно они бывают большими :)

amel27 27-05-2007 03:37 591427

Creat0R
Цитата:

я так понял это вызваная Dll'ка посылает постоянно зарегистрированное сообщения в окно ГУИ, и этим самым “провоцируя” запуск нужной функции (зарегистрированной), так?
угу, самопальный AdLib :) ... имхо в исходнике и без комментов все прозрачно
Цитата:

Хорошо что сама Dll'ка не большая, обычно они бывают большими
FreeBasic рулит! ;)

Diamond 28-05-2007 10:58 591841

Системные цвета
Код:

Const $COLOR_SCROLLBAR = 0 ; - цвет полосы прокрутки
Const $COLOR_BACKGROUND = 1 ; - цвет фона окна
Const $COLOR_ACTIVECAPTION = 2 ; - цвет заголовка активного окна
Const $COLOR_INACTIVECAPTION = 3 ; - цвет заголовка неактивного окна
Const $COLOR_MENU = 4 ; - цвет меню
Const $COLOR_WINDOW = 5 ; - цвет окна
Const $COLOR_WINDOWFRAME = 6 ; - цвет обрамления окна
Const $COLOR_MENUTEXT = 7 ; - цвет текста меню
Const $COLOR_WINDOWTEXT = 8 ; - цвет текста окна
Const $COLOR_CAPTIONTEXT = 9 ; - цвет текста в заголовке окна

Const $COLOR_ACTIVEBORDER = 10 ; - цвет активной границы окна
Const $COLOR_INACTIVEBORDER = 11 ; - цвет неактивной границы окна
Const $COLOR_APPWORKSPACE = 12 ; - цвет рабочего места окна
Const $COLOR_HIGHLIGHT = 13 ; - цвет подсветки
Const $COLOR_HIGHLIGHTTEXT = 14 ; - цвет подсвеченного текста
Const $COLOR_BTNFACE = 15 ; - цвет лицевой части кнопки
Const $COLOR_BTNSHADOW = 16 ; - цвет тени кнопки
Const $COLOR_GRAYTEXT = 17 ; - цвет "серого" текста
Const $COLOR_BTNTEXT = 18 ; - цвет текста в кнопке
Const $COLOR_INACTIVECAPTIONTEXT = 19 ; - цвет текста в заголовке неактивного окна

Const $COLOR_BTNHIGHLIGHT = 20 ; - цвет текущей кнопки

;~ Получаем цвет лицевой части кнопки на текущий момент:
$OldColor = _GetSysColor($COLOR_BTNFACE)
;~ Задаём красный цвет для лицевой части кнопки:
_SetSysColor($COLOR_BTNFACE, 0xFF0000)
;~ тайм-аут 5 секунд
Sleep(5000)
;~ Восстанавливаем полученный ранее цвет
_SetSysColor($COLOR_BTNFACE, $OldColor)

############# -= ФУНКЦИИ =- #############

;~ Позволяет получать системные цвета, определённые текущими параметрами оформления
Func _GetSysColor($nIndex)
        $BGRColor = DllCall("user32.dll", "long", "GetSysColor", "long", $nIndex)
        $BGR = Hex ($BGRColor[0],6 )
        $RGB = "0x" & StringRight($BGR,2) & StringMid($BGR,3,2) & StringLeft($BGR,2)
        Return $RGB
EndFunc
 
;~ Позволяет установить новый цвет для указанного элемента оформления
Func _SetSysColor($nIndex, $nRGBColor)
        $RGB = Hex($nRGBColor,6 )
        $BGR = "0x" & StringRight($RGB,2) & StringMid($RGB,3,2) & StringLeft($RGB,2)
        Local $structColor = DllStructCreate("udword")
        Local $structIndex = DllStructCreate("udword")
        DllStructSetData($structIndex, 1, $nIndex)
        DllStructSetData($structColor, 1, $BGR)
        DllCall("user32.dll", "long", "SetSysColors", "long", 1, "ptr", DllStructGetPtr($structIndex), "ptr", DllStructGetPtr($structColor))
EndFunc


Creat0R 28-05-2007 13:50 591922

Diamond
Спасибо, давно искал что-то подобное :)

Diamond 28-05-2007 14:13 591937

Creat0R
Рад, что пригодилось. Собирал информацию как говориться с мира по нитке. :)
Вот только мне не нравиться что эти функции цвета переворачивают с RGB на GBR, надо будет потом поправить...

Diamond 29-05-2007 09:18 592301

Creat0R
Поправил. :) Теперь только RGB.

V0van3 29-05-2007 15:06 592499

Я написал AutoIt скрипт который автоматически закрывает рекламное окно в visicom 2003:

;Отслеживает и закрывает рекламное окно
;скрыть в системной панели индикатор AutoIt
;AutoItSetOption("TrayIconHide", 1)
;Отображать текущую строку сценария с помощью индикатора системной панели в режиме отладки.
AutoItSetOption("TrayIconDebug", 1)
AutoItSetOption("SendKeyDelay", 15)
;Переходим в папку с visicom
;FileChangeDir('%1%')
FileChangeDir('c:\temp\Visicom')
Run('Vcmurbas.exe')
WinWaitActive('','')
ControlClick('','Вход','Button1')
;MsgBox(4096, "", ProcessExists("mmc.exe"))
;включить режим поиска в окнах-потомках
Opt("WinSearchChildren", 1)
While ProcessExists("ntvdm.exe")<>0
;дожидаемся активности окна с рекламой
WinWait('Внимание!','Подробнее...')
WinClose('Внимание!','Подробнее...')
Sleep(200)
WEnd

запускаю %path_cmdutils%\Autoit3.exe Visicom.au3 %visicom_path% (переменные объявлены и заданы верно)
Работает (рекламные окна закрывает), но не отслеживает закрытия visicom и скрипт продолжает зацикливаться.

Прикол в том что vcmurbas.exe запущен через NTVDM и в явном виде его ProcessExists не видет :(

система Win2kSP4en, что посоветуете? Как это можно обойти?



amel27 30-05-2007 03:25 592727

V0van3
Цитата:

vcmurbas.exe запущен через NTVDM и в явном виде его ProcessExists не видет
так вроде работает:
Код:

$pid = Run("Vcmurbas.exe")

While ProcessExists($pid)
  Sleep(200)
WEnd


mariolast 30-05-2007 09:32 592773

Клевая прога для работы с телефонной книгой, картинками, мелодиями и т.п. для целой кучи 357 видов мобил
Скачать http://download.mobiledit.com/mobiledit!/MOBILedit!.exe
Русик http://msilab.net/show.php?rus=1033
Наброски AutoIt скрипта http://forum.oszone.net/showthread.p...697#post592697
:moderator
Цитата:

Цитата из Шапки темы
Данная тема предназначена для общих вопросов по AutoIt. Вопросы по установке приложений при помощи AutoIt следует задавать в соответствии с правилами форума "Автоматическая установка приложений"


voler 31-05-2007 08:06 593125

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

HTML код:

#cs
----------------------
Приложение: Adobe Acrobat
На какой(их) версии(ях) тестировалось: 7.0.0 Professional

Автор скрипта: Voler
----------------------
#ce
;предотвращение возможности множественного запуска скрипта
If WinExists(@ScriptName) Then Exit
AutoItWinSetTitle(@ScriptName)
;Отображать текущую строку сценария с помощью индикатора системной панели в режиме отладки.
AutoItSetOption("TrayIconDebug", 1)

; Установка переменных
Global $file='setup.exe', $key='keygen.exe', $AvtCode, $ACStr

Run ( $file )

;Splash
WinWaitActive ( 'Adobe Acrobat 7.0 Professional -  Setup' )
ControlClick ( 'Adobe Acrobat 7.0 Professional -  Setup', '', 'Button1' )

;Welcome to the Adobe Acrobat 7.0 Professional Setup
WinWaitActive ( 'Adobe Acrobat 7.0 Professional - Setup' )
Sleep ( 500 )
ControlClick ( 'Adobe Acrobat 7.0 Professional - Setup', '', 'Button1' )

;Click Next to view the End User License agreement.
WinWaitActive ( 'Adobe Acrobat 7.0 Professional - Setup' )
ControlClick ( 'Adobe Acrobat 7.0 Professional - Setup', '', 'Button1' )

;End User License agreement.
WinWaitActive ( 'Adobe Acrobat 7.0 Professional - Setup' )
ControlClick ( 'Adobe Acrobat 7.0 Professional - Setup', '', 'Button2' )

;Customer Information.
WinWaitActive ( 'Adobe Acrobat 7.0 Professional - Setup' )
ControlClick ( 'Adobe Acrobat 7.0 Professional - Setup', '', 'Button1' )

;Cache the Installer Files.
WinWaitActive ( 'Adobe Acrobat 7.0 Professional - Setup' )
ControlClick ( 'Adobe Acrobat 7.0 Professional - Setup', '', 'Button1' )

;PDFMaker Installation and Integration Information.
WinWaitActive ( 'Adobe Acrobat 7.0 Professional - Setup' )
ControlClick ( 'Adobe Acrobat 7.0 Professional - Setup', '', 'Button1' )

;Please select a setup type.
WinWaitActive ( 'Adobe Acrobat 7.0 Professional - Setup' )
ControlClick ( 'Adobe Acrobat 7.0 Professional - Setup', '', 'Button5' )

;Destination Folder.
WinWaitActive ( 'Adobe Acrobat 7.0 Professional - Setup' )
ControlClick ( 'Adobe Acrobat 7.0 Professional - Setup', '', 'Button1' )

; рапорт инсталятора о готовности к установки
WinWait ( 'Adobe Acrobat 7.0 Professional','Ready to Install the Program' )
WinWaitActive ( 'Adobe Acrobat 7.0 Professional','Ready to Install the Program' )
ControlClick ( 'Adobe Acrobat 7.0 Professional', 'Ready to Install the Program', 'Button1' )

; активация - начало
WinWait  ( 'Adobe Acrobat Installer','Activation Options' )

;это окно иногда появляется, а иногда нет. Закономерность появления не найдена.
If WinExists ( 'Adobe Acrobat Installer', 'Activate Using the Internet' ) Then
      WinActivate (  'Adobe Acrobat Installer', 'Activate Using the Internet' )
      WinWaitActive (  'Adobe Acrobat Installer', 'Activate Using the Internet' )
      ControlClick ( 'Adobe Acrobat Installer', 'Activate Using the Internet', 'Button3' )
EndIf

; продолжение активации - выбираем активировать по телефону
WinWaitActive ( 'Adobe Acrobat Installer','Activation Options' )
Sleep ( 500 )
ControlClick ( 'Adobe Acrobat Installer','Activation Options', 'Button2' )
Sleep ( 500 )
ControlClick ( 'Adobe Acrobat Installer','Activation Options', 'Button7' )

exit


amel27 31-05-2007 11:39 593233

voler
Цитата:

в чем может быть проблема?
проблема очевидна - при появлении окна отрабатывают сразу все 9 ControlClick'ов, т.е. для Button1, Button2, Button5, так как эти окна ничем не отличаются - используйте для идентификации текст окна. Кроме того:

- "предотвращение возможности множественного запуска скрипта" работать не будет, используйте функцию ProcessList();
- если окно может не появиться используйте WinWait() / WinWaitActive() с таймаутом ожидания.
- автоматизацию keygen'а лучше с форума убрать, задавайте вопросы по существу.

_Flame_ 31-05-2007 15:29 593357

Сейчас объясню. У меня есть программа в папке, где такое дерево каталогов.

\
\Files

Мне надо, чтобы открывался txt файл, который лежит в папке \Files


Как мне такое сделать.. (Или как вообще txt открыть...)

voler 31-05-2007 16:00 593380

Цитата:

проблема очевидна - при появлении окна отрабатывают сразу все 9 ControlClick'ов, т.е. для Button1, Button2, Button5, так как эти окна ничем не отличаются - используйте для идентификации текст окна. Кроме того:
Скажи ты имеешь ввиду вставлять текст в

WinWaitActive ( 'Adobe Acrobat 7.0 Professional - Setup' )
ControlClick ( 'Adobe Acrobat 7.0 Professional - Setup', 'Вот Сюда?', 'Button1' ) И какой текст вводить?

HTML код:

&Next >
&Cancel
< &Back
The Wizard will install Adobe Acrobat 7.0 Professional on your computer. To continue, click Next.
WARNING: This program is protected by copyright law and international treaties.
BmpDlgImage
InstallShield
InstallShield
Welcome to the Adobe Acrobat 7.0 Professional Setup


DenchikK 31-05-2007 16:08 593384

Не могу понять, как осуществить задуманное.
Идея такая:
Надо в программе заполнять 3 поля: ссылка, логин, пароль.
Список ссылок, логинов и паролей находится в файлах links.txt, logins.txt, pass.txt
Для одной ссылки, пароля и логина я знаю как это делается:

Код:

#include <GUIConstants.au3>

If WinExists(@ScriptName) Then Exit
AutoItWinSetTitle(@ScriptName)
AutoItSetOption("TrayIconDebug", 1)
AutoItSetOption("SendKeyDelay", 60)
AutoItSetOption("MouseCoordMode", 0)

Global $file, $line_logins, $line_pass, $line_links

; Чтение Файла С Логинами

$file = FileOpen("logins.txt", 0)

If $file = -1 Then
    MsgBox(0, "Error", "Unable to open file.")
    Exit
EndIf

$line_logins = FileReadLine($file)

FileClose($file)

; Чтение Файла С Паролями

$file = FileOpen("pass.txt", 0)

If $file = -1 Then
    MsgBox(0, "Error", "Unable to open file.")
    Exit
EndIf

$line_pass = FileReadLine($file)

FileClose($file)

; Чтение Файла С Линками

$file = FileOpen("links.txt", 0)

If $file = -1 Then
    MsgBox(0, "Error", "Unable to open file.")
    Exit
EndIf

$line_links = FileReadLine($file)

FileClose($file)

; Запуск программы

Run ('avaload.exe')

; Построение GUI

GUICreate("Автозаполнение", 330, 300)

$checkCN1 = GUICtrlCreateCheckbox ($line_logins, 10, 10, 180, 20)
$checkCN2 = GUICtrlCreateCheckbox ("CHECKBOX 2", 10, 30, 180, 20)
$checkCN3 = GUICtrlCreateCheckbox ("CHECKBOX 3", 10, 50, 180, 20)

$Start = GUICtrlCreateButton("Заполнить", 200, 10, 120, 20)
$Close = GUICtrlCreateButton("Выход", 200, 30, 120, 20)

GUISetState ()

; Основная Работа Скрипта

While 1
$msg = GUIGetMsg()
If $msg = $GUI_EVENT_CLOSE  Or $msg = $Close Then
        Exit

ElseIf $msg = $Start Then

      If GUICtrlRead($checkCN1) = 1 Then
                    WinActivate ("AvaRemoteLoad")
                    ControlSetText ( 'AvaRemoteLoad', '', 'Edit1', $line_links )
                    ControlSetText ( 'AvaRemoteLoad', '', 'Edit2', $line_logins)
                    ControlSetText ( 'AvaRemoteLoad', '', 'Edit3', $line_pass )
        EndIf

        If GUICtrlRead($checkCN2) = 1 Then
                    MsgBox(0,"Установка","Чекбокс 2",1)
        EndIf

        If GUICtrlRead($checkCN3) = 1 Then
                    MsgBox(0,"Установка","Чекбокс 3",1)
        EndIf

EndIf
WEnd

а вот как переделать это под список - чтоб чекбоксов появлялось столько, сколько записей.

И ещё наверное, либо есть способ чтоб выделялся только один чекбокс, либо надо будет переделать под radiobutton.

Заранее благодарен за любую помощь.

Creat0R 31-05-2007 19:20 593506

_Flame_
Цитата:

Мне надо, чтобы открывался txt файл, который лежит в папке \Files
Открывался в редакторе по умолчанию? тогда так:

Код:

$FilePath = "Files\textfile.txt"
ShellExecute($FilePath)

DenchikK
Цитата:

как переделать это под список - чтоб чекбоксов появлялось столько, сколько записей.
Примерно так - это отдельный набросок для создания чекбоксов в зависимости от числа записей, которые предварительно нужно поместить в массив (см. функцию _FileReadToArray() ) :

Код:

;---это в начало файла---
#include <File.au3>
;------------------------

; Построение GUI
GUICreate("Автозаполнение", 330, 300)

Global $Links_Array
_FileReadToArray("links.txt", $Links_Array)

If IsArray($Links_Array) Then
    $Top = 10
    For $i = 1 To $Links_Array[0]
        GUICtrlCreateCheckbox($Links_Array[$i], 10, $Top, 180, 20)
        $Top += 20
    Next
EndIf

$Start = GUICtrlCreateButton("Заполнить", 200, 10, 120, 20)
$Close = GUICtrlCreateButton("Выход", 200, 30, 120, 20)

GUISetState()

Если записей (каждая запись это отдельная строка в файле) больше чем чекбоксы помещаются в ГУИ, то также как я проделал с переменной $Top, нужно проделать и с левым выравниванием чекбоксов ($Left = 10 и потом прибавлять в цикле, скажем по 80).

DenchikK 01-06-2007 01:47 593663

Creat0R
Спасибо большое! Построение GUI идет как надо, но вот только теперь я не понимаю, как обрабатывать эти чекбоксы... Не понимаю, как это:

Код:

If GUICtrlRead($checkCN1) = 1 Then
                    WinActivate ("AvaRemoteLoad")
            ControlSetText ( 'AvaRemoteLoad', '', 'Edit1', $Links_Array[1] )
                    ControlSetText ( 'AvaRemoteLoad', '', 'Edit2', $Logins_Array[1])
                    ControlSetText ( 'AvaRemoteLoad', '', 'Edit3', $Pass_Array[1])
        EndIf

заставить работать с построением GUI...

Тупо заделал так, но теряется возможность определять, сколько чекбоксов надо сделать для содержимого файла логов:

Код:

#include <GUIConstants.au3>
#include <File.au3>

If WinExists(@ScriptName) Then Exit
AutoItWinSetTitle(@ScriptName)
AutoItSetOption("TrayIconDebug", 1)
AutoItSetOption("SendKeyDelay", 60)
AutoItSetOption("MouseCoordMode", 0)

; Запуск программы

Run ('avaload.exe')

; Построение GUI

GUICreate("Автозаполнение", 330, 300)

Global $Links_Array, $Logins_Array, $Pass_Array

_FileReadToArray("logins.txt", $Logins_Array)
_FileReadToArray("pass.txt", $Pass_Array)
_FileReadToArray("links.txt", $Links_Array)

$checkCN1 = GUICtrlCreateCheckbox ($Logins_Array[1], 10, 10, 180, 20)
$checkCN2 = GUICtrlCreateCheckbox ($Logins_Array[2], 10, 30, 180, 20)
$checkCN3 = GUICtrlCreateCheckbox ($Logins_Array[3], 10, 50, 180, 20)
$checkCN4 = GUICtrlCreateCheckbox ($Logins_Array[4], 10, 70, 180, 20)
$checkCN5 = GUICtrlCreateCheckbox ($Logins_Array[5], 10, 90, 180, 20)
$checkCN6 = GUICtrlCreateCheckbox ($Logins_Array[6], 10, 110, 180, 20)
$checkCN7 = GUICtrlCreateCheckbox ($Logins_Array[7], 10, 130, 180, 20)
$checkCN8 = GUICtrlCreateCheckbox ($Logins_Array[8], 10, 150, 180, 20)
$checkCN9 = GUICtrlCreateCheckbox ($Logins_Array[9], 10, 170, 180, 20)
$checkCN10 = GUICtrlCreateCheckbox ($Logins_Array[9], 10, 190, 180, 20)

$Start = GUICtrlCreateButton("Заполнить", 200, 10, 120, 20)
$Close = GUICtrlCreateButton("Выход", 200, 30, 120, 20)

GUISetState ()

; Основная Работа Скрипта

While 1
$msg = GUIGetMsg()
If $msg = $GUI_EVENT_CLOSE  Or $msg = $Close Then
        Exit

ElseIf $msg = $Start Then

 If GUICtrlRead($checkCN1) = 1 Then
                    WinActivate ("AvaRemoteLoad")
                ControlSetText ( 'AvaRemoteLoad', '', 'Edit1', $Links_Array[1])
                    ControlSetText ( 'AvaRemoteLoad', '', 'Edit2', $Logins_Array[1])
                    ControlSetText ( 'AvaRemoteLoad', '', 'Edit3', $Pass_Array[1])
        EndIf

        If GUICtrlRead($checkCN2) = 1 Then
                    WinActivate ("AvaRemoteLoad")
                ControlSetText ( 'AvaRemoteLoad', '', 'Edit1', $Links_Array[2])
                    ControlSetText ( 'AvaRemoteLoad', '', 'Edit2', $Logins_Array[2])
                    ControlSetText ( 'AvaRemoteLoad', '', 'Edit3', $Pass_Array[2])
        EndIf

        If GUICtrlRead($checkCN3) = 1 Then
                    WinActivate ("AvaRemoteLoad")
                ControlSetText ( 'AvaRemoteLoad', '', 'Edit1', $Links_Array[3])
                    ControlSetText ( 'AvaRemoteLoad', '', 'Edit2', $Logins_Array[3])
                    ControlSetText ( 'AvaRemoteLoad', '', 'Edit3', $Pass_Array[3])
        EndIf

        If GUICtrlRead($checkCN4) = 1 Then
                    WinActivate ("AvaRemoteLoad")
                ControlSetText ( 'AvaRemoteLoad', '', 'Edit1', $Links_Array[4])
                    ControlSetText ( 'AvaRemoteLoad', '', 'Edit2', $Logins_Array[4])
                    ControlSetText ( 'AvaRemoteLoad', '', 'Edit3', $Pass_Array[4])
        EndIf

        If GUICtrlRead($checkCN5) = 1 Then
                    WinActivate ("AvaRemoteLoad")
                ControlSetText ( 'AvaRemoteLoad', '', 'Edit1', $Links_Array[5])
                    ControlSetText ( 'AvaRemoteLoad', '', 'Edit2', $Logins_Array[5])
                    ControlSetText ( 'AvaRemoteLoad', '', 'Edit3', $Pass_Array[5])
        EndIf

        If GUICtrlRead($checkCN6) = 1 Then
                    WinActivate ("AvaRemoteLoad")
                ControlSetText ( 'AvaRemoteLoad', '', 'Edit1', $Links_Array[5])
                    ControlSetText ( 'AvaRemoteLoad', '', 'Edit2', $Logins_Array[5])
                    ControlSetText ( 'AvaRemoteLoad', '', 'Edit3', $Pass_Array[5])
        EndIf

        If GUICtrlRead($checkCN7) = 1 Then
                    WinActivate ("AvaRemoteLoad")
                ControlSetText ( 'AvaRemoteLoad', '', 'Edit1', $Links_Array[7])
                    ControlSetText ( 'AvaRemoteLoad', '', 'Edit2', $Logins_Array[7])
                    ControlSetText ( 'AvaRemoteLoad', '', 'Edit3', $Pass_Array[7])
        EndIf

        If GUICtrlRead($checkCN8) = 1 Then
                    WinActivate ("AvaRemoteLoad")
                ControlSetText ( 'AvaRemoteLoad', '', 'Edit1', $Links_Array[8])
                    ControlSetText ( 'AvaRemoteLoad', '', 'Edit2', $Logins_Array[8])
                    ControlSetText ( 'AvaRemoteLoad', '', 'Edit3', $Pass_Array[8])
        EndIf

        If GUICtrlRead($checkCN9) = 1 Then
                    WinActivate ("AvaRemoteLoad")
                ControlSetText ( 'AvaRemoteLoad', '', 'Edit1', $Links_Array[9])
                    ControlSetText ( 'AvaRemoteLoad', '', 'Edit2', $Logins_Array[9])
                    ControlSetText ( 'AvaRemoteLoad', '', 'Edit3', $Pass_Array[9])
        EndIf

        If GUICtrlRead($checkCN10) = 1 Then
                    WinActivate ("AvaRemoteLoad")
                ControlSetText ( 'AvaRemoteLoad', '', 'Edit1', $Links_Array[10])
                    ControlSetText ( 'AvaRemoteLoad', '', 'Edit2', $Logins_Array[10])
                    ControlSetText ( 'AvaRemoteLoad', '', 'Edit3', $Pass_Array[10])
        EndIf


EndIf
WEnd

Попробовал по изощряться для компактности с $i - не вышло...

Creat0R 01-06-2007 03:45 593677

DenchikK
Цитата:

как обрабатывать эти чекбоксы
По идее можно создавать динамический массив который будет содержать в себе все управляющие идентификаторы (ControlID) от созданных чекбоксов, и отслеживать каждый раз нужный проверяя элементы массива..

Лучше (надёжнее) проверять все чекбоксы, а нужный текст брать из самого названия чекбокса, ведь каждый зажатый чекбокс (который мы и будем проверять), имеет то название, которое и требуется для записи...

Я бы если честно предложил использовать события (Events), правда придётся немного переделать структуру всего GUI (не сильно :) ), для этого в начале скрипта нужно установить опции для срабатывания событии - Opt("GuiOnEventMode", 1), и потом всем (нужным для обработки) контролам присваивать функцию которая будет срабатывать на событие, так в дальнейшем легче обрабатывать элементы (имхо):

Код:

#include <GUIConstants.au3>
#include <File.au3>

If WinExists(@ScriptName) Then Exit
AutoItWinSetTitle(@ScriptName)
Opt("TrayIconDebug", 1)
Opt("SendKeyDelay", 60)
Opt("MouseCoordMode", 0)
Opt("GuiOnEventMode", 1)

Global $Array_logins, $Array_pass, $Array_links, $CheckBoxIDArray[1]

; Чтение Файла С Логинами
_FileReadToArray("logins.txt", $Array_logins)
If @error Then
    MsgBox(0, "Error", "Unable to open file.")
    Exit
EndIf

; Чтение Файла С Паролями
_FileReadToArray("pass.txt", $Array_pass)
If @error Then
    MsgBox(0, "Error", "Unable to open file.")
    Exit
EndIf

; Чтение Файла С Линками
_FileReadToArray("links.txt", $Array_links)
If @error Then
    MsgBox(0, "Error", "Unable to open file.")
    Exit
EndIf

; Запуск программы

Run ('avaload.exe')

; Построение GUI

GUICreate("Автозаполнение", 330, 300)
GUISetOnEvent(-3, "Quit")

$Top = 10
$Left = 10

;Чекбоксы для логинов
If IsArray($Array_logins) Then
    For $i = 1 To $Array_logins[0]
        ReDim $CheckBoxIDArray[UBound($CheckBoxIDArray)+1]
        $CheckBoxIDArray[UBound($CheckBoxIDArray)-1] = GUICtrlCreateCheckbox($Array_logins[$i], $Left, $Top, 180, 20)
        $Top += 20

                If $Top >= 200 Then
            $Top = 10
            $Left += 90
        EndIf
    Next
EndIf

;Чекбоксы для паролей
If IsArray($Array_pass) Then
    For $i = 1 To $Array_pass[0]
        ReDim $CheckBoxIDArray[UBound($CheckBoxIDArray)+1]
        $CheckBoxIDArray[UBound($CheckBoxIDArray)-1] = GUICtrlCreateCheckbox($Array_pass[$i], $Left, $Top, 180, 20)
        $Top += 20
        If $Top >= 160 Then
            $Top = 10
            $Left += 90
        EndIf
    Next
EndIf

;Чекбоксы для линков
If IsArray($Array_links) Then
    For $i = 1 To $Array_links[0]
        ReDim $CheckBoxIDArray[UBound($CheckBoxIDArray)+1]
        $CheckBoxIDArray[UBound($CheckBoxIDArray)-1] = GUICtrlCreateCheckbox($Array_links[$i], $Left, $Top, 180, 20)
        $Top += 20
        If $Top >= 160 Then
            $Top = 10
            $Left += 90
        EndIf
    Next
EndIf

$Start = GUICtrlCreateButton("Заполнить", 200, 10, 120, 20)
GUICtrlSetOnEvent($Start, "Start")

$Close = GUICtrlCreateButton("Выход", 200, 30, 120, 20)
GUICtrlSetOnEvent($Close, "Quit")

GUISetState()

While 1
    Sleep(10)
WEnd

; Основная Работа Скрипта - функция для обработки чекбоксов
Func Start()
    For $i = 1 To UBound($CheckBoxIDArray)-1
        If GUICtrlRead($CheckBoxIDArray[$i]) = 1 Then
            WinActivate("AvaRemoteLoad")
            $CurrentText = GUICtrlRead($CheckBoxIDArray[$i], 1)
            ControlSetText('AvaRemoteLoad', '', 'Edit1', $CurrentText)
            ControlSetText('AvaRemoteLoad', '', 'Edit2', $CurrentText)
            ControlSetText('AvaRemoteLoad', '', 'Edit3', $CurrentText)
        EndIf
    Next
EndFunc

Func Quit()
    Exit
EndFunc

P.S
Кстати, (кажется в последних версиях AutoIt) не обязательно активировать окно для ControlSetText() ;).

DenchikK 01-06-2007 04:31 593683

Creat0R
Ещё раз огромное спасибо!
Но я что то пока так и не смог разобраться, как же всё это работает...

Эти строки я убрал, так они не нужны и мешают (идея какая - если выбран 3 логин, то выбираются вместе с ним 3 пасс и 3 линк):

Код:

;Чекбоксы для паролей

If IsArray($Array_pass) Then
    For $i = 1 To $Array_pass[0]
        ReDim $CheckBoxIDArray[UBound($CheckBoxIDArray)+1]
        $CheckBoxIDArray[UBound($CheckBoxIDArray)-1] = GUICtrlCreateCheckbox($Array_pass[$i], $Left, $Top, 180, 20)
        $Top += 20
        If $Top >= 160 Then
            $Top = 10
            $Left += 90
        EndIf
    Next
EndIf

;Чекбоксы для линков
If IsArray($Array_links) Then
    For $i = 1 To $Array_links[0]
        ReDim $CheckBoxIDArray[UBound($CheckBoxIDArray)+1]
        $CheckBoxIDArray[UBound($CheckBoxIDArray)-1] = GUICtrlCreateCheckbox($Array_links[$i], $Left, $Top, 180, 20)
        $Top += 20
        If $Top >= 160 Then
            $Top = 10
            $Left += 90
        EndIf
    Next
EndIf

и видать из за этого результат этого один и тот же для всех полей:
Код:

; Основная Работа Скрипта - функция для обработки чекбоксов
Func Start()
    For $i = 1 To UBound($CheckBoxIDArray)-1
        If GUICtrlRead($CheckBoxIDArray[$i]) = 1 Then
            WinActivate("AvaRemoteLoad")
            $CurrentText = GUICtrlRead($CheckBoxIDArray[$i], 1)
            ControlSetText('AvaRemoteLoad', '', 'Edit1', $CurrentText)
            ControlSetText('AvaRemoteLoad', '', 'Edit2', $CurrentText)
            ControlSetText('AvaRemoteLoad', '', 'Edit3', $CurrentText)
        EndIf
    Next
EndFunc

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

И скорее всего придётся отказаться от чекбоксов в пользу радиобуттонов, но структура case мне пока не даётся...

amel27 01-06-2007 04:58 593685

voler
Код:

WinWait ( 'Adobe Acrobat 7.0 Professional - Setup', 'Сюда вставить тект окна, отличающий его от остальных')
ControlClick ( 'Adobe Acrobat 7.0 Professional - Setup', 'Сюда тот же текст, что и в предыдущей функции', 'Button1' )

Текст окна можно посмотреть в штатной "AutoIt Window Info".

Creat0R 01-06-2007 05:30 593687

DenchikK
Цитата:

идея какая - если выбран 3 логин, то выбираются вместе с ним 3 пасс и 3 линк
Я если честно теперь ещё больше запутался в отношении самой идеи...

Если можешь, поясни пошагово (не программно, а как бы со стороны юзера) - Что должно произойти, какие чекбоксы будут созданы (их структура и цель назначения), что должно происходить при зажатом чекбоксе (после нажатия кнопки Start) и т.д.

А я попробую построить соответственно гуи и описать процесс... должно быть не сложно, но цель немного смутновата - когда есть чётко поставленная цель, остальное это время, и усидчивость! (+ немного знании ;)).

ChVL 01-06-2007 10:34 593782

В одной папке находятся скрипт .au3 и .exe исходного приложения. При запуске скрипта всё устанавливается правильно, до самого конца.
Через контекстное меню компилирую. При этом скомпилированный .exe "съедает" исходный .exe и имеет иконку такую же, как и скрипт. При запуске скомпилированного .exe ничего не происходит.
AutoIt версия 3.2.4.9.
Что делаю не так?

amel27 01-06-2007 10:43 593786

ChVL
Цитата:

скомпилированный .exe "съедает" исходный .exe и имеет иконку такую же, как и скрипт.
так ты выбери для скрипта другое имя, к примеру: Setup.exe - приложение, Setup_AU.au3 - скрипт, тогда никакого наложения имен при компиляции не будет

ChVL 01-06-2007 11:04 593800

amel27
Цитата:

выбери для скрипта другое имя
Действительно, всё работает! Спасибо!
Странно, что нигде ни в одном мануале о необходимости переименования скрипта нет ни слова. Это же не очевидно. Ну, съедает... А может так и надо?

V0van3 01-06-2007 12:36 593840

уважаемый amel27
к сожалению в данном случае не всё так просто. видимо вы не проверяли.
я добавил сразу после запуска Visicom
MsgBox(4096, "otladka", $pid) и оказалось что Visicom.exe имеет Pid=0 т.е. не отлавливает
т.к. Visicom запускается как дочерний процесс NTVDM.exe, последний продолжает оставаться в памяти при закрытии Visiciom то PID NTVDM'а как условие не годится.
В случае например с Notepad.exe или ещё с каким-нибуть другим приложением, которое висит в памяти как самостоятельный процесс проблем нет.
Естессно ваш код более правильный т.к. позволяет отловить именно тот процесс который запустил скрипт (если есть другой процесс с таким же именем), но в данном случае не в этом проблема.

DenchikK 01-06-2007 13:09 593862

Creat0R
Суть работы скрипта такова:
Заливка файлов по списку ссылок в аккаунты, доступ к которым задается логином и паролем.
То есть со стороны юзеа это выглядит так: он подготоавливает список ссылок на файлы, которые хочет скачать, и список пустых аккаунтов, в которые эти ссылки будут помещены. 1 линк = 1 аккаунт. При запуске скрипта юзер выбирает, в какой именно аккаунт будет заливаться любой по списку файл по линку (radibutton подходит лучше, но я что то до сих пор с опреатором case из примера не разобрался):
http://img154.imageshack.us/img154/3923/1autowa8.jpg

И вот когда выбран нужный аккаунт, поле самой программы заполняется:
http://img154.imageshack.us/img154/8333/2autoyc1.jpg

В поле линк - идет ссылка, тут наверное даже не принципиально её положение в файле, пускай будет самая первая в списке (ещё б сделать в этом случае её удаление из списка, после заполнения поля)
В поле Логин - тот Логин, что выбран, в поле Пароль - соответствующий ему пароль . Например 6 логин сверху соответствует 6 сверху паролю (то же былоб интереснее, чтоб после заполнения они бы стирались).

Вообщем как то так...

Спасибо Вам что Вы со мною возитесь! :-)

voler 01-06-2007 14:55 593904

Проблема, при отработке скрипта. Ставлю прогу , кто может объясните почему нажатие кнопок не срабатывает. В предыдущем посте мне объяснили в чем проблема. Но не помогает.

HTML код:

#cs
----------------------

----------------------
#ce
;предотвращение возможности множественного запуска скрипта
If WinExists(@ScriptName) Then Exit
AutoItWinSetTitle(@ScriptName)
;Отображать текущую строку сценария с помощью индикатора системной панели в режиме отладки.
AutoItSetOption("TrayIconDebug", 1)

; Установка переменных
Global $file='hddinsp.exe', $ACStr

Run ( $file )

WinWaitActive ( 'Installer Language', 'Please select a language.' )
ControlClick ( 'Installer Language', 'Please select a language.', 'Button1' )

WinWaitActive ( 'Установка Hard Drive Inspector Professional', 'Мастер установки Hard Drive Inspector Professional' )
ControlClick ( 'Установка Hard Drive Inspector Professional', 'Мастер установки Hard Drive Inspector Professional', 'Button2' )

WinWaitActive ( 'Установка Hard Drive Inspector Professional', 'Лицензионное соглашение' )
ControlClick ( 'Установка Hard Drive Inspector Professional', 'Лицензионное соглашение', 'Button4' )

WinWaitActive ( 'Установка Hard Drive Inspector Professional', 'Лицензионное соглашение' )
ControlClick ( 'Установка Hard Drive Inspector Professional', 'Лицензионное соглашение', 'Button2' )

WinWaitActive ( 'Установка Hard Drive Inspector Professional', 'Выбор папки установки' )
ControlClick ( 'Установка Hard Drive Inspector Professional', 'Выбор папки установки', 'Button2' )

WinWaitActive ( 'Установка Hard Drive Inspector Professional', 'Папка в меню "Пуск"' )
ControlClick ( 'Установка Hard Drive Inspector Professional', 'Папка в меню "Пуск"', 'Button2' )

WinWaitActive ( 'Установка Hard Drive Inspector Professional', 'Установка завершена' )
ControlClick ( 'Установка Hard Drive Inspector Professional', 'Установка завершена', 'Button2' )

WinWaitActive ( 'Установка Hard Drive Inspector Professional', 'Завершение работы мастера установки' )
ControlClick ( 'Установка Hard Drive Inspector Professional', 'Завершение работы мастера установки', 'Button4' )

WinWaitActive ( 'Установка Hard Drive Inspector Professional', 'Завершение работы мастера установки' )
ControlClick ( 'Установка Hard Drive Inspector Professional', 'Завершение работы мастера установки', 'Button2' )

exit


ChVL 01-06-2007 15:28 593916

Сразу недосмотрел. Скомпилированный exe работает, но только тогда, когда рядом присутствует исходный exe, т.е. ничем не отличается от работы со скриптом au3. Самостоятельно НЕ запускается - сразу же требует исходный exe. Декомпилировал его с помощью Exe2Aut и увидел, что в него один к одному переписан скрипт и больше ничего нет, хотя объём около 200 KB.
Интересный момент: видимое содержимое декомпилированного exe с одинаковыми именами (который вообще не запускается) абсолютно аналогично описанному выше (это просто текст скрипта), и объёмы у них одинаковы.
Где ещё копать?

Diamond 01-06-2007 19:29 594037

voler
Цитата:

Ставлю прогу , кто может объясните почему нажатие кнопок не срабатывает.
Проверил несколько кнопок - работает, но только тогда, когда окно активно...
Я бы заменил WinWaitActive на WinWait(), поскольку ControlClick() умеет работать даже с неактивными окнами, и вполне достаточно просто дождаться появления окна.

Creat0R 02-06-2007 03:19 594198

DenchikK
Попробую переформулировать (для проверки, правильно ли я понял):

Запускаем скрипт, создаются столько чекбоксов, сколько есть записей в файле линков (и только для этих записей создаём чекбоксы)...

а точнее (как я понял), создаём radio button ;)

Далее после нажатия на Старт, в каждое поле вписывается соответственно - Ссылка, логин, и пароль.

Вот только есть одна проблема - какое должно быть название у чекбоксов? можно совместить что то вроде этого:

Login_pass_link (как у тебя на скрине)... и потом разделять это на три значения, для того чтобы выявить нужные данные для записи в прогу.

Такой вопрос:
А списки обязательно держать в трёх разных файлах? может можно записывать в один ini файл (к примеру AvaRemote.ini), чтобы имя секции ровнялось ссылке, а под секцией записи пароля и логина, что то типа такого:

Код:

[http://mail.ru]
loging1=DenchikK
pass1=12345

login2=DenchikK
pass2=54321

и т.д

Так будет намного эргономичнее и удобнее обрабатывать данные.

Работать с Radio button совсем не сложно, почти также как и с обычными чекбоксами, разница только в том что может быть выбран один пункт в определённой группе (при наличии таковой).

Вот пример:

Код:

GUICreate("test")

$Radio1 = GUICtrlCreateRadio("Radio1", 10, 40)

$Radio2 = GUICtrlCreateRadio("Radio2", 10, 70)

$Radio3 = GUICtrlCreateRadio("Radio3", 10, 100)

$ShowSelectedButton = GUICtrlCreateButton("Show checked button", 150, 200)

GUISetState()

While 1
    Switch GUIGetMsg()
        Case -3
            Exit
        Case $ShowSelectedButton
            Select
                Case GUICtrlRead($Radio1) = 1
                    MsgBox(0, "", "This radio button checked: " & GUICtrlRead($Radio1, 1))
                Case GUICtrlRead($Radio2) = 1
                    MsgBox(0, "", "This radio button checked: " & GUICtrlRead($Radio2, 1))
                Case GUICtrlRead($Radio3) = 1
                    MsgBox(0, "", "This radio button checked: " & GUICtrlRead($Radio3, 1))
            EndSelect
    EndSwitch
WEnd


ChVL
Цитата:

Скомпилированный exe работает, но только тогда, когда рядом присутствует исходный exe
Это напряму зависит от того, какой состав скрипта, возможно в скрипте используются данные читаемые при выполнении из самого скрипта :) - чтобы сказать более точно, необходимо видеть исходный код.

DenchikK 02-06-2007 12:02 594243

Creat0R
Цитата:

Запускаем скрипт, создаются столько чекбоксов, сколько есть записей в файле линков (и только для этих записей создаём чекбоксы)...
Почти так - только не линков, а логинов. :-)

Цитата:

Вот только есть одна проблема - какое должно быть название у чекбоксов?
Названия - как у логинов.

Цитата:

А списки обязательно держать в трёх разных файлах? может можно записывать в один ini файл (к примеру AvaRemote.ini)
Это было б вообще прекрасно! Я и не знал о такой возможности!

Цитата:

Работать с Radio button совсем не сложно, почти также как и с обычными чекбоксами
Спасибочки! Сейчас буду пробовать работать с Radio Button

Добавлено ещё раз :-)
C radiobutton кое как разобрался. С ini файлом вроде то же (спасибо огромное за подсказку его использовать! так стало гораздо удобнее ). Вот немного уменьшил скрипт, как смог:
Код:

#include <GUIConstants.au3>
#include <File.au3>

If WinExists(@ScriptName) Then Exit
AutoItWinSetTitle(@ScriptName)
AutoItSetOption("TrayIconDebug", 1)
AutoItSetOption("SendKeyDelay", 60)
AutoItSetOption("MouseCoordMode", 0)

Global $i, $file, $group_1, $group_2, $group_3, $Links_Array, $Logins_Array, $Pass_Array, $Servers_Array, $Secrets_Array

; Запуск программы

Run ('avaload.exe')

; Считывание Данных

$Logins_Array = IniReadSection("ava.ini", "logins")
$Pass_Array = IniReadSection("ava.ini", "pass")
$Links_Array = IniReadSection("ava.ini", "links")
$Servers_Array = IniReadSection("ava.ini", "servers")
$Secrets_Array = IniReadSection("ava.ini", "secrets")

; Построение GUI

GUICreate("Автозаполнение", 340, 350)

;If IsArray($Links_Array) Then
;    $Top = 20
;    For $i = 1 To Logins_Array[0][0]
;    GUICtrlCreateRadio($Logins_Array[$i][1], 10, $Top)
;    $Top += 20
;    Next
;EndIf

$Radio1 = GUICtrlCreateRadio($Logins_Array[1][1], 10, 20)
$Radio2 = GUICtrlCreateRadio($Logins_Array[2][1], 10, 40)
$Radio3 = GUICtrlCreateRadio($Logins_Array[3][1], 10, 60)
$Radio4 = GUICtrlCreateRadio($Logins_Array[4][1], 10, 80)
$Radio5 = GUICtrlCreateRadio($Logins_Array[5][1], 10, 100)
$Radio6 = GUICtrlCreateRadio($Logins_Array[6][1], 10, 120)
$Radio7 = GUICtrlCreateRadio($Logins_Array[7][1], 10, 140)
$Radio8 = GUICtrlCreateRadio($Logins_Array[8][1], 10, 160)
$Radio9 = GUICtrlCreateRadio($Logins_Array[9][1], 10, 180)
$Radio10 = GUICtrlCreateRadio($Logins_Array[10][1], 10, 200)
$Radio11 = GUICtrlCreateRadio($Logins_Array[11][1], 10, 220)
$Radio12 = GUICtrlCreateRadio($Logins_Array[12][1], 10, 240)
$Radio13 = GUICtrlCreateRadio($Logins_Array[13][1], 10, 260)
$Radio14 = GUICtrlCreateRadio($Logins_Array[14][1], 10, 280)
$Radio15 = GUICtrlCreateRadio($Logins_Array[15][1], 10, 300)
$Radio16 = GUICtrlCreateRadio($Logins_Array[16][1], 10, 320)

$Start = GUICtrlCreateButton("Заполнить", 210, 20, 120, 20)
$Close = GUICtrlCreateButton("Выход", 210, 40, 120, 20)
$Server1  = GUICtrlCreateButton("Сервер 1", 210, 60, 120, 20)
$Server2  = GUICtrlCreateButton("Сервер 2", 210, 80, 120, 20)

$group_1 = GUICtrlCreateGroup ("Выбор Аккаунта", 5, 5, 190, 340)
$group_2 = GUICtrlCreateGroup ("Кнопочки", 205, 5, 130, 100)
$group_3 = GUICtrlCreateGroup ("Описание", 205, 105, 130, 240)

$Label1 = GUICtrlCreateLabel("    Описание Работы", 210, 120)
$Label2 = GUICtrlCreateLabel("1. Впишите в ava.ini", 210, 140)
$Label3 = GUICtrlCreateLabel("линки,логины,пароли,", 210, 155)
$Label4 = GUICtrlCreateLabel("параметры серверов.", 210, 170)
$Label5 = GUICtrlCreateLabel("2. Выберите Сервер", 210, 185)
$Label6 = GUICtrlCreateLabel("3. Выберите пустой ", 210, 200)
$Label7 = GUICtrlCreateLabel("аккаунт для заливки. ", 210, 215)
$Label8 = GUICtrlCreateLabel("    Принцип работы: ", 210, 235)
$Label9 = GUICtrlCreateLabel("Например, выбираем", 210, 250)
$Label10 = GUICtrlCreateLabel("первый логин,в него", 210, 265)
$Label11 = GUICtrlCreateLabel("будет заливаться ", 210, 280)
$Label12 = GUICtrlCreateLabel("первый линк. и.т.д", 210, 295)
$Label13 = GUICtrlCreateLabel("            Удачи! ", 210, 315)

GUISetState ()

; Основная Работа Скрипта

GUISetState()  ; display the GUI

While 1
    Switch GUIGetMsg()
        Case -3
            Exit
 
        Case $Close
            Exit

        Case $Server1

                WinActivate ("AvaRemoteLoad")
                ControlClick ( 'AvaRemoteLoad', '', "Button4")

                WinWaitActive ('Настройки')
                ControlSetText ( 'Настройки', '', 'Edit1', $Servers_Array[1][1])
                ControlSetText ( 'Настройки', '', 'Edit2', $Secrets_Array[1][1])

                ControlClick ( 'Настройки', '', "Button2")

        Case $Server2
                WinActivate ("AvaRemoteLoad")
                ControlClick ( 'AvaRemoteLoad', '', "Button4")

                WinWaitActive ('Настройки')
                ControlSetText ( 'Настройки', '', 'Edit1', $Servers_Array[2][1])
                ControlSetText ( 'Настройки', '', 'Edit2', $Secrets_Array[2][1])

                ControlClick ( 'Настройки', '', "Button2")

        Case $Start

        Select

        Case GUICtrlRead($Radio1) = 1
                $i = 1
        Case GUICtrlRead($Radio2) = 1
                $i = 2
        Case GUICtrlRead($Radio3) = 1
                $i = 3
        Case GUICtrlRead($Radio4) = 1
                $i = 4
        Case GUICtrlRead($Radio5) = 1
                $i = 5
        Case GUICtrlRead($Radio6) = 1
                $i = 6
        Case GUICtrlRead($Radio7) = 1
                $i = 7
        Case GUICtrlRead($Radio8) = 1
                $i = 8
        Case GUICtrlRead($Radio9) = 1
                $i = 9
        Case GUICtrlRead($Radio10) = 1
                $i = 10
        Case GUICtrlRead($Radio11) = 1
                $i = 11
        Case GUICtrlRead($Radio12) = 1
                $i = 12
        Case GUICtrlRead($Radio13) = 1
                $i = 13
        Case GUICtrlRead($Radio14) = 1
                $i = 14
        Case GUICtrlRead($Radio15) = 1
                $i = 15
        Case GUICtrlRead($Radio16) = 1
                $i = 16
            EndSelect

                    WinActivate ("AvaRemoteLoad")
            ControlSetText ( 'AvaRemoteLoad', '', 'Edit1', $Links_Array[$i][1])
                    ControlSetText ( 'AvaRemoteLoad', '', 'Edit2', $Logins_Array[$i][1])
                    ControlSetText ( 'AvaRemoteLoad', '', 'Edit3', $Pass_Array[$i][1])

EndSwitch
WEnd

И вот тут у меня появляется такая затыка:

Для последующей обработки выбора radiobutton
Код:

Case GUICtrlRead($Radio1) = 1
                $i = 1

пытался впихнуть строчку
Код:

If IsArray($Logins_Array) Then
    $Top = 20
    For $i = 1 To Logins_Array[0][0]
    GUICtrlCreateRadio($Logins_Array[$i][1], 10, $Top)
  $Radio[$i] = GUICtrlCreateRadio($Logins_Array[$i][1], 10, $Top)
    $Top += 20
    Next
EndIf

но не получилось, вываливается ошибка. Как сопоставить теперь автоматическое рисование нужного количества радиобутаннов и их работу - ума не приложу...

amel27 03-06-2007 05:20 594446

Diamond
Цитата:

Я бы заменил WinWaitActive на WinWait()
+1
Почему-то был уверен, что поставил WinWait(), уже исправил...

V0van3
Цитата:

к сожалению в данном случае не всё так просто. видимо вы не проверяли
+1 :)
конечно не проверял, нынче найти 16-битное приложение не так просто... вот навскидку два варианта:

Простой и надежный способ ценой лишнего CMD-процесса:
Код:

$exe = 'Vcmurbas.exe' ; Имя 16-битного приложения
$dir = 'C:\Program Files\Vcmurbas' ; Путь к каталогу программы
$pid = Run(@COMSPEC & ' /C START /WAIT /SEPARATE ' & $exe, $dir, @SW_HIDE)

While ProcessExists($pid)
  Sleep(200)
WEnd

Более "навороченный", но без дополнительных процессов:
Код:

$exe = 'Vcmurbas.exe' ; Имя 16-битного приложения
$dir = 'C:\Program Files\Vcmurbas' ; Путь к каталогу программы

$PDL = ProcessList ('ntvdm.exe')
Run (@COMSPEC & ' /C START /SEPARATE ' & $exe, $dir, @SW_HIDE)
$PID = _ProcessListWait($PDL, 'ntvdm.exe')

While ProcessExists($pid)
  Sleep(200)
WEnd

; Функция, которая сравнивает списки процессов до появления различий
; и возвращает PID нового процесса.
Func _ProcessListWait (ByRef $arrPLOld, $strPName = '')
    Local $i, $arrPLNew, $strPLOld='', $newPID=0
    For $i=1 To $arrPLOld[0][0]
        $strPLOld &= $arrPLOld[$i][1] &';'
    Next
    Do
        Sleep (100)
        If @NUMPARAMS=1 Then $arrPLNew = ProcessList()
        If @NUMPARAMS=2 Then $arrPLNew = ProcessList($strPName)
        For $i=1 To $arrPLNew[0][0]
            If StringInStr($strPLOld, $arrPLNew[$i][1]&';')=0 Then $newPID=$arrPLNew[$i][1]
        Next
    Until $newPID
    Return $newPID
EndFunc

З.Ы. Во 2-м случае можно обойтись без @COMSPEC если настроить систему на запуск каждого 16-битного приложения в отдельном NTVDM-процессе: ключ реестра HKLM\SYSTEM\CurrentControlSet\Control\WOW, параметр DefaultSeparateVDM = "yes"

ChVL 03-06-2007 19:55 594610

Creat0R
Цитата:

Цитата:

Скомпилированный exe работает, но только тогда, когда рядом присутствует исходный exe
Это напряму зависит от того, какой состав скрипта, возможно в скрипте используются данные читаемые при выполнении из самого скрипта - чтобы сказать более точно, необходимо видеть исходный код.
Использовал разные au3, в том числе и от Sanja Alone. Во всех случаях скомпилированный exe имеет объём чуть больше 200 КВ, не зависит от объёма исходного exe и от того, какая прога устанавливается.

Diamond 03-06-2007 22:15 594662

amel27
Цитата:

Почему-то был уверен, что поставил WinWait(), уже исправил...
А я был уверен что идея принадлежит voler ... :blush:
Это и не ошибка вовсе, а всего лишь другой способ. :sorry:

amel27 04-06-2007 02:37 594702

Diamond
Цитата:

Это и не ошибка вовсе, а всего лишь другой способ
ИМХО при автоматизации установки имеют смысл только два варианта:

- WinWait()+ControlClick()/ControlCommand()
- WinWait()+WinActivate()+Send().

Creat0R 04-06-2007 02:48 594704

DenchikK
Цитата:

в соответствии с ini файлом, как я понял, переделал так:
Не совсем верно, дело в том, что функция IniReadSection() возвращяет двумерный массив, нулевой элемент ([0]), как и в других обычных массивах, содержит общее число элементов массива.
Построение цикла, должно быть так:

Код:

For $i = 1 To NN

Next

Тут For $i = 1, означает что для переменной $i, в теле цикла, будет присваиваться возрастающее значение от 1 и до NN (вместо NN нам и нужно подставить общее число элементов нашего массива, в данном случае, это $Logins_Array[0][0], иногда, обычно самодельные массивы, могут быть построены неверно, поэтому надёжнее проверять общее число массива, используя функцию Ubound, но при этом нужно отнять 1, чтобы нулевой элемент не учитывался:

Код:

For $i = 1 To Ubound($Logins_Array) - 1
   
Next

Или используем нулевой элемент для выявления общего числа элементов массива (не самый надёжный метод):

Код:

For $i = 1 To $Logins_Array[0][0]
   
Next

В справке написано, что функция IniReadSection(), возвращает двумерный массив, теперь его элементы присваиваются так:

Logins_Array[N][0] = Ключь в Ini-Файле
Logins_Array[N][1] = Значение этого же ключа (ключ это то что идёт перед знаком ровно в Ini-файле).

Цитата:

пытался впихнуть строчку
Тут тоже ошибка, ведь в начале идёт проверка переменной, является ли она массивом - If IsArray($Links_Array) Then...

Но в теле условия (If ... Then ... EndIf), массив обрабатывается совсем другой...

GUICtrlCreateRadio($Logins_Array[$i][1], 10, $Top)...

Вот отсюда и может быть вызвана ошибка.


Попытка №2 :) :

(Добавил также немного проверок на ошибочность).

Код:

#include <GUIConstants.au3>

If WinExists(@ScriptName) Then Exit
AutoItWinSetTitle(@ScriptName)
AutoItSetOption("TrayIconDebug", 1)
AutoItSetOption("SendKeyDelay", 60)
AutoItSetOption("MouseCoordMode", 0)

Global $group_1, $group_2, $group_3, $RadioArr[1], $Links_Array, $Logins_Array, $Pass_Array, $Servers_Array, $Secrets_Array

; Запуск программы

Run ('avaload.exe')

; Считывание Данных

$Logins_Array = IniReadSection("ava.ini", "logins")
$Pass_Array = IniReadSection("ava.ini", "pass")
$Links_Array = IniReadSection("ava.ini", "links")
$Servers_Array = IniReadSection("ava.ini", "servers")
$Secrets_Array = IniReadSection("ava.ini", "secrets")

; Построение GUI

GUICreate("Автозаполнение", 340, 350)

If IsArray($Logins_Array) Then
        ReDim $RadioArr[UBound($Logins_Array)]
        $Top = 20
    For $i = 1 To UBound($Logins_Array)-1
                $RadioArr[$i] = GUICtrlCreateRadio($Logins_Array[$i][1], 10, $Top)
                $Top += 20
    Next
EndIf

$Start = GUICtrlCreateButton("Заполнить", 210, 20, 120, 20)
$Close = GUICtrlCreateButton("Выход", 210, 40, 120, 20)
$Server1  = GUICtrlCreateButton("Сервер 1", 210, 60, 120, 20)
$Server2  = GUICtrlCreateButton("Сервер 2", 210, 80, 120, 20)

$group_1 = GUICtrlCreateGroup ("Выбор Аккаунта", 5, 5, 190, 340)
$group_2 = GUICtrlCreateGroup ("Кнопочки", 205, 5, 130, 100)
$group_3 = GUICtrlCreateGroup ("Описание", 205, 105, 130, 240)

$Label1 = GUICtrlCreateLabel("    Описание Работы", 210, 120)
$Label2 = GUICtrlCreateLabel("1. Впишите в ava.ini", 210, 140)
$Label3 = GUICtrlCreateLabel("линки,логины,пароли,", 210, 155)
$Label4 = GUICtrlCreateLabel("параметры серверов.", 210, 170)
$Label5 = GUICtrlCreateLabel("2. Выберите Сервер", 210, 185)
$Label6 = GUICtrlCreateLabel("3. Выберите пустой ", 210, 200)
$Label7 = GUICtrlCreateLabel("аккаунт для заливки. ", 210, 215)
$Label8 = GUICtrlCreateLabel("    Принцип работы: ", 210, 235)
$Label9 = GUICtrlCreateLabel("Например, выбираем", 210, 250)
$Label10 = GUICtrlCreateLabel("первый логин,в него", 210, 265)
$Label11 = GUICtrlCreateLabel("будет заливаться ", 210, 280)
$Label12 = GUICtrlCreateLabel("первый линк. и.т.д", 210, 295)
$Label13 = GUICtrlCreateLabel("            Удачи! ", 210, 315)

GUISetState ()

; Основная Работа Скрипта

GUISetState()  ; display the GUI

While 1
    Switch GUIGetMsg()
        Case -3, $Close
            Exit
                Case $Server1
                       
                        If UBound($Servers_Array) < 2 Or UBound($Secrets_Array) < 2 Then
                                MsgBox(48, "Ошибка", "Извените, невозможно продолжить, видимо не были найдены данные серверов")
                                ContinueLoop
                        EndIf
                       
                        WinActivate ("AvaRemoteLoad")
                        ControlClick ( 'AvaRemoteLoad', '', "Button4")

                        WinWaitActive ('Настройки')
                        ControlSetText ( 'Настройки', '', 'Edit1', $Servers_Array[1][1])
                        ControlSetText ( 'Настройки', '', 'Edit2', $Secrets_Array[1][1])

                        ControlClick ( 'Настройки', '', "Button2")

                Case $Server2
                       
                        If UBound($Servers_Array) < 3 Or UBound($Secrets_Array) < 3 Then
                                MsgBox(48, "Ошибка", "Извените, невозможно продолжить, видимо не были найдены данные серверов")
                                ContinueLoop
                        EndIf
                       
                        WinActivate ("AvaRemoteLoad")
                        ControlClick ( 'AvaRemoteLoad', '', "Button4")

                        WinWaitActive ('Настройки')
                        ControlSetText ( 'Настройки', '', 'Edit1', $Servers_Array[2][1])
                        ControlSetText ( 'Настройки', '', 'Edit2', $Secrets_Array[2][1])

                        ControlClick ( 'Настройки', '', "Button2")

                Case $Start
                       
                        Local $iSet = 0
                        For $i = 1 To UBound($Logins_Array)-1
                                If GUICtrlRead($RadioArr[$i]) = 1 Then
                                        $iSet = $i
                                        ExitLoop
                                EndIf
                        Next
                       
                        If $iSet = 0 Then
                                MsgBox(48, "Ошибка", "Выберите пожалуйста один из логинов")
                                ContinueLoop
                        EndIf
                       
                        If $iSet > UBound($Links_Array)-1 Or $iSet > UBound($Logins_Array)-1 Or $iSet > UBound($Pass_Array)-1 Then
                                MsgBox(48, "Ошибка", "Извените, невозможно продолжить, видимо не были найдены данные линков/логинов/паролей")
                                ContinueLoop
                        EndIf
                       
                        WinActivate ("AvaRemoteLoad")
                        ControlSetText ( 'AvaRemoteLoad', '', 'Edit1', $Links_Array[$iSet][1])
                        ControlSetText ( 'AvaRemoteLoad', '', 'Edit2', $Logins_Array[$iSet][1])
                        ControlSetText ( 'AvaRemoteLoad', '', 'Edit3', $Pass_Array[$iSet][1])

        EndSwitch
WEnd

ChVL
Цитата:

Во всех случаях скомпилированный exe имеет объём чуть больше 200 КВ, не зависит от объёма исходного exe и от того, какая прога устанавливается.
Не вижу связи с поставленной проблемой...

Цитата:

Скомпилированный exe работает, но только тогда, когда рядом присутствует исходный exe
:idontnow:

...И с тем что я написал :)

ChVL 04-06-2007 05:27 594715

Creat0R
Ещё конкретнее.
Беру autoit-winamp.au3 (7.43 KB) от Sanja Alone и winamp533_pro.exe (6.33 MB). Компилирую. Теперь autoit-winamp.exe имеет объём 205 КВ. Это правильно? Этот autoit-winamp.exe работает только тогда, когда рядом находится winamp533_pro.exe.

Creat0R 04-06-2007 06:01 594716

ChVL
Цитата:

Этот autoit-winamp.exe работает только тогда, когда рядом находится winamp533_pro.exe.
Значит в самом скрипте путь к winamp533_pro.exe указан тот же в котором находится сам скрипт, либо вовсе не указан (в таком случае, путь обычно проверяется в соответствии с рабочим каталогом).

Но я всё же не понимаю связи с этим:

Цитата:

Скомпилированный exe работает, но только тогда, когда рядом присутствует исходный exe
Либо тут неправильная подстановка термина “исходный exe”, либо я чего то недопонимаю... в моём понимании “исходный exe”, это не скомпилированный скрипт :) - именно на основе этого понимания я и ответил:

Цитата:

Это напряму зависит от того, какой состав скрипта, возможно в скрипте используются данные читаемые при выполнении из самого скрипта - чтобы сказать более точно, необходимо видеть исходный код.
А в чём собственно проблема?

amel27 04-06-2007 06:33 594717

Creat0R
Цитата:

Или используем нулевой элемент для выявления общего числа элементов массива (не самый надёжный метод):
Хм... Почему "ненадежный"?.. Не вижу смысла подсчитывать количество элементов если это уже сделала за нас функция... двойная работа получается. Откуда такое недоверие к разработчикам? ;)

Creat0R 04-06-2007 06:43 594718

amel27
Цитата:

Откуда такое недоверие к разработчикам?
Я это на всякий случай пишу, потому что лучше перестраховаться, при наличии больших скриптов, можно “не вспомнить” кто создавал массив, встроенная функция, или построенный нами цикл (или просто “рукописный массив”) :)

Я вовсе не утверждал что нужно не доверять встроенным функциям, я им очень даже доверяю (но проверяю ;) ), ведь если бы не доверял, то и небыло бы для меня повода использовать ту же встроенную функцию Ubound() ;)

VelDmi 04-06-2007 06:44 594719

ChVL
Цитата:

Теперь autoit-winamp.exe имеет объём 205 КВ. Это правильно?
Да, правильно.
Цитата:

Этот autoit-winamp.exe работает только тогда, когда рядом находится winamp533_pro.exe.
Естественно, ведь он запускает winamp533_pro.exe, а затем производит над его окном определенные действия. Если же ты хотел, чтобы получился всего один файл, то прочитай справку по fileinstall (). Тогда winamp533_pro.exe будет помещен внутрь скрипта и получится один exe большого размера.

DenchikK 04-06-2007 13:01 594847

Creat0R
Огромное Вам спасибо! Буду разбираться.

ChVL 04-06-2007 17:04 594952

VelDmi
Спасибо!
C помощью FileInstall поместил дистрибутив в скомпилированный скрипт (по размеру скрипта всё сходится). Как теперь сделать так, чтобы скрипт при запуске использовал именно этот exe, а не требовал его снаружи?

Второй вопрос. Как сделать так, чтобы не мелькали окна приложения в процессе установки?

Creat0R 04-06-2007 18:49 595003

ChVL
Цитата:

Как теперь сделать так, чтобы скрипт при запуске использовал именно этот exe, а не требовал его снаружи?
FileInstall() позволяет помещать файлы в скомпилированный скрипт, чтобы потом они распаковывались в указанное место, вот перед всеми основными действиями скрипта, нужно прописать установку нужного файла, можно распаковывать с любым указанным именем, в данном случае, можно взять имя самого скрипта, и прибавить к нему приставку _Setup:

Код:

$WinampPath = StringTrimRight(@ScriptFullPath, 4) & "_Setup.exe"
FileInstall("winamp533_pro.exe", $WinampPath, 1)
Run($WinampPath)

Цитата:

Как сделать так, чтобы не мелькали окна приложения в процессе установки?
Либо запустить приложение в скрытом режиме ( Run($WinampPath, "", @SW_HIDE) ), либо прятать окна в процессе (см. WinSetState("Title", "Text", @SW_HIDE) )

ChVL 04-06-2007 21:07 595061

Creat0R
Спасибо!
C FileInstall() разобрался, работает. Не сразу, правда, понял, что AutoIt принципиально не переваривает кириллицу в директории (безуспешно пытался использовать Рабочий стол).

Со скрытым режимом не получается.
Запуск ( Run($WinampPath, "", @SW_HIDE) ) на окна, выскакивающие в процессе установки, не влияет (не скрывает).
Функция WinSetState оказалась несовместимой с WinWaitActive. Если WinSetState ставить перед WinWaitActive, то последняя не работает. Если после - нет смысла, т.к. окно уже промелькнуло.
Эти варианты пробовал и раньше, а другие не нашёл.

Creat0R 04-06-2007 21:43 595072

ChVL
Цитата:

AutoIt принципиально не переваривает кириллицу в директории
Ну почему, в случае с FileInstall очень даже переваривает, возможно неверно указаны параметры функции? первый параметр не должен содержать переменных и/или макросов, только чистый текст.

Цитата:

Функция WinSetState оказалась несовместимой с WinWaitActive
Если нам нужно скрыть окна, то WinWaitActive ни к чему, окно никогда не будет активным :) - но вот WinWait может помочь, оно позволит ожидать окно, т.е ожидать его появление, а не активность...

Код:

WinWait("Title", "", 5)
WinSetState("Title", "", @SW_HIDE)


Creat0R 06-06-2007 02:40 595723

Функции (и пример использования) для отображения стильного диалога “О Программе”

Код:

#include <GUIConstants.au3>

$Title = "About Info"

$MainLabel = "My program Name"
$CopyRLabel = "Copyright © " & @YEAR & " Company/Author. All rights reserved."

$NameURL1 = "App Web Page"
$URL1 = "http://www.autoitscript.com"
$NameURL2 = "Email"
$URL2 = "mailto:my_email@mail.com"
$NameURL3 = "Some additional link"
$URL3 = "http://personalwebpafe.com"
$LinkColor = 0x0000FF
$BkColor = 0xFFFFFF

$ParentGui = GUICreate('Parent For "About Program" Demo')

$Menu = GUICtrlCreateMenu("Help")
$AboutItem = GUICtrlCreateMenuitem("About...", $Menu)

GUISetState()

While 1
        Switch GUIGetMsg()
                Case -3
                        Exit
                Case $AboutItem
                        _About($Title, $MainLabel, $CopyRLabel, "v1.0", $NameURL1, $URL1, $NameURL2, $URL2, $NameURL3, $URL3, @AutoItExe, $LinkColor, $BkColor, -1, -1, -1, -1, $ParentGui)
        EndSwitch
WEnd


Func _About($Title, $MainLabel, $CopyRLabel, $VerLabel, $NameURL1, $URL1, $NameURL2, $URL2, $NameURL3, $URL3, $IconFile="", $LinkColor=0x0000FF, $BkColor=0xFFFFFF, $Left=-1, $Top=-1, $Style=-1, $ExStyle=-1, $Parent=0)
        Local $OldEventOpt = Opt("GUIOnEventMode", 0)
        Local $OldRunErrOpt = Opt("RunErrorsFatal", 0)
        Local $GUI, $LinkTop=120, $Msg, $CurInfo
        Local $CurIsOnCtrlArr[1]
       
        Local $LinkVisitedColor[4] = [3, $LinkColor, $LinkColor, $LinkColor]
        Local $LinkLabel[4]
       
        WinSetState($Parent, "", @SW_DISABLE)
       
        If $ExStyle = -1 Then $ExStyle = ""
        $GUI = GUICreate($Title, 320, 240, $Left, $Top, $Style, 0x00000080+$ExStyle, $Parent)
        GUISetBkColor($BkColor)

        GUICtrlCreateLabel($MainLabel, 40, 20, 280, 25, 1)
        GUICtrlSetFont(-1, 16)

        GUICtrlCreateIcon($IconFile, 0, 10, 20)

        GUICtrlCreateGraphic(5, 75, 310, 3, $SS_ETCHEDFRAME)
       
        For $i = 1 To 3
                $LinkLabel[$i] = GUICtrlCreateLabel(Eval("NameURL" & $i), 150, $LinkTop, 145, 15, 1)
                GUICtrlSetCursor(-1, 0)
                GUICtrlSetColor(-1, $LinkColor)
                GUICtrlSetFont(-1, 9, 400, 0)
                GUICtrlSetTip(-1, Eval("URL" & $i))
                $LinkTop += 30
        Next

        GUICtrlCreateLabel("Program version: " & @LF & $VerLabel, 10, 130, 150, 35, 1)
        GUICtrlSetFont(-1, 10, 600, 0, "Tahoma")
       
        GUICtrlCreateLabel($CopyRLabel, 0, 220, 320, -1, 1)

        GUISetState(@SW_SHOW, $GUI)

        While 1
                $Msg = GUIGetMsg()
                If $Msg = -3 Then ExitLoop
                For $i = 1 To 3
                        If $Msg = $LinkLabel[$i] Then
                                While 1
                                        GUISetCursor(0, 1, $GUI)
                                        If GUIGetMsg() = $GUI_EVENT_PRIMARYUP Then
                                                $CurInfo = GUIGetCursorInfo($GUI)
                                                If $CurInfo[4] = $LinkLabel[$i] Then
                                                        GUISetCursor(-1, 0, $GUI)
                                                        $LinkVisitedColor[$i] = 0xAC00A9
                                                        GUICtrlSetColor($LinkLabel[$i], $LinkVisitedColor[$i])
                                                        ShellExecute(Eval("URL" & $i))
                                                EndIf
                                                ExitLoop
                                        EndIf
                                WEnd
                                GUISetCursor(-1, 0, $GUI)
                        EndIf
                Next
                If WinActive($GUI) Then
                        For $i = 1 To 3
                                ControlHover($GUI, $LinkLabel[$i], $i, $CurIsOnCtrlArr, 0xFF0000, $LinkVisitedColor[$i])
                        Next
                EndIf
        WEnd
        WinSetState($Parent, "", @SW_ENABLE)
        GUIDelete($GUI)
        Opt("GUIOnEventMode", $OldEventOpt)
        Opt("RunErrorsFatal", $OldRunErrOpt)
EndFunc

Func ControlHover($hWnd, $CtrlID, $CtrlNum, ByRef $CurIsOnCtrlArr, $HoverColor=0xFF0000, $LinkColor=0x0000FF)
        Local $CursorCtrl = GUIGetCursorInfo($hWnd)
        ReDim $CurIsOnCtrlArr[UBound($CurIsOnCtrlArr)+1]
        If $CursorCtrl[4] = $CtrlID And $CurIsOnCtrlArr[$CtrlNum] = 1 Then
                GUICtrlSetFont($CtrlID, 9, 400, 6)
                GUICtrlSetColor($CtrlID, $HoverColor)
                $CurIsOnCtrlArr[$CtrlNum] = 0
        ElseIf $CursorCtrl[4] <> $CtrlID And $CurIsOnCtrlArr[$CtrlNum] = 0 Then
                GUICtrlSetFont($CtrlID, 9, 400, 0)
                GUICtrlSetColor($CtrlID, $LinkColor)
                $CurIsOnCtrlArr[$CtrlNum] = 1
        EndIf
EndFunc


Diamond 06-06-2007 18:52 596068

Пример Gui-оболочки для консольных конверторов
У меня накопилось с десяток консольных программ типа: архиваторы, конверторы звуковых и графических файлов и т.п. и я подумал, что неплохо было бы для них написать Gui.
Цели, которые я поставил при написании:
1. Список для добавляемых файлов должен быть ListView, при чем с поддержкой перетаскивания файлов (Drag&Drop)
2. Каждый новый Файл должен добавляться в конец списка, а как следствие - сортировка ListView запрещена.
3. В списке не должно быть дубликатов файловых путей.

Это только стартовый интерфейс, но надеюсь он кому-то сэкономит время в написании подобных программ. :)
Код:

#include <GUIConstants.au3>
#include <GuiListView.au3>
Opt("GUIOnEventMode",1)
Opt("TrayIconHide",1)
Global Const $WM_DROPFILES = 0x233
Global $StringCount=0
Global $Dict=ObjCreate("Scripting.Dictionary") ; <- Словарь
$hGUI=GUICreate("Конвертор ;)",600,500,-1,-1,-1,$WS_EX_ACCEPTFILES)
        GUISetOnEvent($GUI_EVENT_CLOSE,"Quit")
$listview=GUICtrlCreateListView  ("Файл|Путь",5,5,590,450,BitOR($LVS_NOSORTHEADER,$LVS_SHOWSELALWAYS))
$ButtonDelete=GUICtrlCreateButton("Удалить",250,465,80,24)
        GUICtrlSetOnEvent(-1,"StrDelete")
$ButtonAdd=GUICtrlCreateButton("Добавить",120,465,80,24)
        GUICtrlSetOnEvent(-1,"AddOpenFiles")
GUISetState(@SW_SHOWNORMAL)

;~ Регистрируем событие Drag&Drop
GUIRegisterMsg ($WM_DROPFILES, "DropFiles")

While 1
        Sleep(1000)
WEnd

;~ Выход из приложения
Func Quit()
        Exit(0)
EndFunc

;~ Этот функция была взята с официального форума или... точно не помню ;)
;~ Создаёт массив $gaDropFiles, из файлов полученный при перетаскивании
;~ Вызывается событием, прописанным в GUIRegisterMsg()
Func DropFiles($hWnd, $msgID, $wParam, $lParam)
    Local $nSize, $pFileName, $gaDropFiles[1]
    Local $nAmt = DllCall("shell32.dll", "int", "DragQueryFile", "hwnd", $wParam, "int", 0xFFFFFFFF, "ptr", 0, "int", 255)
    For $i = 0 To $nAmt[0] - 1
        $nSize = DllCall("shell32.dll", "int", "DragQueryFile", "hwnd", $wParam, "int", $i, "ptr", 0, "int", 0)
        $nSize = $nSize[0] + 1
        $pFileName = DllStructCreate("char[" & $nSize & "]")
        DllCall("shell32.dll", "int", "DragQueryFile", "hwnd", $wParam, "int", $i, "ptr", DllStructGetPtr($pFileName), "int", $nSize)
        ReDim $gaDropFiles[$i+1]
        $gaDropFiles[$i] = DllStructGetData($pFileName, 1)
        $pFileName = 0
    Next
        Call ("AddDropedFiles", $gaDropFiles)
EndFunc

;~ Добавляет в ListViev файлы, полученные с помощью перетаскивания (Drag&Drop)
;~ Является продолжением функции DropFiles()
Func AddDropedFiles($gaDropFiles)
        Call ("DictionaryAdd")
        Local $Count=$StringCount
        For $o In $gaDropFiles
                If Not $Dict.Exists($o) Then
                        _GUICtrlListViewInsertItem($listview, $Count, GetFileName($o) & '|' & $o)
                        Call ("AutoSize")
                        $Count=$Count+1
                EndIf
        Next
        $Dict.RemoveAll
EndFunc

;~ Добавляет файлы в ListViev с помощью FileOpenDialog()
;~ Вызывается кнопкой
Func AddOpenFiles()
        $FilePath = FileOpenDialog("Открыть","","Wave файлы (*.wav) | Все файлы (*.*)",4+1)
        If @error <> 1 Then
                Local $array = StringSplit($FilePath, "|")
                Local $Count = $StringCount
                If $array[0]>1 Then
                        $path=$array[1]
                        Call ("DictionaryAdd")
                        For $i=2 To $array[0]
                                $FullPath=$path & "\" & $array[$i]
                                If Not $Dict.Exists($FullPath) Then
                                        _GUICtrlListViewInsertItem($listview, $Count, $array[$i] & '|' & $FullPath)
                                        Call ("AutoSize")
                                        $Count=$Count+1
                                EndIf
                        Next
                ElseIf $array[0]=1 Then
                        Call ("DictionaryAdd")
                        If Not $Dict.Exists($array[1]) Then
                                _GUICtrlListViewInsertItem($listview, $StringCount, GetFileName($array[1]) & '|' & $array[1])
                                Call ("AutoSize")
                        Endif
                EndIf
                $Dict.RemoveAll
        EndIf
EndFunc

;~ Удаляет выбранные элементы в ListViev
;~ Вызывается кнопкой
Func StrDelete()
        _GUICtrlListViewDeleteItemsSelected($listview)
        If _GUICtrlListViewGetItemCount($listview) Then AutoSize()
EndFunc

;~ ========================
;~ Вспомогательные функции:
;~ ========================

; Возвращает имя файла или папки из пути
;~ Вызывается некоторыми функциями
Func GetFileName($FilePath)
        If StringRight($FilePath,1)="\" Then
                $FilePath=StringTrimRight($FilePath,1)
        EndIf
        Return StringTrimLeft($FilePath,StringInStr($FilePath,"\",0,-1))
EndFunc

;~ Изменяет размеры колонок в ListViev
;~ Вызывается некоторыми функциями
Func AutoSize()
_GUICtrlListViewSetColumnWidth($listview,1,$LVSCW_AUTOSIZE)
_GUICtrlListViewSetColumnWidth($listview,0,$LVSCW_AUTOSIZE)
EndFunc

;~ Добавляет в словарь все элементы второй колонки ListViev (Пути к файлам)
;~ З.Ы. Поиск дубликатов по словарю, значительно быстрее чем перебор-сравнение в массиве!
Func DictionaryAdd()
        $StringCount=_GUICtrlListViewGetItemCount($listview)
        For $i=0 To $StringCount
                $Item = _GUICtrlListViewGetItemTextArray ($listview, $i)
                If IsArray($Item) Then
                        $Dict.Add($Item[2],"")
                EndIf
        Next
EndFunc

;~ ---------------------------------------------
;~ Позволят получить файловое расширение из пути или имени файла.
;~ Это единственная функция которая нигде не используется!
Func FileGetExtension($name)
        Local $Count=StringInStr($name,".",0,-1)
        If $Count=0 Then
                Return 0
        Else
                Return StringTrimLeft($name,$Count)
        EndIf
EndFunc


Creat0R 06-06-2007 22:17 596143

Diamond
Цитата:

Этот функция была взята с официального форума или... точно не помню ;)
Да да, иименно от туда, я и сам ей пользуюсь с удовольствием :), взял тоже именно с оф. форума (её наисал кажется gafrost).

У меня почему то при вызове $dict.Exists скрипт выпадает с ошибкой:

Цитата:

The requested action with this object has failed.
Вобщем я немного изменил скрипт, надеюсь что в лучшую сторону, изменения таковы:

-Функцию _FileOpenDialog() добавил самдельную (от amel27) - позволяет открыть диалог для выбора файла как дочерний диалог ГУИ.

-Добавил функцию для поиска в самом ListView, имхо, так надёжнее, и не так уж намного медленнее ;)

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

-Теперь при добавлении файлов используя перетаскивание, существующие в списке файлы будут подсвечиваться (выделяться) - так думаю более удобно :).

-Функцию GetFileName() немного укоротил ;)

-Добавил отображение иконок для добавляемых файлов, иконки определяются используя функцию _FileGetIcon() (тоже где то на оф. форуме нашел, правда немного изменил).

-Чтобы можно было присваивать иконки айтемам, пришлось вместо вставки айтемов, создавать их встроенными средствами, т.к требуется ControlID.

Вот что получилось:

Код:

#include <GUIConstants.au3>
#include <GuiListView.au3>
Opt("GUIOnEventMode",1)
Opt("TrayIconHide",1)
Global Const $WM_DROPFILES = 0x233
Global $StringCount=0
Global $Dict=ObjCreate("Scripting.Dictionary") ; <- Словарь
$hGUI=GUICreate("Конвертор ;)",600,500,-1,-1,-1,$WS_EX_ACCEPTFILES)
        GUISetOnEvent($GUI_EVENT_CLOSE,"Quit")
$listview=GUICtrlCreateListView  ("Файл|Путь",5,5,590,450,BitOR($LVS_NOSORTHEADER,$LVS_SHOWSELALWAYS))
$ButtonDelete=GUICtrlCreateButton("Удалить",250,465,80,24)
        GUICtrlSetOnEvent(-1,"StrDelete")
$ButtonAdd=GUICtrlCreateButton("Добавить",120,465,80,24)
        GUICtrlSetOnEvent(-1,"AddOpenFiles")
GUISetState(@SW_SHOWNORMAL)

;~ Регистрируем событие Drag&Drop
GUIRegisterMsg ($WM_DROPFILES, "DropFiles")

While 1
        Sleep(1000)
WEnd

;~ Выход из приложения
Func Quit()
        Exit(0)
EndFunc

;~ Этот функция была взята с официального форума или... точно не помню ;)
;~ Создаёт массив $gaDropFiles, из файлов полученный при перетаскивании
;~ Вызывается событием, прописанным в GUIRegisterMsg()
Func DropFiles($hWnd, $msgID, $wParam, $lParam)
    Local $nSize, $pFileName, $gaDropFiles[1]
    Local $nAmt = DllCall("shell32.dll", "int", "DragQueryFile", "hwnd", $wParam, "int", 0xFFFFFFFF, "ptr", 0, "int", 255)
    For $i = 0 To $nAmt[0] - 1
        $nSize = DllCall("shell32.dll", "int", "DragQueryFile", "hwnd", $wParam, "int", $i, "ptr", 0, "int", 0)
        $nSize = $nSize[0] + 1
        $pFileName = DllStructCreate("char[" & $nSize & "]")
        DllCall("shell32.dll", "int", "DragQueryFile", "hwnd", $wParam, "int", $i, "ptr", DllStructGetPtr($pFileName), "int", $nSize)
        ReDim $gaDropFiles[$i+1]
        $gaDropFiles[$i] = DllStructGetData($pFileName, 1)
        $pFileName = 0
    Next
        Call ("AddDropedFiles", $gaDropFiles)
EndFunc

;~ Добавляет в ListViev файлы, полученные с помощью перетаскивания (Drag&Drop)
;~ Является продолжением функции DropFiles()
Func AddDropedFiles($gaDropFiles)
        Local $SelCount = 1, $LVIID, $IconFile, $IconID
        For $o In $gaDropFiles
                $FindPathInLV = _FindInListView($listview, 1, $o)
                If $FindPathInLV = -1 Then
                        $LVIID = GUICtrlCreateListViewItem(GetFileName($o) & '|' & $o, $listview)
                        _FileGetIcon($IconFile, $IconID, $o)
                        GUICtrlSetImage($LVIID, $IconFile, $IconID)
                Else
                        If $SelCount = 1 Then ControlListView($hGUI, "", $listview, "SelectClear")
                        _GUICtrlListViewSetItemSelState($listview, $FindPathInLV)
                        $SelCount = -1
                EndIf
        Next
        If $SelCount = -1 Then ControlFocus($hGUI, "", $listview)
        Call ("AutoSize")
EndFunc

;~ Добавляет файлы в ListViev с помощью FileOpenDialog()
;~ Вызывается кнопкой
Func AddOpenFiles()
        $FilePath = _FileOpenDialog("Открыть","","Wave файлы (*.wav) | Все файлы (*.*)",4+1, "", "", $hGUI)
        If Not @error Then
                $FilePath = StringStripCR($FilePath)
                Local $array = StringSplit($FilePath, "|")
                Local $LVIID, $IconFile, $IconID
                If $array[0]>1 Then
                        $path=$array[1]
                        For $i=2 To $array[0]
                                $FullPath=$path & "\" & $array[$i]
                                If _FindInListView($ListView, 1, $FullPath) = -1 Then
                                        $LVIID = GUICtrlCreateListViewItem($array[$i] & '|' & $FullPath, $listview)
                                        _FileGetIcon($IconFile, $IconID, $FullPath)
                                        GUICtrlSetImage($LVIID, $IconFile, $IconID)
                                EndIf
                        Next
                ElseIf $array[0]=1 Then
                        If _FindInListView($ListView, 1, $array[1]) = -1 Then
                                $LVIID = GUICtrlCreateListViewItem(GetFileName($array[1]) & '|' & $array[1], $listview)
                                _FileGetIcon($IconFile, $IconID, $array[1])
                                GUICtrlSetImage($LVIID, $IconFile, $IconID)
                        EndIf
                EndIf
                Call ("AutoSize")
        EndIf
EndFunc

;~ Удаляет выбранные элементы в ListViev
;~ Вызывается кнопкой
Func StrDelete()
        _GUICtrlListViewDeleteItemsSelected($listview)
        If _GUICtrlListViewGetItemCount($listview) Then AutoSize()
EndFunc

;~ ========================
;~ Вспомогательные функции:
;~ ========================

; Возвращает имя файла или папки из пути
;~ Вызывается некоторыми функциями
Func GetFileName($FilePath)
        Return StringRegExpReplace($FilePath, "^.*\\", "")
EndFunc

;~ Изменяет размеры колонок в ListViev
;~ Вызывается некоторыми функциями
Func AutoSize()
_GUICtrlListViewSetColumnWidth($listview,1,$LVSCW_AUTOSIZE)
_GUICtrlListViewSetColumnWidth($listview,0,$LVSCW_AUTOSIZE)
EndFunc

;~ Добавляет в словарь все элементы второй колонки ListViev (Пути к файлам)
;~ З.Ы. Поиск дубликатов по словарю, значительно быстрее чем перебор-сравнение в массиве!
Func DictionaryAdd()
        $StringCount=_GUICtrlListViewGetItemCount($listview)
        For $i=0 To $StringCount
                $Item = _GUICtrlListViewGetItemTextArray ($listview, $i)
                If IsArray($Item) Then
                        $Dict.Add($Item[2],"")
                EndIf
        Next
EndFunc

;~ Функция производит поиск в списке List View, в случае удачи, возвращает индекс найденного айтема в списке,
;в противном случае возвращает -1
Func _FindInListView($ListViewID, $SubItem, $WhatToFind, $SubItem2=-1, $WhatToFind2="")
        Local $TotalItemsArr = _GUICtrlListViewGetItemCount($ListViewID)
        Local $CurrentText, $CurrentText2
        If $TotalItemsArr > 0 Then
                For $i = 0 To $TotalItemsArr - 1
                        $CurrentText = _GUICtrlListViewGetItemText($ListViewID, $i, $SubItem)
                        If $SubItem2 <> -1 Then
                                $CurrentText2 = _GUICtrlListViewGetItemText($ListViewID, $i, $SubItem2)
                                If $CurrentText = $WhatToFind And $CurrentText2 = $WhatToFind2 Then Return $i
                        Else
                                If $CurrentText = $WhatToFind Then Return $i
                        EndIf
                Next
        EndIf
        Return -1
EndFunc

;~ Самодельная функци FileOpenDialog() - позволяет открыть диалог для выбора файла как дочерний диалог ГУИ.
Func _FileOpenDialog($sTitle, $sInitDir, $sFilter = 'All (*.*)', $iOpt = 0, $sDefaultFile = "", $sDefaultExt = "", $mainGUI = 0)
    Local $iFileLen = 65536 ; Max chars in returned string
    ; API flags prepare
    Local $iFlag = BitOR ( _
        BitShift (BitAND ($iOpt, 1),-12), BitShift (BitAND ($iOpt, 2),-10), BitShift (BitAND ($iOpt, 4),-7 ), _
        BitShift (BitAND ($iOpt, 8),-10), BitShift (BitAND ($iOpt, 4),-17) )
    ; Filter string to array convertion
    Local $asFLines = StringSplit ( $sFilter, '|'), $asFilter [$asFLines [0] *2+1]
    Local $i, $iStart, $iFinal, $suFilter = ''
    $asFilter [0] = $asFLines [0] *2
    For $i=1 To $asFLines [0]
        $iStart = StringInStr ($asFLines [$i], '(', 0, 1)
        $iFinal = StringInStr ($asFLines [$i], ')', 0,-1)
        $asFilter [$i*2-1] = StringStripWS (StringLeft ($asFLines [$i], $iStart-1), 3)
        $asFilter [$i*2] = StringStripWS (StringTrimRight (StringTrimLeft ($asFLines [$i], $iStart), StringLen ($asFLines [$i]) -$iFinal+1), 3)
        $suFilter = $suFilter & 'byte[' & StringLen ($asFilter [$i*2-1])+1 & '];byte[' & StringLen ($asFilter [$i*2])+1 & '];'
    Next
    ; Create API structures
    Local $uOFN = DllStructCreate ('dword;int;int;ptr;ptr;dword;dword;ptr;dword' & _
        ';ptr;int;ptr;ptr;dword;short;short;ptr;ptr;ptr;ptr;ptr;dword;dword' )
    Local $usTitle  = DllStructCreate ('byte[' & StringLen ($sTitle) +1 & ']')
    Local $usInitDir= DllStructCreate ('byte[' & StringLen ($sInitDir) +1 & ']')
    Local $usFilter = DllStructCreate ($suFilter & 'byte')
    Local $usFile  = DllStructCreate ('byte[' & $iFileLen & ']')
    Local $usExtn  = DllStructCreate ('byte[' & StringLen ($sDefaultExt) +1 & ']')
    For $i=1 To $asFilter [0]
        DllStructSetData ($usFilter, $i, $asFilter [$i])
    Next
    ; Set Data of API structures
    DllStructSetData ($usTitle, 1, $sTitle)
    DllStructSetData ($usInitDir, 1, $sInitDir)
    DllStructSetData ($usFile, 1, $sDefaultFile)
    DllStructSetData ($usExtn, 1, $sDefaultExt)
    DllStructSetData ($uOFN,  1, DllStructGetSize($uOFN))
    DllStructSetData ($uOFN,  2, $mainGUI)
    DllStructSetData ($uOFN,  4, DllStructGetPtr ($usFilter))
    DllStructSetData ($uOFN,  7, 1)
    DllStructSetData ($uOFN,  8, DllStructGetPtr ($usFile))
    DllStructSetData ($uOFN,  9, $iFileLen)
    DllStructSetData ($uOFN, 12, DllStructGetPtr ($usInitDir))
    DllStructSetData ($uOFN, 13, DllStructGetPtr ($usTitle))
    DllStructSetData ($uOFN, 14, $iFlag)
    DllStructSetData ($uOFN, 17, DllStructGetPtr ($usExtn))
    DllStructSetData ($uOFN, 23, BitShift (BitAND ($iOpt, 32), 5))
    ; Call API function
    $ret = DllCall ('comdlg32.dll', 'int', 'GetOpenFileName', _
            'ptr', DllStructGetPtr ($uOFN) )
    If $ret [0] Then
        If BitAND ($iOpt, 4) Then
            $i = 1
            While 1
                If DllStructGetData ($usFile, 1, $i) =0 Then
                    If DllStructGetData ($usFile, 1, $i+1) Then
                        DllStructSetData ($usFile, 1, 124, $i)
                    Else
                        ExitLoop
                    EndIf
                EndIf
                $i += 1
            Wend
        EndIf
        Return DllStructGetData ($usFile, 1)
    Else
        SetError (1)
        Return ""
    EndIf
EndFunc

;~ Функция задаёт значения для переменных $szIconFile и $nIcon путь к файлу и идентификатор иконки в файле
; (для определения иконки по заданному пути к файлу).
Func _FileGetIcon(ByRef $szIconFile, ByRef $nIcon, $szFile)
        Local $OldEES = Opt("ExpandEnvStrings", 1)
        Local $szRegDefault = "", $szDefIcon = "", $szExt
        $nIcon = 0
        If _IsDir($szFile) Then
                $szRegDefault = RegRead("HKCR\Folder", "")
                If $szRegDefault <> "" Then $szDefIcon = RegRead("HKCR\Folder\DefaultIcon", "")
        Else
                $szExt = StringRegExpReplace($szFile, '^.*\.', '.')
                If $szExt = $szFile Then
                        $szExt = FileFindFirstFile($szFile & ".*")
                        $szExt = StringRegExpReplace(FileFindNextFile($szExt), '^.*\.', '.')
                        $szFile = $szFile & $szExt
                EndIf
                $szRegDefault = RegRead("HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\" & $szExt, "ProgID")
                If $szRegDefault = "" Then $szRegDefault = RegRead("HKCR\" & $szExt, "")
                If $szRegDefault <> "" Then $szDefIcon = RegRead("HKCR\" & $szRegDefault & "\DefaultIcon", "")
        EndIf
        If $szDefIcon = "" Then
                $szIconFile = "shell32.dll"
        ElseIf $szDefIcon <> "%1" Then
                If StringRegExpReplace($szFile, "^.*\\", "") = "shell32.dll" Then
                        $szIconFile = $szFile
                        $nIcon = 0
                Else
                        $arSplit = StringSplit($szDefIcon, ",")
                        If IsArray($arSplit) Then
                                $szIconFile = $arSplit[1]
                                If $arSplit[0] > 1 Then $nIcon = $arSplit[2]
                        Else
                                Opt("ExpandEnvStrings", $OldEES)
                                Return 0
                        EndIf
                EndIf
        ElseIf $szDefIcon = "%1" Then
                $szIconFile = $szFile
                $nIcon = 0
        EndIf
        Opt("ExpandEnvStrings", $OldEES)
        Return 1
EndFunc

;~ Функция предназначена для проверки, является ли заданый путь каталогом.
Func _IsDir($Path)
        Return StringInStr(FileGetAttrib($Path), "D")
EndFunc

;~ ---------------------------------------------
;~ Позволят получить файловое расширение из пути или имени файла.
;~ Это единственная функция которая нигде не используется!
Func FileGetExtension($name)
        Local $Count=StringInStr($name,".",0,-1)
        If $Count=0 Then
                Return 0
        Else
                Return StringTrimLeft($name,$Count)
        EndIf
EndFunc


Creat0R 07-06-2007 02:13 596210

Есть такой вопрос:

Утилита OpenedFilesView, “умеет просматривать” файлы которые заняты разными приложениями...
Среди прочих возможностей программы, она имеет весьма удобную функцию - закрывать файлы (их Handle), чтобы к примеру, можно было удалить/переместить/переименовать файл без проблем, или изменить в нём данные.

Также программа отображает полный путь к приложению которое “держит” эти файлы...

Вопрос в том, возможно ли и на AutoIt получить доступ к подобной информации, а также иметь возможность закрывать Handles файлов, или временно их неитрализовывать (чего в самой программе нет :) )?

Полагаю тут надо копать в сторону DllCall, но я даже и не знаю какой “тип лопаты” выбрать :biggrin:

P.S
На оф. форуме поднимался подобный вопрос, но до сих пор так ни кто и не нашёл решения, надеюсь среди наших, найдутся знатоки и умеющие хорошо копать люди :)

gregaz 07-06-2007 12:22 596335

Просьба помочь "чайнику" AutoItа
Надоело вариться в собственном соку

Как правильно организовать скрипт с использованием GUI ?
Хотел обратиться раньше,но решил сначала немного самому пощупать(и не без пользы .оказывается)
Просьба показать на примере,содержащем следующее :

1.Создается окно GUI

2.В нем создаются :
- пара текстовых строк (наверное Label 1 - Label 2)
- пара кнопок ( скажем button 1-Button 2)

3.При нажатии кнопки button 1:
- предыдущая инфа стирается
- создается :
- пара новых текстовых строк
- пара элементов Input ( с каким то текстом )
- пара новых кнопок ( скажем Read-Save)
- при нажатии новой кнопки Read :
- выводится инфа до редактирования текста в окнах Input(Слева в окне GUI)
- при нажатии новой кнопки Save :
- выводится инфа после редактирования текста в окнах Input (Справа в окне GUI)

4.При нажатии кнопки button 2:
- Все окно очищается
- Выводится любая обобщающая информация

Из примера хотелось бы понять :

1.Как правильно вводить текст и очищать окно
2.Как правильно организовать опрос элементов GUI при наличии вновь появляющихся
элементов (кнопок Read-Save,элементов Input и т.п. )
3.Как правильно осуществлять поиск по данной теме форума
Заранее благодарен

Creat0R 07-06-2007 14:59 596413

gregaz
Цитата:

Просьба показать на примере,содержащем следующее
Вот пример:

Код:

Global $Input1, $Input2, $ReadButton=-1, $SaveButton=-1

$Gui = GUICreate("Demo GUI", 400, 300)

$Label1 = GUICtrlCreateLabel("Строка 1", 20, 50, 300)
$Label2 = GUICtrlCreateLabel("Строка 2", 20, 100, 300)

$Button1 = GUICtrlCreateButton("Button1", 100, 260, 70)
$Button2 = GUICtrlCreateButton("Button2", 250, 260, 70)

GUISetState()

While 1
    Switch GUIGetMsg()
        Case -3
            Exit
        Case $Button1 ;нажата кнопка "Button1"
            ;Нажата кнопка "Button1", а значит стираем инфу и вместо неё пишем другую
            ;(можно конечно удалять контроли и создавать новые, но не вижу в этом смысла ;) )...
            GUICtrlSetData($Label1, "Новая строка 1")
            GUICtrlSetData($Label2, "Новая строка 2")

                        ;Создаём поля ввода
            $Input1 = GUICtrlCreateInput("Поле ввода 1", 20, 140, 300)
            $Input2 = GUICtrlCreateInput("Поле ввода 2", 20, 180, 300)

                        ;Создаём кнопки Read-Save
            $ReadButton = GUICtrlCreateButton("Read", 100, 220, 70)
            $SaveButton = GUICtrlCreateButton("Save", 250, 220, 70)
        Case $Button2 ;нажата кнопка "Button2"
            ;Удаляем всё кроме кнопок "Button1" и "Button2"
            GUICtrlDelete($Label1)
            GUICtrlDelete($Label2)
            GUICtrlDelete($Input1)
            GUICtrlDelete($Input2)
            GUICtrlDelete($ReadButton)
            GUICtrlDelete($SaveButton)
        Case $ReadButton ;нажата кнопка "Read"
            ;Выводим тот текст что создали (я так понял это нужно?)
            MsgBox(64, "Info", "Поле ввода 1" & @LF & "Поле ввода 2")
        Case $SaveButton ;нажата кнопка "Save"
            ;Выводим то что в полях ввода
            $ReadInput1 = GUICtrlRead($Input1)
            $ReadInput2 = GUICtrlRead($Input2)
            MsgBox(64, "Info", $ReadInput1 & @LF & $ReadInput2)
    EndSwitch
WEnd

Цитата:

Как правильно вводить текст и очищать окно
Это очень сильно зависит от конкретного случая... можно удалить все созданные контроли, но можно и просто очистить данные (GuiCtrlSetData($ControlID, ""), но это также зависит от типа контроля (поле ввода, чекбокс, и т.д).

Цитата:

Как правильно организовать опрос элементов GUI при наличии вновь появляющихся
В каком смысле опрос элементов? чтобы иметь к ним доступ? я это привёл в примере, те контроли, что создаются позже в цикле, нужно заранее обьявить, и желательно со значениями не ровняющимися нулю (0) - типичное поведение переменных обьявленых без значения.

Цитата:

Как правильно осуществлять поиск по данной теме форума
Лучше всего переключить в режим печати (ВСЕ), и искать на странице (Ctrl F :)).

Diamond 07-06-2007 16:33 596472

Creat0R
Рукописная функция _FileOpenDialog у меня возвращает цифры 0x433A5C446F63756D... и т.п. и очень много нулей. :idontnow:
Цитата:

У меня почему то при вызове $dict.Exists скрипт выпадает с ошибкой
А в отдельном скрипте сам объект не пробовал тестировать?
Цитата:

-Добавил функцию для поиска в самом ListView, имхо, так надёжнее, и не так уж намного медленнее
Разница в скорости станет очевидной при обработке больших объёмов информации. ИМХО "Scripting.Dictionary" очень даже надёжен и я принципиально не хочу:lo: от него отказываться. ;)
Цитата:

иконки определяются используя функцию _FileGetIcon()
Я уже начал писать нечто подобное, вот только не знал как получить иконку для папки. Спасибо.
Цитата:

вызывается AutoSize на каждый добавляемый файл, хотя логичнее бдет вызвать один раз эту функцию по оканчанию добавления всех файлов.
... уже думал об этом, но потом решил что это не сильно отразиться на скорости добавления - возможно я и не прав... :dont-know
Цитата:

-Чтобы можно было присваивать иконки айтемам, пришлось вместо вставки айтемов, создавать их встроенными средствами, т.к требуется ControlID.
Спасибо, буду разбираться. :)

Diamond 07-06-2007 17:43 596512

Creat0R
Цитата:

Полагаю тут надо копать в сторону DllCall, но я даже и не знаю какой “тип лопаты” выбрать
По поводу лопаты... Думаю, нужно копать в сторону файловых дескрипторов.
Скорее всего, программе удаётся это сделать за счёт подмены или переназначения блокирующего дескриптора, для своего собственного процесса.
К сожалению, больше ничем помочь не смогу... :dont-know

gregaz 07-06-2007 18:22 596531

Creat0R !
Спасибо за помощь !
Многое стало понятнее .

Естественно сразу возникли вопросы :

1. Почему даный пример работает даже без обьявления #include <GUIConstants.au3> ?

2. Правильно ли я понял ,что обявление Global переменных нужно только лишь для Обьявления
начальных значений еще не созданных элементов ( можно наверное и так : $Input1 ="" и т.д.) ?

3. Цикл Switch-Case-EndSwitch полностью аналогичен циклу Select-Case-EndSelect или есть отличия ?
Можно ли здесь поменять их ?

4. Что означает Case -3 (GUIGetMsg()= -3 ) ? Когда появится это значение ?

5. Правильно ли я понял ,что независимо от появляющихся впоследствии элементов GUI , опрос
об их состояниях (значениях) производится ВСЕГДА в одном общем цикле While-Wend ?
Я пытался после создания новых элементов создавать еще внутренний цикл While-Wend ,поскольку иначе они
почему то получались статическими.

6. Можно ли вместо вывода информации в окне MsgBox осуществлять вывод в том же окне GUI ?

7.Можно ли для очиски окна использовать GUICtrlDelete($ControlID) или GuiCtrlSetData($ControlID, "") - что правильнее ?

8. Как праильно осуществлять поиск ранее обсуждавшихся вопросов на форуме ( не на странице) ?

Извините что напрягаю.

Creat0R 08-06-2007 00:51 596690

Diamond

Цитата:

Рукописная функция _FileOpenDialog у меня возвращает цифры 0x433A5C446F63756D... и т.п. и очень много нулей.
Странно, amel27, что скажешь, от чего это может быть вызвано?

Цитата:

А в отдельном скрипте сам объект не пробовал тестировать?
Не пробовал, но как выяснилось, это вызвано тем, что самопальная функция возвращает символы перевода строки на конце переменной выбранных файлов. При передаче подобной переменной в проверку словаря, действие проваливается.

gregaz
Цитата:

Почему даный пример работает даже без обьявления #include <GUIConstants.au3> ?
Паотому что нет констант из этого вложения используемых примером :)

Цитата:

Правильно ли я понял ,что обявление Global переменных нужно только лишь для Обьявления
начальных значений еще не созданных элементов ( можно наверное и так : $Input1 ="" и т.д.) ?
Совершенно правильно. Если переменные создавать вне функции/циклов (в начале скрипта), то особой необходимости в глобальном обьявлении переменных нет (в данном случае), но всё же это не помешает.

Цитата:

Цикл Switch-Case-EndSwitch полностью аналогичен циклу Select-Case-EndSelect или есть отличия ?
Отличия в том, что при Select подстанавливается полное условие - Case 1 = 1, а при Switch можно один раз указать с чем следует использовать (сравнивать) условия - Switch $Test.... Case 1 - этот случай будет выполнен если переменная $Test будет ровна 1.

Цитата:

Правильно ли я понял ,что независимо от появляющихся впоследствии элементов GUI , опрос
об их состояниях (значениях) производится ВСЕГДА в одном общем цикле While-Wend ?
Не всегда, при желании (необходимости) можно создавать несколько циклов.

Цитата:

Можно ли вместо вывода информации в окне MsgBox осуществлять вывод в том же окне GUI ?
Можно, нужно строить также новый ГУИ ;)

Цитата:

Можно ли для очиски окна использовать GUICtrlDelete($ControlID) или GuiCtrlSetData($ControlID, "") - что правильнее ?
если нужно поменять значение у текстовой строки (Label), то лучше использовать GuiCtrlSetData($ControlID, ""), для полного удаления контроля из ГУИ, нужно использовать GUICtrlDelete($ControlID).

Цитата:

Как праильно осуществлять поиск ранее обсуждавшихся вопросов на форуме
Есть на этом форуме раздел поиска, там вводишь нужный запрос с нужными параметрами (есть помощь там же по поиску), и осуществляется поиск :)

amel27 08-06-2007 06:17 596725

Creat0R
Цитата:

Странно, amel27, что скажешь, от чего это может быть вызвано?
чего-то не пойму что там разработчики намутили с юникодом, кто нибудь может объяснить поведение скрипта?.. у меня значения не совпадают в 2 раза +2
Код:

$u = DllStructCreate ('byte[10]')
ConsoleWrite ("Размер байтового массива: "& DllStructGetSize ($u) &@CRLF)
ConsoleWrite ("Размер данных в массиве: "& StringLen (DllStructGetData ($u,1)) &@CRLF)


amel27 08-06-2007 07:16 596735

Creat0R
Цитата:

Вопрос в том, возможно ли и на AutoIt получить доступ к подобной информации
ИМХО не тот случай, чтобы внешним утилитам предпочесть DLLCall... Надежней будет сваять GUI-интерфейс над подходящей CMD-утилитой, благо возможностей в AutoIT предостаточно... :) Дополнительные линки по теме:

http://www.thefreecountry.com/utilit...kedfiles.shtml
http://www.microsoft.com/technet/sys...on/Handle.mspx

З.Ы. Поясню свою позицию. Дело в том, что в Windows нет документированных API-функций по перечислению открытых хэндлов, все подобные утилиты используют недокументированные вызовы функций ядра что не есть хорошо для обычного приложения, в частности могут возникать утечки памяти... При вызове внешних приложений таких проблем не возникает, так как при закрытии процесса система подчищает за ним все "хвосты". Лопата здесь лежит: http://forum.sysinternals.com/forum_...ID=3577&a%20mp. ;)

amel27 08-06-2007 08:21 596748

Creat0R
Помнится, мы мучали функцию _PathSplitByRegExp()... Так вот оказалось, что RegExp-аналог оригинальной функции _PathSplit() занимает всего одну строчку... :)
Код:

#include <array.au3>

$path = 'C:\Program Files\AutoIT3\test.au3'
$p = StringRegExp ($path, '(?i)^\s*([A-Z]:|\\\\[^\\]*)(\\.*\\)(.*?)(\.?[^\.]*)\s*$', 3)

_ArrayDisplay ($p, $path)


gregaz 08-06-2007 17:46 596980

Creat0R !
Спасибо за пример и разьяснения !
Все встает на свои места.

Еще пару вопросов,если можно :

1.На вопрос: Можно ли вместо вывода информации в окне MsgBox осуществлять вывод в том же окне GUI ?
был дан ответ : Можно, нужно строить также новый ГУИ .

А разве нельзя в этом же GUI вот так(тот же пример) : ? Вроде работает.

Код:

Global $Input1, $Input2, $ReadButton=-1, $SaveButton=-1

$Gui = GUICreate("Demo GUI", 400, 300)

$Label1 = GUICtrlCreateLabel("Строка 1", 20, 50, 300,40)
$Label2 = GUICtrlCreateLabel("Строка 2", 20, 100, 300,40)

$Button1 = GUICtrlCreateButton("Button1", 100, 260, 70)
$Button2 = GUICtrlCreateButton("Button2", 250, 260, 70)

GUISetState()

While 1
    Switch GUIGetMsg()
        Case -3
            Exit
        Case $Button1 ;нажата кнопка "Button1"
            ;Нажата кнопка "Button1", а значит стираем инфу и вместо неё пишем другую
            ;(можно конечно удалять контроли и создавать новые, но не вижу в этом смысла ;) )...
            GUICtrlSetData($Label1, "Новая строка 1")
            GUICtrlSetData($Label2, "Новая строка 2")

                        ;Создаём поля ввода
            $Input1 = GUICtrlCreateInput("Поле ввода 1", 20, 140, 300)
            $Input2 = GUICtrlCreateInput("Поле ввода 2", 20, 180, 300)

                        ;Создаём кнопки Read-Save
            $ReadButton = GUICtrlCreateButton("Read", 100, 220, 70)
            $SaveButton = GUICtrlCreateButton("Save", 250, 220, 70)
        Case $Button2 ;нажата кнопка "Button2"
            ;Удаляем всё кроме кнопок "Button1" и "Button2"
            GUICtrlDelete($Label1)
            GUICtrlDelete($Label2)
            GUICtrlDelete($Input1)
            GUICtrlDelete($Input2)
            GUICtrlDelete($ReadButton)
            GUICtrlDelete($SaveButton)
        Case $ReadButton ;нажата кнопка "Read"
            ;Выводим тот текст что создали (я так понял это нужно?)
                        GUICtrlSetData($Label1, "Поле ввода 1" & @LF & "Поле ввода 2")
;                        MsgBox(64, "Info", "Поле ввода 1" & @LF & "Поле ввода 2")
        Case $SaveButton ;нажата кнопка "Save"
            ;Выводим то что в полях ввода
            $ReadInput1 = GUICtrlRead($Input1)
            $ReadInput2 = GUICtrlRead($Input2)
                        GUICtrlSetData($Label2, $ReadInput1 & @LF & $ReadInput2)
;                        MsgBox(64, "Info", $ReadInput1 & @LF & $ReadInput2)
    EndSwitch
WEnd

Может быть такая кострукция в чем то неверна и это скажется в других случаях ?

2. Просьба привести любой простой пример выполнения опросов состояний элементов GUI в разных циклах
Может быть даже в том же примере провести опрос состояний кнопок "Read" и "Save"в отдельном цикле ?
3. Что означает Case -3 (GUIGetMsg()= -3 )? Какой-то идентификатор завершения процессов ???

Diamond 08-06-2007 20:12 597058

Creat0R
Цитата:

как выяснилось, это вызвано тем, что самопальная функция возвращает символы перевода строки на конце переменной выбранных файлов. При передаче подобной переменной в проверку словаря, действие проваливается.
OK, тестирую...
Код:

$Dict=ObjCreate("Scripting.Dictionary")
Dim $var[4]
$var[0]="test1 -->" & @CRLF & "<-- возврат каретки и перенос строки"
$var[1]="test2" & @CRLF
$var[2]=@CRLF & "test3" & @CRLF
$var[3]=@CRLF & @CRLF & @LF & @LF & @CR & @CR

;~ Добавление ключей:
For $o In $var
        $Dict.Add($o,"")
Next

;~ Проверка добавленных ключей:
For $o In $var
        If $Dict.Exists($o) Then
;~        OK!
        Else
;~        ...
        EndIf
Next
;~ У меня не вылетает

;~ Проверка несуществующего ключа
MsgBox(0,"Должен быть: 0",$Dict.Exists("test5"))

;~ Проверка массива:
$arrayKey=$Dict.Keys
For $i=0 To $Dict.Count-1
        MsgBox(0,"Перебор массива...",$arrayKey[$i])
Next
;~ Всё на своём месте.

Наверное дело в чём то другом...
Похожая ошибка возникает при попытке добавить в словарь ключ (Кеу) который там уже существует. (Словарь - изначально не поддерживает дубликаты)


Creat0R 08-06-2007 23:06 597117

amel27
Цитата:

Лопата здесь лежит:
Спасибо, немного покапал, правда не очень глубоко...

Утилита из того топика, вызвращает хэндлы TCP/UDP (правда не совсем понимаю что это), для обычных файлов информации нет :(.

Взял утилиту из второго линка, она возвращает то что нужно, но 400 с лишним кб, это тяжко, даже очень тяжко :sorry: .


Creat0R 09-06-2007 00:03 597137

amel27
Цитата:

оказалось, что RegExp-аналог оригинальной функции _PathSplit() занимает всего одну строчку...
Оригинально, прадва расширение не возвращается...
Но вообще то, я делал функцию _PathSplitByRegExp() не как аналог функции _PathSplit(), а как что то более юзабельное и функциональнее, можно сказать что это как бы “мод” той функции :).


gregaz
Цитата:

А разве нельзя в этом же GUI вот так(тот же пример)
Можно, но лучше отдельно построить ГУИ для вывода информации, и поместить его в функцию, чтобы при каждом вызове небыло необходимости строить занового гуи:

Код:

#include <GuiConstants.au3>

$Gui = GUICreate("Demo GUI", 400, 300)

$Button1 = GUICtrlCreateButton("Button1", 100, 260, 70)

GUISetState()

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $Button1 ;нажата кнопка "Button1"
            $Ret = _GuiMsgBox($WS_EX_TOPMOST, 2, "Info", "Текст 1" & @LF & "Текст 2", 330, 120, _
                "Больше не показывать", "OK", "Отмена", $Gui)
            MsgBox(0, "", "Вернувшееся значение: " & $Ret)
    EndSwitch
WEnd

;Функция для показа самодельного окна MsgBox
Func _GuiMsgBox($Type, $ButtonsNumber, $Title, $Text, $Left, $Top, $CheckBoxText, $FirstButtonText="OK", $SecondButtonText="Cancel", $hWnd=0)
    Local $Yes, $No, $OK, $CheckBox=-1, $Gui, $Msg, $ReturnVal = 0

        If $hWnd <> 0 Then WinSetState($hWnd, "", @SW_DISABLE)

        $Gui = GuiCreate($Title, $Left, $Top, -1, -1, -1, $Type, $hWnd)

    GUICtrlCreateLabel($Text, ($Left-($Left-($Left/2/2)))/2, (($Top/2)/2)-10, $Left-($Left/2/2), 40, $SS_CENTER)

    Select
        Case $ButtonsNumber = 2
            $Yes = GUICtrlCreateButton($FirstButtonText, ($Left/2)-90, ($Top/2), 70, 20)
            $No = GUICtrlCreateButton($SecondButtonText, ($Left/2)+20, ($Top/2), 70, 20)
        Case $ButtonsNumber > 2 Or $ButtonsNumber <= 1
            $OK = GUICtrlCreateButton($FirstButtonText, ($Left-70)/2, $Top/2, 70, 20)
    EndSelect

    If $CheckBoxText <> "" Then $CheckBox = GUICtrlCreateCheckbox($CheckBoxText, 15, $Top-30)
    GuiSetState(@SW_SHOW, $Gui)

    While 1
        $Msg = GUIGetMsg()
        Select
            Case $ButtonsNumber = 2 And $Msg = $Yes
                If GUICtrlRead($CheckBox) = 1 Then
                    $ReturnVal = 6+8
                Else
                    $ReturnVal = 6
                EndIf
                ExitLoop
            Case $ButtonsNumber = 2 And $Msg = $No
                If GUICtrlRead($CheckBox) = 1 Then
                    $ReturnVal = 7+8
                Else
                    $ReturnVal = 7
                EndIf
                ExitLoop
            Case ($ButtonsNumber = 1 Or $ButtonsNumber <> 2) And $Msg = $OK
                If GUICtrlRead($CheckBox) = 1 Then
                    $ReturnVal = 1+8
                Else
                    $ReturnVal = 1
                EndIf

                            Case $Msg = -3
                ExitLoop
        EndSelect
    Wend
    If $hWnd <> 0 Then WinSetState($hWnd, "", @SW_ENABLE)
    GUIDelete($Gui)
    Return $ReturnVal
EndFunc

Цитата:

Просьба привести любой простой пример выполнения опросов состояний элементов GUI в разных циклах
Не уверен что понимаю просьбу, что значить в разных циклах? цикл не важен, важно действие, что именно требуеся опрашивать, если нужно проверить текст поля ввода, тогда GuiCtrlGetData, если нужно проверить зажат ли той или инной чекбокс (птичка), тогда GuiCtrlRead() - если 1, тогда зажата, в противном случе вернётся 4, и т.д.

Цитата:

Что означает Case -3 (GUIGetMsg()= -3 )? Какой-то идентификатор завершения процессов ???
-3 это тоже самое что и $GUI_EVENT_CLOSE, я просто изначально значение многих констант выучил наизусть, поэтому по привычке использую их как есть, это иногда удобно, и позволяет не использовать вложения библиотеки, типа #Include <GuiConstants.au3>. $GUI_EVENT_CLOSE это константа, функция GuiGetMsg() возвращает её значение (-3) если послана команда закрыть окно ГУИ (пользователь нажал крестик закрытия программы).

Diamond
Цитата:

Наверное дело в чём то другом...
Возможно...

Цитата:

Похожая ошибка возникает при попытке добавить в словарь ключ (Кеу) который там уже существует.
Но у меня выводилась ошибка именно на строке с проверкой $Dict.Exists... :idontnow:

P.S
Но я всё же больше доверяю массивам :tongue: (возможно боязень чего то нового).

amel27 09-06-2007 06:28 597182

Creat0R
Цитата:

правда расширение не возвращается
енто частности, уже исправил. :)

Кстати, насчет твоего старого вопроса о массовой замене и функции _StringRexExpReplaceEx… зачем там RegExp? Имхо вариант с обычным StringReplace справится лучше, плюсы очевидны:

- работает быстрее;
- нет проблем с форматными символами (речь о "|");
- если элементу из массива $Pattern нет соответствия в $Replace автоматически предполагается пустая строка.
Код:

$String = 'file://localhost/%22c:/my%20test/test.zip%22'
Dim $Pattern [4] = ['/','%20','%22','file:\\localhost\']
Dim $Replace[3] = ['\',' ','"']

Func _StringReplaceEx ($String, $Pattern, $Replace)
    Local $i
    ReDim $Replace[UBound($Pattern)]
    For $i=0 To UBound($Pattern)-1
        ConsoleWrite ($Pattern[$i]&':'&$Replace[$i]&@CRLF)
        $String = StringReplace ($String, $Pattern[$i], $Replace[$i])
    Next
    Return $String
EndFunc

MsgBox (64, "Results", _StringReplaceEx ($String, $Pattern, $Replace)) ;На выходе имеем это: "c:\my test\test.zip"


gregaz 09-06-2007 09:26 597221

Creat0R
функция _GuiMsgBox достаточно громоздкая видимо из-за своей универсальности(на все случаи жизни)
Попробую разобраться в ней.
А пока 1 вопрос :
При закрытии дочернего окна GUI у меня обычно закрывается и родительсое окно.
У тебя же в примере этого не происходит .
Чем это достигнуто ?

Creat0R 09-06-2007 09:37 597223

amel27
Цитата:

зачем там RegExp?
Я тоже в начале не хотел это использовать, но дело в том, что в отличие от приведённого мной примера, иногда есть необходимость для каждой замены задавать Patern (кстати, как оно по русский? :) ), чтобы по нему делать замену.

Вобщем спасибо, идея с созданием массива вне функции мне понравилась, это позволяет более удобно задавать Patern и соответственно замену.
А также...

Цитата:

- нет проблем с форматными символами (речь о "|");
:)

Вот немного переделал, добавил проверку ошибочности и возврат общего числа сделанных замен (@Extended):

Код:

$String = 'file://localhost/%22c:/my%20test/test.zip%22'
Dim $Pattern[4] = ['/', '%20', '%22', 'file:\\localhost\']
Dim $Replace[4] = ['\', ' ', '"', '']

$String = _StringMultiReplace($String, $Pattern, $Replace)

MsgBox (64, "Results", $String  & @LF & "Число замен: " & @extended)
;На выходе имеем это:
;"c:\my test\test.zip"
;Число замен: 9

Func _StringMultiReplace($String, $Pattern, $Replace)
    If Not IsArray($Pattern) Or Not IsArray($Replace) Then Return SetError(1, 0, $String)
    Local $Extended = 0
    ReDim $Replace[UBound($Pattern)]
    For $i = 0 To UBound($Pattern)-1
        $String = StringReplace($String, $Pattern[$i], $Replace[$i])
        $Extended += @extended
    Next
    Return SetError(0, $Extended, $String)
EndFunc

gregaz
Цитата:

При закрытии дочернего окна GUI у меня обычно закрывается и родительсое окно.
Это зависит от того как оно закрывается...

Цитата:

Чем это достигнуто ?
Функция GuiDelete() имеет один опциональный параметр, это должен быть уникальный идентификатор, который возвращается функцией GuiCreate().

Соответственно, если имеем 2 ГУИ:

$Gui_1 = GuiCreate("Первый ГУИ")

$Gui_2 = GuiCreate("Второй ГУИ")


То для закрытия второго (предполагается что они оба уже видны), задаём как первый параметр команды GuiDelete() его идентификатор:

GuiDelete($Gui_2)

Также можно и спрятать окно:

GuiSetState(@SW_HIDE, $Gui_2)

Для показа обратно:

GuiSetState(@SW_SHOW, $Gui_2)

gregaz 09-06-2007 10:01 597233

Цитата:

gregaz
Цитата:При закрытии дочернего окна GUI у меня обычно закрывается и родительсое окно.

Creat0R
Это зависит от того как оно закрывается...
Спасибо это тоже полезно,ноя имел ввиду закрытие системным крестиком (в правом верхнем углу ).

amel27 09-06-2007 10:33 597244

Creat0R
По поводу _FileOpenDialog() - замени по тексту в определении структур "byte" на "char"... Так вроде работает, но логику изменений в работе структурных функций AutoIT-а пока не просек... нелогично это, когда бинарные данные (не текст!) по умолчанию преобразуются в юникод... на выходе получается чёрти-чё...

Creat0R 09-06-2007 11:27 597267

gregaz
Цитата:

я имел ввиду закрытие системным крестиком
Но если в главном цикле не задать действие для этого крестика, а именно это:

If GuiGetMsg = -3 Then
GuiDelete($Gui_2)
EndIf

то ничего происходить не будет.

Поэтому я и написал, что это зависит от ситуации и метода закрытия.

amel27
Цитата:

замени по тексту в определении структур "byte" на "char"
Ок, спасибо, но у меня пока этой проблемы нет, я ещё не ставил новую версию AutoIt (юзаю 3.2.2.0), но когда поставлю, полагаю мне это пригодится :)


Время: 07:44.

Время: 07:44.
© OSzone.net 2001-