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

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   Замена текста с помощью VBScript при условии?! (http://forum.oszone.net/showthread.php?t=336117)

Hraniti 10-08-2018 07:53 2825726

Замена текста с помощью VBScript при условии?!
 
Здравствуйте, пытаюсь реализовать скрипт который будет находить нужное мне значение например 1134 и заменять на 1401 при условии что 1134 должно находится между dota_camera_pitch_max и dota_camera_distance.

Код:

Const ForReading = 1
Const ForWriting = 2

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\1111\client.dll", ForReading)

strText = objFile.ReadAll
objFile.Close
strNewText = Replace(strText, "1134", "1401")

Set objFile = objFSO.OpenTextFile("C:\1111\client.dll", ForWriting)
objFile.WriteLine strNewText
objFile.Close

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

Iska 10-08-2018 11:04 2825758

Hraniti, лучше не пытайтесь работать таким кодом с бинарными файлами, коими являются библиотеки.

Как надо:
  • берёте конкретную версию библиотеки;
  • берёте правильный hex-редактор;
  • открываете в нём библиотеку;
  • ищете потребное значение и находите;
  • делаете потребную замену;
  • на основе сделанной замены создаёте патч для исходной библиотеки.

megaloman 10-08-2018 11:08 2825760

Hraniti, Если тупо решать задачу как поставлено (Iska наверняка прав!) то вместо Вашего реплэйса
Код:

lstrText = LCase(strText)
marg1 = InStr(1, lstrText, "dota_camera_pitch_max")
marg2 = InStr(1, lstrText, "dota_camera_distance")
repstr = Mid(strText, marg1, marg2 - marg1)

strNewText = Replace(strText, repstr, Replace(repstr, "1134", "1401"))

Если 1134 между указанными строками встречается многократно, то заменятся все.

Hraniti 10-08-2018 11:09 2825761

Iska, Я понимаю что не надо, но давайте попробуем реализовать как я прошу попробовать. Ну если есть возможность можете более детальней объяснить как сделать эту надобность.

Iska 10-08-2018 11:14 2825762

Hraniti, упаковываете Вашу библиотеку в архив, каковой прикладываете к сообщению. Если сюда не помещается — выкладываете на DropMeFiles.

Hraniti 10-08-2018 12:02 2825779

Вложений: 1
  • 22.jpg (23.70 KB, скачиваний: 13)
megaloman,

Код:

Const ForReading = 1
Const ForWriting = 2

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\Program Files (x86)\Steam\steamapps\common\dota 2 beta\game\dota\bin\win64\client.dll", ForReading)

lstrText = LCase(strText)
marg1 = InStr(1, lstrText, "dota_camera_pitch_max")
marg2 = InStr(1, lstrText, "dota_camera_distance")
repstr = Mid(strText, marg1, marg2 - marg1)

strNewText = Replace(strText, repstr, Replace(repstr, "1134", "1401"))

Set objFile = objFSO.OpenTextFile("C:\Program Files (x86)\Steam\steamapps\common\dota 2 beta\game\dota\bin\win64\client.dll", ForWriting)
objFile.WriteLine strNewText
objFile.Close

Пишет ошибку

Iska 10-08-2018 12:42 2825785

Код:

Option Explicit

Const strPath2Client = "C:\Мои проекты\0180\client.dll"

Dim strContent
Dim objRegExp


With WScript.CreateObject("Scripting.FileSystemObject")
        If .FileExists(strPath2Client) Then
               
                With .OpenTextFile(strPath2Client)
                        strContent = .ReadAll()
                        .Close
                End With
               
                Set objRegExp = WScript.CreateObject("VBScript.RegExp")
               
                objRegExp.Pattern = "(dota_camera_pitch_max\x00{3})1134(\x00{4}dota_camera_distance)"
               
                If objRegExp.Test(strContent) Then
                        With .CreateTextFile(strPath2Client, True)
                                .Write objRegExp.Replace(strContent, "$11401$2")
                                .Close
                        End With
                Else
                        WScript.Echo "Can't find pattern [" & Replace(objRegExp.Pattern, Chr(0), " ") & "] in source file [" & strPath2Client & "]."
                        WScript.Quit 2
                End If
               
                Set objRegExp = Nothing
        Else
                WScript.Echo "Can't find source file [" & strPath2Client & "]."
                WScript.Quit 1
        End If
End With

WScript.Quit 0


Hraniti 13-08-2018 11:29 2826158

Вложений: 1
  • err.jpg (20.80 KB, скачиваний: 11)
Iska, Выдает ошибку и данные не меняются. скриншот прилагаю.

Hraniti 13-08-2018 11:30 2826159

Вот собственно сам файл https://yadi.sk/d/q-nkzoD_3a692L

Iska 13-08-2018 13:21 2826178

Цитата:

Цитата Hraniti
Вот собственно сам файл https://yadi.sk/d/q-nkzoD_3a692L »

Дружище, попробуйте, ради интереса, сами найти в нём dota_camera_pitch_max и dota_camera_distance. Или хотя бы одно из них.

Hraniti 13-08-2018 14:28 2826188

Вложений: 1
Iska, Спасибо что помогаете. вот скриншот

Iska 13-08-2018 14:54 2826196

Hraniti, не нахожу. Контрольные суммы выложенного client.dll приведите.
Код:

CRC32:  1453ECB7
MD5:    22A7A67509A454059CC83D58B0A6B0B5
SHA1:  07DA4D35F4CA0B3F2A1FAF95D9E76D210A38D919
SHA256: 4BD116EF090741FCF1CB08388BCDCB80859558E82826C4433BD7DB3616443B4B

Возьмите HxD - Freeware Hex Editor and Disk Editor | mh-nexus, откройте им client.dll, найдите и укажите точное значение смещения.

Hraniti 13-08-2018 17:20 2826215

Iska, Откройте через Notepad++

Iska 13-08-2018 18:04 2826220

Hraniti, я открывал и через Notepad++. Нету.

Мы можем долго играть в угадайку. Повторяю: приведите контрольные суммы для файла client.dll и укажите точное значение смещения, где находится 1134 (или dota_camera_pitch_max, или dota_camera_distance).

Hraniti 14-08-2018 07:36 2826303

Вложений: 1
  • sss.jpg (81.20 KB, скачиваний: 9)
Iska, понял. на всякий случай перезалил файл https://yadi.sk/d/UnQmDTD43aCgLd
Вот данные контрольной суммы.
MD5: 4DD79EB8E0EB3DF55618C1145CED6AB8
SHA1: 24E680C045016DB05F291D8B9588275659BE6821
SHA256: A09E4A300F16AF502095CC0B9D8A3193D8499E4676BA5736BA94213FD334B446

Если открыть notepad без переноса строк, интересующая информация содержится на 290877 строчке.
Код:

dota_camera_pitch_max  1134    dota_camera_distance
Скриншот notepad++ с данными с точным нахождением данных прилагаю.

Пустота вокруг 1134 это знак NUL.

Iska 14-08-2018 09:28 2826321

Цитата:

Цитата Hraniti
Вот данные контрольной суммы.
MD5: 4DD79EB8E0EB3DF55618C1145CED6AB8
SHA1: 24E680C045016DB05F291D8B9588275659BE6821
SHA256: A09E4A300F16AF502095CC0B9D8A3193D8499E4676BA5736BA94213FD334B446 »

Как видите, контрольные суммы ранее выложенного файла и текущего не совпадают. Банально не совпадают и размеры файлов. Вот так.

На PowerShell это может выглядеть так:
Код:

$sPath2Client = 'C:\Мои проекты\0183\client.dll'

if([System.IO.File]::Exists($sPath2Client)) {
        $sContent = Get-Content -Path $sPath2Client -Raw
        $oRegExp  = [System.Text.RegularExpressions.Regex]::new('(dota_camera_pitch_max\x00{3})1134(\x00{4}dota_camera_distance)')
       
        if($oRegExp.IsMatch($sContent)) {
                $oRegExp.Replace($sContent, '${1}1401${2}') | Set-Content -Path $sPath2Client -NoNewline
        } else {
                Write-Host "Can't find pattern [$oRegExp] in source file [$sPath2Client]." -ForegroundColor Red
        }
} else {
        Write-Host "Can't find source file [$sPath2Client]." -ForegroundColor Red
}

С WSH наблюдаются определённые проблемы при попытках работы с данным файлом как с текстом, возможно из-за большого количества символов 0x00, не работает не то что поиск по регулярному выражению, так и банальная функция InStr. Возможно, получится поиграться с классом ADODB.Stream, посмотрю, что можно будет сделать.

Iska 15-08-2018 08:44 2826570

На WSH:
Скрытый текст
Код:

Option Explicit

Const strPath2Client = "C:\Мои проекты\0183\client.dll"

Const adTypeBinary = 1
Const adTypeText  = 2

Const adSaveCreateOverWrite = 2

Const intBufferSize = 512

Const strFindString    = "1134"
Const strReplaceString = "1401"


Dim strPattern
Dim strBlockSignature

Dim strContent
Dim lngFileSize

Dim i
Dim arrContent()

Dim lngFoundPosition


strPattern        = "dota_camera_pitch_max" & String(3, Chr(0)) & strFindString & String(4, Chr(0)) & "dota_camera_distance"
strBlockSignature = ConvertByteArray2HexString(ConvertString2ByteArray(strPattern))

With WScript.CreateObject("Scripting.FileSystemObject")
        If .FileExists(strPath2Client) Then
                WScript.StdOut.WriteLine "Source file [" & strPath2Client & "] exists."
               
                lngFileSize = .GetFile(strPath2Client).Size
               
                With WScript.CreateObject("ADODB.Stream")
                        .Type = adTypeBinary
                        .Open
                       
                        WScript.StdOut.WriteLine "Read content."
                        .LoadFromFile(strPath2Client)
                       
                        ReDim arrContent(lngFileSize \ intBufferSize)
                       
                        For i = 0 To lngFileSize - 1 Step intBufferSize
                                arrContent(i \ intBufferSize) = ConvertByteArray2HexString(.Read(intBufferSize))
                                WScript.StdOut.Write "Convert content into hex string: " & FormatNumber(i / (lngFileSize - 1) * 100, 2) & "%" & vbCr
                        Next
                       
                        WScript.StdOut.WriteLine
                       
                        strContent = Join(arrContent, "")
                       
                        lngFoundPosition = InStr(strContent, strBlockSignature)
                       
                        If lngFoundPosition > 0 Then
                                WScript.StdOut.WriteLine "Search pattern [" & strPattern & "] found."
                               
                                .Position = lngFoundPosition \ 2
                               
                                WScript.StdOut.WriteLine "Write new content [" & Replace(strPattern, strFindString, strReplaceString) & "] into source file [" & strPath2Client & "]."
                               
                                .Write ConvertString2ByteArray(Replace(strPattern, strFindString, strReplaceString))
                                .SaveToFile strPath2Client, adSaveCreateOverWrite
                                .Close
                        Else
                                WScript.StdOut.WriteLine "Can't find search pattern [" & strPattern & "] in content of source file [" & strPath2Client & "]."
                                WScript.Quit 2
                        End If
                End With
        Else
                WScript.StdOut.WriteLine "Can't find source file [" & strPath2Client & "]."
                WScript.Quit 1
        End If
End With

WScript.Quit 0
'=============================================================================

'=============================================================================
Function ConvertByteArray2HexString(arrByteArray)
        Dim i
        Dim strValue
       
        strValue = ""
       
        For i = 1 To LenB(arrByteArray)
                strValue = strValue & Right("00" & Hex(AscB(MidB(arrByteArray, i, 1))), 2)
        Next
       
        ConvertByteArray2HexString = strValue
End Function
'=============================================================================

'=============================================================================
Function ConvertString2ByteArray(strValue)
        With WScript.CreateObject("ADODB.Stream")
                .Type = adTypeText
                .CharSet = "windows-1251"
                .Open
                .WriteText strValue
                .Position = 0
                .Type = adTypeBinary
                ConvertString2ByteArray = .Read()
                .Close
        End With
End Function
'=============================================================================


Придётся набраться терпения: перевод массива байт, c которыми VBScript напрямую работать не может, в строку — процесс весьма не быстрый (у меня занимает десять-пятнадцать секунд, ужас). Пробуйте.

Hraniti 15-08-2018 09:06 2826579

Iska, Мне не хватает ума запустить этот код. я правильно понимаю, мне нужно создать файл с расширением .WSH? или мне нужно просто выполнить данный код через консоль?

Разобрался. у меня порядка минуты уходит что бы выполнился этот код. очень долго.

Iska 15-08-2018 09:23 2826586

Цитата:

Цитата Hraniti
я правильно понимаю, мне нужно создать файл с расширением .WSH? »

Нет, создайте файл с расширением .vbs (это скрипт Windows Script Host со входным языком VBScript). .wsh — это файл настроек для скрипта, создавать такой файл Вам не нужно.

Цитата:

Цитата Hraniti
у меня порядка минуты уходит что бы выполнился этот код. очень долго. »

Ото ж. У меня заметно меньше, но всё равно это дико долго выходит. Увы и ах — WSH, в отличие от VB/VBA, не работает напрямую с байтовыми массивами (Byte()).

Hraniti 15-08-2018 09:27 2826588

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

Iska 15-08-2018 09:34 2826591

Цитата:

Цитата Hraniti
думал об более быстром варианте. »

Код для PowerShell я приводил здесь же ранее. Кроме того, к Вашим услугам AutoIt, AutoHotKey и куча языков высокого уровня.

YuS_2 15-08-2018 12:21 2826623

Цитата:

Цитата Iska
На PowerShell это может выглядеть так »

Если говорить о powershell, можно, конечно, и с бинарными данными "поработать":
Код:

$bytes = [io.file]::readallbytes("client.dll")
[byte[]]$rep = [int[]][char[]]'1401'
[byte[]]$fin = [int[]][char[]]"dota_camera_pitch_max$([char]0x00+[char]0x00+[char]0x00)1134"
$i = -1
$a = -join $fin
do {
        $i++
        if($bytes[$i] -eq $fin[0]){
                $b = -join $bytes[$i..($i+$fin.count-1)]
        }
} while ($a -ne $b)
for($n=0;$n -lt $rep.count;$n++){
        $bytes[$i+24+$n] = $rep[$n]
}
[io.file]::writeallbytes("client1.dll", $bytes)

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

Days              : 0
Hours            : 0
Minutes          : 1
Seconds          : 46
Milliseconds      : 912
Ticks            : 1069122715
TotalDays        : 0,00123741054976852
TotalHours        : 0,0296978531944444
TotalMinutes      : 1,78187119166667
TotalSeconds      : 106,9122715
TotalMilliseconds : 106912,2715


в отличие от работы с текстом:
Код:

(gc client.dll -raw) -replace '(?<=dota_camera_pitch_max\x00{3})1134','1401'|set-content client2.dll -non
приемлемая скорость
Код:

Days              : 0
Hours            : 0
Minutes          : 0
Seconds          : 3
Milliseconds      : 979
Ticks            : 39799266
TotalDays        : 4,60639652777778E-05
TotalHours        : 0,00110553516666667
TotalMinutes      : 0,06633211
TotalSeconds      : 3,9799266
TotalMilliseconds : 3979,9266



Цитата:

Цитата Hraniti
Разобрался. у меня порядка минуты уходит что бы выполнился этот код. очень долго. »

Если изменяемые значения находятся по перманентному адресу смещения (т.е. адрес изменяемых данных в файле не меняется), то это будет значительно быстрее...

Iska 15-08-2018 12:29 2826626

Цитата:

Цитата YuS_2
Код:

(gc client.dll -raw) -replace '(?<=dota_camera_pitch_max\x00{3})1134','1401'|set-content client.dll -non
»

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


Цитата:

Цитата YuS_2
но скорость такого "зверского" поиска:
не впечатлила »

С чем сие связываете?

YuS_2 15-08-2018 12:47 2826629

Цитата:

Цитата Iska
файл будет пересоздаваться всякий раз, независимо от того, было ли совпадение шаблона, або нет. »

Это да, проверки нет в коде, но это ведь несложно осуществить...

Цитата:

Цитата Iska
С чем сие связываете? »

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

Iska 15-08-2018 13:42 2826639

Цитата:

Цитата YuS_2
а последовательный перебор массива... »

Хмм… Неужто это даже медленнее работы со строками на WSH?

YuS_2 15-08-2018 14:49 2826652

Цитата:

Цитата Iska
Неужто это даже медленнее работы со строками на WSH? »

Со строками или с массивом текста?
Да и в любом случае, перебор массива (в данном случае массива символов, не строк) - затратная операция.

Iska 15-08-2018 23:32 2826721

Цитата:

Цитата YuS_2
Со строками или с массивом текста? »

Со строками. Вот эти вот:
Код:

For i = 1 To LenB(arrByteArray)
    strValue = strValue & Right("00" & Hex(AscB(MidB(arrByteArray, i, 1))), 2)
Next

в ConvertByteArray2HexString(arrByteArray) для доступа к содержимому байтового массива. Массив строк же сугубо для минимизации временны??х затрат при выделении памяти при конкатенации строк — мы заменяем повторённое N раз strContent = strContent & "bla-bla-bla" на одну strContent = Join(arrContent, "") (теоретически там должны быть те же N конкатенаций с теми же всё возрастающими размерами конечной строки с теми же временны??ми затратами при выделении памяти, но по факту, при стомегабайтных строках — намного, намного ниже).

Кстати, надо бы и с strValue = strValue & Right("00" & Hex(AscB(MidB(arrByteArray, i, 1))), 2) поэкспериментировать аналогичным образом, может тогда получится увеличить размер буфера чтения (он же размер массива arrByteArray).

Цитата:

Цитата YuS_2
Да и в любом случае, перебор массива (в данном случае массива символов, не строк) - затратная операция. »

Да ладно :). Или массив в .Net/PowerShell какой-то не совсем «массив».

Iska 16-08-2018 06:26 2826747

Цитата:

Цитата Iska
Кстати, надо бы и с strValue = strValue & Right("00" & Hex(AscB(MidB(arrByteArray, i, 1))), 2) поэкспериментировать аналогичным образом, может тогда получится увеличить размер буфера чтения (он же размер массива arrByteArray). »

Поэкспериментировал. Как и подозревал, в данном месте существенной разницы от замены простой конкатенации строк в цикле на присвоение значений массиву строк и его Join()'у по выходу из цикла — не обнаружилось. Оно и понятно — тут-то мы манипулируем в небольших пределах строки — размера буфера (он же размер байтового массива, он же размер порции чтения из файла), это же не конкатенация строки размером в сотню мегабайт, как могло бы быть в основном теле скрипта (вместо использования Join()). В том месте замена конкатенации на Join() имело существенное значение, в этом же месте — не имеет.

Также обнаружилось, что оптимальные значения размера буфера лежат в интервале от 256 до 2048 байт, изменение размера буфера в меньшую или большую сторону приводит к увеличению времени исполнения (весьма забавно, что интуитивно выбранное значение в 512 байт оказалось по факту, пожалуй, наилучшим выбором — для данного конкретного случая, конечно).

YuS_2 16-08-2018 06:30 2826748

Цитата:

Цитата Iska
Со строками »

Цитата:

Цитата Iska
Или массив в .Net/PowerShell какой-то не совсем «массив». »

Воот... массив-то, он массив, но его перебор, причем посимвольный, не построчный, так как:
Код:

$bytes = [io.file]::readallbytes("client.dll")
- массив байтов, по сути, а я его пытался парсить циклом со счетчиком...
возможно и есть более правильные варианты, но увы знаний у меня по ним нет...

Iska 16-08-2018 10:03 2826773

Цитата:

Цитата YuS_2
можно, конечно, и с бинарными данными "поработать": »

Не-не-не, это нещщитово — никаких строк, никаких -join'ов. Только массивы, только байты, только хардкор! :lol: И там, кстати, ещё медленнее выйдет, нежели с приведённым вариантом со сравнением первого байта, а затем цельной строки шаблона. Почти в два раза медленнее.

YuS_2 16-08-2018 12:08 2826806

Цитата:

Цитата Iska
Не-не-не, это нещщитово — никаких строк, никаких -join'ов. »

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

Цитата:

Цитата Iska
И там, кстати, ещё медленнее выйдет, нежели с приведённым вариантом со сравнением первого байта, а затем цельной строки шаблона. Почти в два раза медленнее. »

Ну, дык, это и было попыткой ускориться :)
А первоначально, вообще, была стопка вложенных условий... но разница не особо большая получилась :)

Iska 16-08-2018 13:08 2826816

Цитата:

Цитата YuS_2
чойта? кто запретил?
Работаем со всеми доступными методами, главное - результат, а он, увы не впечатляет »

Ну, это я, понятное дело, шучу так ;): работаем старыми проверенными дедовскими способами — и точка!

Цитата:

Цитата YuS_2
А первоначально, вообще, была стопка вложенных условий... »

Ну, я парой обошёлся (и то — мне кажется какой-то кривовастенькой получившаяся реализация).

x0r 16-08-2018 13:17 2826817

ByteKiller или всемизвестный diablo2oo2's Universal Patcher - [dUP] - a freeware patch generator ....уже всёб сделали, пока вы тута переписуетеся

Iska 16-08-2018 13:52 2826832

x0r, Вы что — тему не читали? Автор не жаждет подобным пользоваться. Я ему зараз предлагал.

x0r 16-08-2018 14:24 2826840

Iska, да читал я... подумал, что со второго раза, мож одумаюццо люди, да возьмут норм. способ.

Hraniti 17-08-2018 03:13 2826929

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

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

Iska 17-08-2018 05:50 2826943

Цитата:

Цитата Hraniti
С таким же успехом у могу клавиатуру с мышкой запрограммировать они в секунду будут подобную процедуру делать. »

«С таким же успехом» — не запрограммируете. Никак. Совсем. На воспроизводимость операций вида тык-тык-тык и щёлк-щёлк-щёлк влияет куча внешних факторов, в отличие от нормального программирования.

Hraniti 17-08-2018 05:51 2826944

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

Iska 17-08-2018 06:28 2826945

Hraniti, а причём тут консоль, когда Вы ведёте речь про:
Цитата:

Цитата Hraniti
могу клавиатуру с мышкой запрограммировать они в секунду будут… »


Hraniti 17-08-2018 07:06 2826946

Iska, В общем не хочу в полемики в ходить, я считаю что все должно быть автоматизировано. используя старинной софт это уже как усложненно. Нужно что бы все было просто, нажал 1 раз и все запустилось как нужно.

Iska 17-08-2018 07:22 2826950

Цитата:

Цитата Hraniti
старинной »

Как в одном слове сделать три ошибки — имелось в виду «сторонний»?


Вам предоставили код на PowerShell, на WSH, что не так? И почему «усложнено» — какая разница, исполнять скрипт WSH, скрипт PowerShell или патч в виде исполняемого exe-файла?

x0r 18-08-2018 16:28 2827303

Цитата:

Цитата Hraniti
в день по 10 раз пользоваться костылями? »

костыли, это именно то, что ты пытаесся заделать на VBscript. ОТкрывать бинарнег как текст, заменять там что-то и пользовать ЭТО... ну это ппц.

Ты можешь сделать в DuP патчер, который будет... в общем, ты даже непотрудился справку почитать того, что тебе предложили. там и маски есть и остальное...
ну, вобчем, прадалжай прадалжать жмакать VB.


Время: 23:10.

Время: 23:10.
© OSzone.net 2001-