Форум программистов, компьютерный форум, киберфорум
Delphi для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.77/22: Рейтинг темы: голосов - 22, средняя оценка - 4.77
2 / 2 / 1
Регистрация: 22.09.2012
Сообщений: 189
1

Поиск и копирование файлов

06.10.2012, 19:01. Просмотров 4215. Ответов 40

1. открытие диалогового окна "Выбор файла" (или дирректории) (в 1 месте дирректорию, в другом файл)
2. копирование пути выбранного файла в Edit.Text и реестр (файл надо сделать в эдит, дирректорию в реестр)
3. по нажатию кнопки поиск в выбранной дирректории файлов с выбранными форматоми и раскладка по папкам в соответствии с типом

если точнее пытаюсь написать нечто вроде патчера, в котором надо выбрать при первом запуске дирректорию установки (возможно в дальнейшем изменение) и сохранить ее в реестр для дальнейшего использовани. дальше выбирается предположительно скачанная папка (в ней какие то файлы разных форматов) или (желательно конечно, если это не очень сложно) архив (zip\rar) так вот там проводится поиск каких то заданных типов файлов, и допустим нашли 1.txt и положили в дир. установки в папку "моя папка\txt files\" что то типа того и так с остальными типами файлов...
помогите пжл с этими 3 пунктами

п.с. еще просто практически не изучал работу с файлами в делфи =)
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
06.10.2012, 19:01
Ответы с готовыми решениями:

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

Поиск и копирование файлов, перебирая все доступные диски
Всем доброго времени суток. Сегодня я столкнулся с проблемой что перед тем как переустановить...

Поиск и копирование файлов. Incompatible types: 'TSearchRec' and 'PAnsiChar'
procedure TForm1.Button1Click(Sender: TObject); Var SR:TSearchRec; FindRes:Integer; prog...

Поиск и копирование файлов
Доброго Времени суток. Народ может вопрос мой будет звучит и глупо но нужна помощ вот в чем, нужно...

40
13036 / 5822 / 1705
Регистрация: 19.09.2009
Сообщений: 8,807
06.10.2012, 19:27 2
По 1 и 3 пункту смотри здесь: Копирование групп файлов, имеющих особенности в именах (например *. Txt) или в содержании. Здесь потребуется доработка для своей задачи.
2 пункт делается с помощью класса TRegistry, который определён в модуле Registry.
1
2 / 2 / 1
Регистрация: 22.09.2012
Сообщений: 189
06.10.2012, 20:04  [ТС] 3
Цитата Сообщение от Mawrat Посмотреть сообщение
По 1 и 3 пункту смотри здесь: Копирование групп файлов, имеющих особенности в именах (например *. Txt) или в содержании. Здесь потребуется доработка для своей задачи.
2 пункт делается с помощью класса TRegistry, который определён в модуле Registry.
спс, но все никак не врублюсь как открыть именно папку? нашел Open.Dialog но он открывает только файлы
0
Заблокирован
06.10.2012, 20:13 4
Delphi
1
2
3
4
5
6
procedure TForm1.Button1Click(Sender: TObject);
var
  Dir: String;
begin
  SelectDirectory('Каталог', 'C:\', Dir); //В Dir путь
end;
0
2 / 2 / 1
Регистрация: 22.09.2012
Сообщений: 189
06.10.2012, 20:31  [ТС] 5
Цитата Сообщение от Бородач Посмотреть сообщение
Delphi
1
2
3
4
5
6
procedure TForm1.Button1Click(Sender: TObject);
var
  Dir: String;
begin
  SelectDirectory('Каталог', 'C:\', Dir); //В Dir путь
end;
да, вот только что сейчас про это читал, а толку? где он этот загадочный компонент??? весю делфю перерыл нигде нет...
0
Миниатюры
Поиск и копирование файлов  
Заблокирован
06.10.2012, 20:37 6
в uses FileCtrl добавь и в палитре не ищи, его там нет
1
13036 / 5822 / 1705
Регистрация: 19.09.2009
Сообщений: 8,807
06.10.2012, 20:40 7
Илья Панов, ты смотрел ссылку которую я дал??? Там SelectDirectory(), как раз, применяется.
0
2 / 2 / 1
Регистрация: 22.09.2012
Сообщений: 189
06.10.2012, 21:26  [ТС] 8
Цитата Сообщение от Бородач Посмотреть сообщение
в uses FileCtrl добавь и в палитре не ищи, его там нет
спс огромное получилось

Добавлено через 1 минуту
Цитата Сообщение от Mawrat Посмотреть сообщение
Илья Панов, ты смотрел ссылку которую я дал??? Там SelectDirectory(), как раз, применяется.
недопер что его подключать надо

Добавлено через 44 минуты
Delphi
1
2
3
4
5
6
7
8
9
10
procedure TForm1.Button2Click(Sender: TObject);
Var Registry: TRegistry;
begin
Registry := TRegistry.Create;
Dir1:= Registry.OpenKeyReadOnly('software\MyProgramm');
Registry.CloseKey;
Registry.Free;
 
Edit1.Text:=Dir1;
end;
пишет несовместимость типов стринг и булеан
0
13036 / 5822 / 1705
Регистрация: 19.09.2009
Сообщений: 8,807
06.10.2012, 21:37 9
Например, предположим, что в разделе HKEY_LOCAL_MACHINE\SOFTWARE создан подраздел MyProgramm и в этом подразделе имеется ключ Dir. Нам нужно прочитать значение этого ключа.
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
uses
  Registry;
 
procedure TForm1.Button1Click(Sender: TObject);
var
  Reg : TRegistry;
  S : String;
begin
  Reg := TRegistry.Create;
  
  Reg.RootKey := HKEY_LOCAL_MACHINE;
  S := '';
  //Второй параметр = True - если такого раздела нет, то создаём его.
  if Reg.OpenKey('SOFTWARE\MyProgramm', True) then
    S := Reg.ReadString('Dir');
  
  Edit1.Text := S;
  
  FreeAndNil(Reg);
end;
1
2 / 2 / 1
Регистрация: 22.09.2012
Сообщений: 189
06.10.2012, 22:59  [ТС] 10
сяп =)

Добавлено через 1 час 16 минут
можно поподробнее по поводу 1 ссылки? я просто мозг об тот код сломал... что то уж очень много кода, увидел аж страшно стало в 1 сообщении описал, что конкретно мне нужно:

выбирается предположительно скачанная папка (в ней какие то файлы разных форматов) или (желательно конечно, если это не очень сложно) архив (zip\rar) так вот там проводится поиск каких то заданных типов файлов, и допустим нашли 1.txt и положили в дир. установки в папку "моя папка\txt files\" что то типа того и так с остальными типами файлов...
как бы мне это попроще нельзя сделать? код можно конкретный? (к моему случаю) путь где искать файлы лежит в переменной Dir2, путь куда их складывать в Dir1, надо только отсортировать... да, и еще такое дело некоторые типы файлов надо всегда пихать в одну папку, а некоторые исходя из пути в Dir2... так вот запутанно т.е. если файл C:\Documents and Settings\Admin\Рабочий стол\Dir2\TXT1\1.txt, а в C:\Documents and Settings\Admin\Рабочий стол\Dir1\ 2 папки Dir1\TXT1\ и Dir1\TXT2\ то надо класть именно в Dir1\TXT1\ вот как то так...
0
13036 / 5822 / 1705
Регистрация: 19.09.2009
Сообщений: 8,807
06.10.2012, 23:12 11
Там значит ещё и вложенные папки надо обрабатывать? Здесь, для начала, надо написать код, который копирует всё содержимое из исходной папки - в целевую. А потом уже можно думать, как реализовать дополнительную логику.
Я сейчас этот начальный код, тогда напишу.
0
2 / 2 / 1
Регистрация: 22.09.2012
Сообщений: 189
06.10.2012, 23:29  [ТС] 12
Цитата Сообщение от Mawrat Посмотреть сообщение
Там значит ещё и вложенные папки надо обрабатывать? Здесь, для начала, надо написать код, который копирует всё содержимое из исходной папки - в целевую. А потом уже можно думать, как реализовать дополнительную логику.
Я сейчас этот начальный код, тогда напишу.
погоди, все содержимое копировать нельзя... в целевой папке есть подпапки (куда и надо распихивать файлы...), но помимо этого там уже есть другие файлы и если ты заменишь все, то часть файлов пропадет, а этого не должно быть... т.е. копировать надо не папки, а сами файлы в нужные папки... да, кстати сейчас ладно пока думаем про папки, но в дальнейшем возможно ли реализовать, чтобы поиск и копирование ПОМИМО папок проводился в архивах? (зип или рар)

п.с. да, еще мелочь такая, название файлов определенного формата надо скопировать и дописать в файл ini внизу (каждое название на 1 строчке)
0
13036 / 5822 / 1705
Регистрация: 19.09.2009
Сообщений: 8,807
07.10.2012, 00:00 13
Цитата Сообщение от Илья Панов Посмотреть сообщение
т.е. копировать надо не папки, а сами файлы в нужные папки...
В общем сейчас пока сделано так. В целевой папке создаётся та же структура каталогов, что и в исходной папке. А файлы копируются только те, которые удовлетворяют заданной маске. Дальше уже можно дополнительную логику придумывать.
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
uses
  FileCtrl;
 
//Процедура копирует структуру папок из aPath1 в папку aPath2.
//И копирует файлы, соответствующие маске aMask.
//Если aMask = '', то маска принимается равной '*'.
procedure CopyFolder(const aPath1, aPath2, aMask : String);
const
  SelfName = 'CopyFolder()';
var
  Sr : TSearchRec;
  Attr : Integer;
  Path1, Path2, Mask : String;
begin
  //Проверка путей.
  Path1 := aPath1;
  Path2 := aPath2;
  if Path1 = '' then
    raise Exception.Create(SelfName + '. Не задан путь к исходной папке.');
  if not DirectoryExists(Path1) then
    raise Exception.Create(SelfName + '. Путь к исходной папке не найден.');
  if Path2 = '' then
    raise Exception.Create(SelfName + '. Не задан путь к целевой папке.');
  //Добавление завершающего слеша в пути.
  Path1 := IncludeTrailingPathDelimiter(Path1);
  Path2 := IncludeTrailingPathDelimiter(Path2);
  //Маска имён файлов.
  Mask := aMask;
  if Mask = '' then Mask := '*';
  //Значение атрибутов, соответствующее любым файлам, исключая тома.
  Attr := faAnyFile - faVolumeID;
 
  //Создаём целевую папку.
  ForceDirectories(Path2);
  //Копирование содержимого.
  try
    if FindFirst(Path1 + Mask, Attr, Sr) = 0 then
    repeat
      //Если найдена папка.
      if (Sr.Attr and faDirectory) = faDirectory then begin
        //Если папка не является ссылкой на саму себя '.' или на папку
        //вышестоящего уровня '..', то выполняем для неё рекурсивный вызов.
        if (Sr.Name <> '.') and (Sr.Name <> '..') then
          CopyFolder(Path1 + Sr.Name, Path2 + Sr.Name, aMask);
      //Если найден файл - копируем его.
      end else
        CopyFile(PChar(Path1 + Sr.Name), PChar(Path2 + Sr.Name), False);
    until FindNext(Sr) <> 0;
  finally
    FindClose(Sr);
  end;
end;
 
procedure TForm1.Button1Click(Sender: TObject);
var
  Mask, Path1, Path2 : String;
begin
  //Исходный путь.
  Path1 := Edit1.Text;
  //Целевой путь.
  Path2 := Edit2.Text;
  //Маска имён файлов.
  Mask := Edit3.Text;
 
  //Копирование.
  CopyFolder(Path1, Path2, Mask);
end;
Если перезаписывать файлы не надо, то в строках 47...48 заменить:
Delphi
1
2
end else
  CopyFile(PChar(Path1 + Sr.Name), PChar(Path2 + Sr.Name), False);
на:
Delphi
1
2
end else if not FileExists(Path2 + Sr.Name) then
  CopyFile(PChar(Path1 + Sr.Name), PChar(Path2 + Sr.Name), False);
0
2 / 2 / 1
Регистрация: 22.09.2012
Сообщений: 189
07.10.2012, 00:14  [ТС] 14
Цитата Сообщение от Mawrat Посмотреть сообщение
Дальше уже можно дополнительную логику придумывать.
я уже не совсем нуб в делфи, но конкретно в работе с файлами вообще пока ничего толком не врубаюсь... можно собственно логику еще плиз к тому же как я понял твой код совсем не катит ведь файлы то потеряются... (те которые уже были в целевой дирректории)

п.с. пошел спать спокойной...
0
13036 / 5822 / 1705
Регистрация: 19.09.2009
Сообщений: 8,807
07.10.2012, 00:24 15
Цитата Сообщение от Илья Панов Посмотреть сообщение
ведь файлы то потеряются... (те которые уже были в целевой дирректории)
Я в предыдущем посте внизу пометку написал - чтобы файлы не перезаписывались, а добавлялись только те, которых в целевой папке пока ещё нет, надо сделать так:
в строках 47...48 заменить:
Delphi
1
2
end else
  CopyFile(PChar(Path1 + Sr.Name), PChar(Path2 + Sr.Name), False);
на:
Delphi
1
2
end else if not FileExists(Path2 + Sr.Name) then
  CopyFile(PChar(Path1 + Sr.Name), PChar(Path2 + Sr.Name), False);
Цитата Сообщение от Илья Панов Посмотреть сообщение
можно собственно логику еще плиз
Логика процедуры CopyFolder() такая. Сначала создаётся целевая папка, если она до этого ещё не была создана. Это делается с помощью вызова ForceDirectories(). Затем, в заданной исходной папке aPath1 с помощью вызовов FindFirst() - FindNext() идёт перебор файлов и вложенных папок по заданной маске. Если встретилась папка - то её мы опять обрабатываем с помощью CopyFolder(). Это рекурсия называется - т. е. процедура CopyFolder() для обработки вложенных папок вызывает саму себя. А если встретился файл - то его мы копируем в целевую папку. Здесь я уже упомянул как сделать так, чтобы существующие файлы не перезаписывались.
1
2 / 2 / 1
Регистрация: 22.09.2012
Сообщений: 189
07.10.2012, 08:29  [ТС] 16
+100500 и все же файлы не перезаписываются... я может не догоняю просто что это значит, но... вот если открыть вин рар, и посмотреть что у него во вкладке обновление (когда запаковываешь), то мне скорее всего подходит вариант обновить существующие файлы... т.е. целевая дирректория не заменяется, файлы добавляются и обновляют существующие, если такие присутствуют.
Потом не совсем понял где и как изпользуется mask... (в смысле не в CopyFolder, а уже использование готовой функции) т.е.
Delphi
1
2
3
//Копирование.
  end else if not FileExists(Path2 + Sr.Name) then
  CopyFile(PChar(Path1 + Sr.Name), PChar(Path2 + Sr.Name), False);
а где мы вводим маску то? (в параметры)

п.с. и еще выше писал 2 вопроса: про добавление имен в ini и поиск и копирование из архивов
0
13036 / 5822 / 1705
Регистрация: 19.09.2009
Сообщений: 8,807
07.10.2012, 22:44 17
Я подправил код. Нам надо сделать так, чтобы выполнялся полный перебор папок. Т. е. для папок у нас маска всегда должна быть такая: '*'. А вот для файлов уже маску можно задавать по-разному.
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
uses
  FileCtrl;
 
//Процедура копирует структуру папок из aPath1 в папку aPath2.
//И копирует файлы, соответствующие маске aMask.
//Если aMask = '', то маска принимается равной '*'.
procedure CopyFolder(const aPath1, aPath2, aMask : String);
const
  SelfName = 'CopyFolder()';
var
  Srd, Srf : TSearchRec;
  AttrD, AttrF : Integer;
  Path1, Path2, Mask : String;
begin
  //Проверка путей.
  Path1 := aPath1;
  Path2 := aPath2;
  if Path1 = '' then
    raise Exception.Create(SelfName + '. Не задан путь к исходной папке.');
  if not DirectoryExists(Path1) then
    raise Exception.Create(SelfName + '. Путь к исходной папке не найден.');
  if Path2 = '' then
    raise Exception.Create(SelfName + '. Не задан путь к целевой папке.');
  //Добавление завершающего слеша в пути.
  Path1 := IncludeTrailingPathDelimiter(Path1);
  Path2 := IncludeTrailingPathDelimiter(Path2);
  //Маска имён файлов.
  Mask := aMask;
  if Mask = '' then Mask := '*';
  //Значение атрибутов, которое может соответствовать папкам.
  AttrD := faAnyFile - faVolumeID;
  //Значение атрибутов, соответствующее любым файлам, исключая тома и папки.
  AttrF := faAnyFile - faVolumeID - faDirectory;
 
  //Создаём целевую папку.
  ForceDirectories(Path2);
 
  //Перебор файлов, согласно маске.
  try
    if FindFirst(Path1 + Mask, AttrF, Srf) = 0 then
    repeat
      CopyFile(PChar(Path1 + Srf.Name), PChar(Path2 + Srf.Name), False);
    until FindNext(Srf) <> 0;
  finally
    FindClose(Srf);
  end;
 
  //Перебор всех папок.
  try
    if FindFirst(Path1 + '*', AttrD, Srd) = 0 then
    repeat
      //Если текущий объект является папкой и такая папка не является ссылкой
      //на саму себя '.' или на папку вышестоящего уровня '..', то выполняем
      //для неё рекурсивный вызов.
      if ( Srd.Attr and faDirectory = faDirectory )
        and (Srd.Name <> '.') and (Srd.Name <> '..')
      then
        CopyFolder(Path1 + Srd.Name, Path2 + Srd.Name, aMask);
    until FindNext(Srd) <> 0;
  finally
    FindClose(Srd);
  end;
end;
 
procedure TForm1.Button1Click(Sender: TObject);
var
  Mask, Path1, Path2 : String;
begin
  //Исходный путь.
  Path1 := Edit1.Text;
  //Целевой путь.
  Path2 := Edit2.Text;
  //Маска имён файлов.
  Mask := Edit3.Text;
 
  //Копирование.
  CopyFolder(Path1, Path2, Mask);
end;
Здесь, если существующие в целевой папке файлы не должны перезаписываться (заменяться), то следует сделать замену в строке 43.
Заменить:
Delphi
1
CopyFile(PChar(Path1 + Srf.Name), PChar(Path2 + Srf.Name), False);
на:
Delphi
1
2
if not FileExists(Path2 + Srf.Name) then
  CopyFile(PChar(Path1 + Srf.Name), PChar(Path2 + Srf.Name), False);
Цитата Сообщение от Илья Панов Посмотреть сообщение
и все же файлы не перезаписываются... я может не догоняю просто что это значит, но... вот если открыть вин рар, и посмотреть что у него во вкладке обновление (когда запаковываешь), то мне скорее всего подходит вариант обновить существующие файлы... т.е. целевая дирректория не заменяется, файлы добавляются и обновляют существующие, если такие присутствуют.
Перезапись файла - это замена содержимого этого файла.
По поводу папок. В представленном коде делается так. Если целевая папка существует, то в отношении самой этой папки никаких действий не выполняется. А если целевой папки нет, то она создаётся.
В отношении файлов. Если используется такой код:
Delphi
1
CopyFile(PChar(Path1 + Srf.Name), PChar(Path2 + Srf.Name), False);
то существующие файлы в целевой папке перезаписываются (т. е. заменяются) версиями из исходной папки. А также записываются те файлы, которых нет в целевой папке, но которые имеются в исходной папке.
Если используется код:
Delphi
1
2
if not FileExists(Path2 + Srf.Name) then
  CopyFile(PChar(Path1 + Srf.Name), PChar(Path2 + Srf.Name), False);
То те файлы, которые уже есть в целевой папке, не заменяются. А только добавляются те файлы, которых в целевой папке нет.
---
Ещё можно обрабатывать сведения о времени изменения файла. Т. е., можно сделать так. Если в исходной и целевой папке имеются файлы с одинаковым именем. И если в исходной папке время изменения файла больше времени изменения такого же файла в целевой папке, то тогда происходит замена файла в целевой папке. В противном случае файл в целевой папке не заменяется.
Цитата Сообщение от Илья Панов Посмотреть сообщение
а где мы вводим маску то? (в параметры)
Маска - это третий параметр в процедуре CopyFolder().
Примеры маски:
'*' - все файлы и папки.
'*.txt' - все файлы и папки с расширением ".TXT".
'a*.txt' - все файлы и папки, имена которых начинаются на "a" и которые при этом имеют расширение ".TXT".
'a??.txt' - все файлы и папки, имена которых состоят из трёх символов и начинаются на "a" и которые при этом имеют расширение ".TXT".
В теле процедуры CopyFolder() маска передаётся в функцию FindFirst(). Тогда цикл вызовов FindFirst() - FindNext() будет выбирать только те файлы (и папки), которые удовлетворяют маске.
Цитата Сообщение от Илья Панов Посмотреть сообщение
про добавление имен в ini
Для работы с INI файлами можно воспользоваться классом TIniFile из модуля IniFiles.
Цитата Сообщение от Илья Панов Посмотреть сообщение
и поиск и копирование из архивов
Для работы с архивами можно применять разные компоненты или модули. Есть много бесплатных компонентов.
Например: ZIPForge, ZipMaster, ZLib.
1
2 / 2 / 1
Регистрация: 22.09.2012
Сообщений: 189
07.10.2012, 22:53  [ТС] 18
 Комментарий модератора 
Нарушение Правил, п.5.17


спс

Mask := Edit3.Text; что это за строка и зачем она там??? ну понятно что присваивает маску из эдита, но разьве мне не надо тогда уж писать каждый раз
CopyFolder(Path1, Path2, '*.txt');
CopyFolder(Path1, Path2, '*.exe'); и т.д. ?
0
13036 / 5822 / 1705
Регистрация: 19.09.2009
Сообщений: 8,807
07.10.2012, 23:05 19
Это для примера сделано - что маска из Edit3 берётся. А так, в программе маску можно другими путями передавать. Если маску задать в виде пустой строки или так: '*' - то будут обрабатываться все файлы.
Цитата Сообщение от Илья Панов Посмотреть сообщение
CopyFolder(Path1, Path2, '*.txt');
CopyFolder(Path1, Path2, '*.exe'); и т.д. ?
Можно и так. - Действовать надо в зависимости от потребностей в алгоритме.
0
2 / 2 / 1
Регистрация: 22.09.2012
Сообщений: 189
07.10.2012, 23:11  [ТС] 20
все, поиск и копирование робит =) спс тебе большое
а можно теперь поподробнее про ini? мне надо взять имена (с расширениями) у одного типа файлов копируемых этой же функцией и записать их в ini файл в самый конец по 1 имени на строчку, файл находится в целевой дирректории (он там уже находится и ничто его точно не будет копировать)
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
07.10.2012, 23:11

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

Поиск файлов и копирование
Здравствуйте, подскажите пожалуайста, как сделать поиск с копированием файлов по расширению на...

Поиск и копирование файлов
Уважаемые знатоки! Прошу вашей помощи.На просторах интернета нашёл батник,который ищет на всех...

Поиск и копирование файлов
Пересмотрел все что смог понять, но так ничего толком и не нашел. Нужно искать на диске С: например...

Авто поиск и копирование файлов
rem если вам надо копировать другие файлы замените значение переменной nam rem по умолчанию поиск...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2020, vBulletin Solutions, Inc.