Что нового

[Ошибки] Ошибка связанная с массивом

Hmayak

Новичок
Сообщения
24
Репутация
0
Доброго времени суток.
Изучаю AutoIt второй день и решил написать скрипт, который бы блокировал доступ к сайтам, так сказать практикуюсь.
Код скрипта следующий:
Код:
#requireadmin ;Запрашиваем права администратора
#Include <File.au3>

Dim $WebAddress ;Переменная хранящая веб-адрес
Dim $FileHandle ;Указатель на файл
Dim $FileText   ;Переменная для хранения текста файла
Dim $TextLines  ;Массив для хранения строк файла
Dim $TextLineNumber ;Переменная для хранения номера совпавшей строки

$WebAddress = InputBox("Блокировка сайта", "Введите адрес веб-сайта," & _
	        "который необходимо заблокировать" & _
			" (например порнуха точка ком):", "", "", 318, 140 ,553, 292, 0) ;Записываем адрес введенный пользователем

If $WebAddress = "" Then ;Если ничего не введено
   Exit       ;то выходим из программы
Else
   $FileHandle = FileOpen(@WindowsDir&"\System32\drivers\etc\hosts", 0) ;Открываем файл hosts для чтения и считываем его дескриптор

If $FileHandle = -1 Then                                             ;Проверяем доступ к файлу
	  MsgBox(16, "Ошибка", "Невозможно открыть файл!")
	  Exit
   EndIf

   $FileText = FileRead($FileHandle)   ;Считываем файл в переменную FileText
   $TextLines = StringSplit($FileText, @CRLF, 1) ;Разбиваем текст на строки
;------- Проверяем записан ли сайт в списке блокированных --------
   $TextLineNumber = -1

   For $i = 0 To UBound($TextLines) Step +1 ;Узнаем размер массива и считываем содержимое его строк в порядке убывания
	  If StringInStr($TextLines[$i], $WebAddress) Then ;Если сайт присутствует в списке файла hosts
	     $TextLineNumber = $TextLines[$i] ;Записываем индекс текущего элемента массива
	  EndIf
   Next
   FileClose($FileHandle)
;-----------------------------------------------------------------
   $FileHandle = FileOpen(@WindowsDir&"\System32\drivers\etc\hosts", 1) ;Открываем файл теперь для записи

  If $FileHandle = -1 Then                                            ;Проверяем доступ к файлу
	  MsgBox(16, "Ошибка", "Невозможно открыть файл!")
	  Exit
   EndIf

  If $TextLineNumber <> -1 Then  ;Если был записан номер совпавшей строки
	  If MsgBox(4, "Ошибка", "Данный сайт уже забанен!"& _
			" Разблокировать его?") = 6 Then ;Спрашиваем у пользователя о разблокировке
	      _FileWriteToLine($FileHandle, $TextLineNumber, "", 1) ;Если согласился удаляем строку с записью данного сайта
	      FileClose($FileHandle) ;Закроем файл
		 Exit
	  EndIf
   Else
	  FileWriteLine($FileHandle, "127.0.0.1 " & $WebAddress) ;Заблокируем сайт
      FileClose($FileHandle) ;Закроем файл
   EndIf
EndIf

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

Вложения

  • .PNG
    .PNG
    25.5 КБ · Просмотры: 11

veretragna

Как писал, так и работает.
Сообщения
140
Репутация
10
Ошибка тут:
Код:
For $i = 0 To UBound($TextLines) Step +1 ;Узнаем размер массива и считываем содержимое его строк в порядке убывания


Исправить на:
Код:
For $i = 0 To UBound($TextLines)-1 Step +1 ;Узнаем размер массива и считываем содержимое его строк в порядке убывания


Суть в том, что (схематически) если размер массива 10, то его 10 элементов находятся по индексам 0-9. 0 - первый, 9 - десятый. Ты же обращаешься по 0-10, запрашивая 11-й элемент, которого не существует, и возникает ошибка.
Поэтому в циклах опроса массивов от возвращенного результата UBound() всегда нужно отнимать единицу. Пробуй!
 
Автор
H

Hmayak

Новичок
Сообщения
24
Репутация
0
Ошибка исчезла, но скрипт не удаляет строку с заблокированным веб-сайтом
 

alex33

Скриптер
Сообщения
1,457
Репутация
186
Hmayak сказал(а):
Ошибка исчезла, но скрипт не удаляет строку с заблокированным веб-сайтом
Вот ошибка, там вместо индекса записывается текст
Код:
$TextLineNumber = $TextLines[$i] ;Записываем индекс текущего элемента массива

А надо записать цифру, которая находится в $i, да и ещё +1 прибавить, потому что строки считаются от одного, а массив от нуля. И того:
Код:
$TextLineNumber = $i + 1 ;Записываем индекс текущего элемента массива
 

veretragna

Как писал, так и работает.
Сообщения
140
Репутация
10
Hmayak сказал(а):
Ошибка исчезла, но скрипт не удаляет строку с заблокированным веб-сайтом

Вот этот участок кода:
Код:
$TextLineNumber = $TextLines[$i] ;Записываем индекс текущего элемента массива

надо заменить на
Код:
$TextLineNumber = $i+1 ;Записываем индекс текущего элемента массива


Вам же нужен номер строки в этой переменной, а не сама строка в текстовом виде.


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

Упс, уже ответили)
 
Автор
H

Hmayak

Новичок
Сообщения
24
Репутация
0
И снова 0 реакции :(
Строки записывает а удалить не может
 

Вложения

  • Снимок.PNG
    Снимок.PNG
    6.8 КБ · Просмотры: 7

InnI

AutoIT Гуру
Сообщения
4,922
Репутация
1,432
Hmayak
Код:
For $i = 1 To $TextLines[0]
  If StringInStr($TextLines[$i], $WebAddress) Then
    $TextLineNumber = $i
    ExitLoop
  EndIf
Next
 
Автор
H

Hmayak

Новичок
Сообщения
24
Репутация
0
InnI сказал(а):
Hmayak
Код:
For $i = 1 To $TextLines[0]
  If StringInStr($TextLines[$i], $WebAddress) Then
    $TextLineNumber = $i
    ExitLoop
  EndIf
Next
Та же ситуация.

alex33 сказал(а):
Hmayak сказал(а):
И снова 0 реакции :(
Строки записывает а удалить не может
Проверяйте флаг @error.
Код:
ConsoleWrite("error code = " & @error & @CRLF)
Вставил в раздел, где выдается пользователю сообщение с предложением о замене файла, после нажатия "Да" ничего не выдает.
Код:
If $TextLineNumber <> -1 Then  ;Если был записан номер совпавшей строки
	  If MsgBox(4, "Ошибка", "Данный сайт уже забанен!"& _
			" Разблокировать его?") = 6 Then ;Спрашиваем у пользователя о разблокировке
	      _FileWriteToLine($FileHandle, $TextLineNumber, "", 1) ;Если согласился удаляем строку с записью данного сайта
	      FileClose($FileHandle) ;Закроем файл
		  ConsoleWrite("error code = " & @error & @CRLF)
		 ;Exit
	  EndIf
 

veretragna

Как писал, так и работает.
Сообщения
140
Репутация
10
Заменить
Код:
_FileWriteToLine($FileHandle, $TextLineNumber, "", 1) ;Если согласился удаляем строку с записью данного сайта

на
Код:
_FileWriteToLine(@WindowsDir&"\System32\drivers\etc\hosts", $TextLineNumber, "", 1) ;Если согласился удаляем строку с записью данного сайта
 

alex33

Скриптер
Сообщения
1,457
Репутация
186
madmasles сказал(а):
Hmayak [?]
Строки записывает а удалить не может
_FileWriteToLine() не удаляет строки.
А это тогда что?
file.I_001.jpg
 

veretragna

Как писал, так и работает.
Сообщения
140
Репутация
10
Hmayak сказал(а):
Я пытаюсь ее хотя бы перезаписать на пустую.
Как быть?

В общем, этот скрипт работает. И добавляет, и удаляет. Не за что!

Код:
#RequireAdmin ;Запрашиваем права администратора
#include <File.au3>

Dim $WebAddress ;Переменная хранящая веб-адрес
Dim $FileHandle ;Указатель на файл
Dim $FileText ;Переменная для хранения текста файла
Dim $TextLines ;Массив для хранения строк файла
Dim $TextLineNumber ;Переменная для хранения номера совпавшей строки

$WebAddress = InputBox("Блокировка сайта", "Введите адрес веб-сайта," & _
		"который необходимо заблокировать" & _
		" (например порнуха точка ком):", "", "", 318, 140, 553, 292, 0) ;Записываем адрес введенный пользователем

If $WebAddress = "" Then ;Если ничего не введено
	Exit ;то выходим из программы
Else
	$FileHandle = FileOpen(@WindowsDir & "\System32\drivers\etc\hosts", 0) ;Открываем файл hosts для чтения и считываем его дескриптор

	If $FileHandle = -1 Then ;Проверяем доступ к файлу
		MsgBox(16, "Ошибка", "Невозможно открыть файл!")
		Exit
	EndIf

	$FileText = FileRead($FileHandle) ;Считываем файл в переменную FileText
	$TextLines = StringSplit($FileText, @CRLF, 1) ;Разбиваем текст на строки
	;------- Проверяем записан ли сайт в списке блокированных --------
	$TextLineNumber = -1

	For $i = 1 To $TextLines[0] ;Узнаем размер массива и считываем содержимое его строк в порядке убывания
		If StringInStr($TextLines[$i], $WebAddress) Then ;Если сайт присутствует в списке файла hosts
			$TextLineNumber = $i ;Записываем индекс текущего элемента массива
			ExitLoop
		EndIf
	Next
	FileClose($FileHandle)
	;-----------------------------------------------------------------

	$FileHandle = FileOpen(@WindowsDir & "\System32\drivers\etc\hosts", 1) ;Открываем файл теперь для записи

	If $FileHandle = -1 Then ;Проверяем доступ к файлу
		MsgBox(16, "Ошибка", "Невозможно открыть файл!")
		Exit
	EndIf

	If $TextLineNumber <> -1 Then ;Если был записан номер совпавшей строки
		If MsgBox(4, "Ошибка", "Данный сайт уже забанен!" & _
				" Разблокировать его?") = 6 Then ;Спрашиваем у пользователя о разблокировке
			FileClose($FileHandle) ; да-да! Закрыть активный хэндл перед вызовом _FileWriteToLine, иначе получим ошибку "файл заблокирован"
			_FileWriteToLine(@WindowsDir & "\System32\drivers\etc\hosts", $TextLineNumber, "", 1) ;Если согласился удаляем строку с записью данного сайта
			Exit
		EndIf
	Else
		FileWriteLine($FileHandle, "127.0.0.1 " & $WebAddress) ;Заблокируем сайт
		FileClose($FileHandle) ;Закроем файл
	EndIf
EndIf
 
Автор
H

Hmayak

Новичок
Сообщения
24
Репутация
0
veretragna сказал(а):
Hmayak сказал(а):
Я пытаюсь ее хотя бы перезаписать на пустую.
Как быть?

В общем, этот скрипт работает. И добавляет, и удаляет. Не за что!

Код:
#RequireAdmin ;Запрашиваем права администратора
#include <File.au3>

Dim $WebAddress ;Переменная хранящая веб-адрес
Dim $FileHandle ;Указатель на файл
Dim $FileText ;Переменная для хранения текста файла
Dim $TextLines ;Массив для хранения строк файла
Dim $TextLineNumber ;Переменная для хранения номера совпавшей строки

$WebAddress = InputBox("Блокировка сайта", "Введите адрес веб-сайта," & _
		"который необходимо заблокировать" & _
		" (например порнуха точка ком):", "", "", 318, 140, 553, 292, 0) ;Записываем адрес введенный пользователем

If $WebAddress = "" Then ;Если ничего не введено
	Exit ;то выходим из программы
Else
	$FileHandle = FileOpen(@WindowsDir & "\System32\drivers\etc\hosts", 0) ;Открываем файл hosts для чтения и считываем его дескриптор

	If $FileHandle = -1 Then ;Проверяем доступ к файлу
		MsgBox(16, "Ошибка", "Невозможно открыть файл!")
		Exit
	EndIf

	$FileText = FileRead($FileHandle) ;Считываем файл в переменную FileText
	$TextLines = StringSplit($FileText, @CRLF, 1) ;Разбиваем текст на строки
	;------- Проверяем записан ли сайт в списке блокированных --------
	$TextLineNumber = -1

	For $i = 1 To $TextLines[0] ;Узнаем размер массива и считываем содержимое его строк в порядке убывания
		If StringInStr($TextLines[$i], $WebAddress) Then ;Если сайт присутствует в списке файла hosts
			$TextLineNumber = $i ;Записываем индекс текущего элемента массива
			ExitLoop
		EndIf
	Next
	FileClose($FileHandle)
	;-----------------------------------------------------------------

	$FileHandle = FileOpen(@WindowsDir & "\System32\drivers\etc\hosts", 1) ;Открываем файл теперь для записи

	If $FileHandle = -1 Then ;Проверяем доступ к файлу
		MsgBox(16, "Ошибка", "Невозможно открыть файл!")
		Exit
	EndIf

	If $TextLineNumber <> -1 Then ;Если был записан номер совпавшей строки
		If MsgBox(4, "Ошибка", "Данный сайт уже забанен!" & _
				" Разблокировать его?") = 6 Then ;Спрашиваем у пользователя о разблокировке
			FileClose($FileHandle) ; да-да! Закрыть активный хэндл перед вызовом _FileWriteToLine, иначе получим ошибку "файл заблокирован"
			_FileWriteToLine(@WindowsDir & "\System32\drivers\etc\hosts", $TextLineNumber, "", 1) ;Если согласился удаляем строку с записью данного сайта
			Exit
		EndIf
	Else
		FileWriteLine($FileHandle, "127.0.0.1 " & $WebAddress) ;Заблокируем сайт
		FileClose($FileHandle) ;Закроем файл
	EndIf
EndIf
Спасибо.
Объясните пожалуйста принцип работы циклического оператора
Код:
For $i = 1 To $TextLines[0]

Что он там считает?
 

veretragna

Как писал, так и работает.
Сообщения
140
Репутация
10
Функция StringSplit возвращает массив, нулевой элемент которого содержит общее количество получившихся подстрок, а в элементах от 1 до $result[0] - собственно подстроки.

Можешь посмотреть наглядно, включив в проект
Код:
#include <Array.au3>

; и немного ниже
$TextLines = StringSplit($FileText, @CRLF, 1) ;Разбиваем текст на строки
_ArrayDisplay($TextLines)
 
Автор
H

Hmayak

Новичок
Сообщения
24
Репутация
0
veretragna сказал(а):
Функция StringSplit возвращает массив, нулевой элемент которого содержит общее количество получившихся подстрок, а в элементах от 1 до $result[0] - собственно подстроки.

И разница между

Код:
_FileWriteToLine(@WindowsDir&"\System32\drivers\etc\hosts", $TextLineNumber, "", 1)

и
Код:
_FileWriteToLine($FileHandle, $TextLineNumber, "", 1)


учитывая, что
Код:
$FileHandle = FileOpen(@WindowsDir&"\System32\drivers\etc\hosts", 1)
 

veretragna

Как писал, так и работает.
Сообщения
140
Репутация
10
Функция FileOpen возвращает не строку-путь к файлу, а указатель-хэндл на открытый поток файла.
Строка может принимать вид @WindowsDir&"\System32\drivers\etc\hosts", а хэндл - только 32-битное число, похожее на 0x00A0FFBB (чисто схематически, конечно).

Если функция _FileWriteToLine требует на вход только строку, а ты скормишь ей хэндл - получишь ошибку.
 
Верх