как распаковать файлы в app раньше чем распакуются арк.архивы, использую isdone?
» Inno Setup (создание инсталяционных пакетов)
Despofix
Если пакуешь файлы средствами inno, то, чтоб они распаковались раньше арк-архивов, повесь распаковку архивов на ssPostInstall (из Isdone):
procedure CurStepChanged(CurStep: TSetupStep);
...
if CurStep = ssInstall then begin //ssPostInstall
...
Если пакуешь файлы средствами inno, то, чтоб они распаковались раньше арк-архивов, повесь распаковку архивов на ssPostInstall (из Isdone):
procedure CurStepChanged(CurStep: TSetupStep);
...
if CurStep = ssInstall then begin //ssPostInstall
...
innonewbie
это я знаю и это мне не подходит. так как будут создваться в начале ярлыки, ставится софт и т.д, а потом только архивы распаковываться будут
это я знаю и это мне не подходит. так как будут создваться в начале ярлыки, ставится софт и т.д, а потом только архивы распаковываться будут
Despofix
тогда в этой же процедуре на том же шаге
ниже строк распаковки припиши строки для созданием ярлыков и установки софта с привязкой к чекбоксам задач и убери строки из RUN
,,,,,,,,,,,,,,,,,,,,,
begin
CreateShellLink(ExpandConstant('{commondesktop}\Ярлык.lnk'), '',
ExpandConstant('{app}\game.exe'),'параметры запуска', ExpandConstant('{app}'), ExpandConstant('{app}\game.ico'), 0, SW_SHOWNORMAL);
_____________________
begin
var
res: integer;
begin
...
Exec(ExpandConstant('{src}\outer\VCRedist\vcredist_x86.exe'), '/q', ExpandConstant('{src}\outer\VCRedist'), SW_SHOW, ewWaitUntilTerminated, Res);
...
тогда в этой же процедуре на том же шаге
ниже строк распаковки припиши строки для созданием ярлыков и установки софта с привязкой к чекбоксам задач и убери строки из RUN
,,,,,,,,,,,,,,,,,,,,,
begin
CreateShellLink(ExpandConstant('{commondesktop}\Ярлык.lnk'), '',
ExpandConstant('{app}\game.exe'),'параметры запуска', ExpandConstant('{app}'), ExpandConstant('{app}\game.ico'), 0, SW_SHOWNORMAL);
_____________________
begin
var
res: integer;
begin
...
Exec(ExpandConstant('{src}\outer\VCRedist\vcredist_x86.exe'), '/q', ExpandConstant('{src}\outer\VCRedist'), SW_SHOW, ewWaitUntilTerminated, Res);
...
Ребят, вот немного помощи нужно.
1. Есть реестр:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{EAEAAF8C-8E86-4CAC-AC08-1A33EDCA34AC}]
"ModifyPath"="\"C:\\Program Files (x86)\\InstallShield Installation Information\\{EAEAAF8C-8E86-4CAC-AC08-1A33EDCA34AC}\\setup.exe\" -runfromtemp -l0x0419 "
"NoModify"=dword:00000001
"NoRepair"=dword:00000001
"UninstallString"="\"C:\\Program Files (x86)\\InstallShield Installation Information\\{EAEAAF8C-8E86-4CAC-AC08-1A33EDCA34AC}\\setup.exe\" -runfromtemp -l0x0419 -removeonly"
"LogFile"="C:\\Program Files (x86)\\InstallShield Installation Information\\{EAEAAF8C-8E86-4CAC-AC08-1A33EDCA34AC}\\setup.ilg"
"ProductGuid"="{EAEAAF8C-8E86-4CAC-AC08-1A33EDCA34AC}"
2.На этот реестр наверняка будет ссылаться autorun кнопка "Удаление". Мне нужно, чтоб при установке моего перепакованного установщика запись была именно в это место "{EAEAAF8C-8E86-4CAC-AC08-1A33EDCA34AC}", а не в "[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\'Принц Персии: Забытые Пески'_is1]" к примеру , чтоб потом можно было тем же autorun при нажатии "Удалить" - запускало мой файл деинсталяции "uninstall.exe" в папке установки.
Если этого не сделать - авторан вместо удаления - запускает снова установку.
Я надеюсь более менее понятно объяснил.
1. Есть реестр:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{EAEAAF8C-8E86-4CAC-AC08-1A33EDCA34AC}]
"ModifyPath"="\"C:\\Program Files (x86)\\InstallShield Installation Information\\{EAEAAF8C-8E86-4CAC-AC08-1A33EDCA34AC}\\setup.exe\" -runfromtemp -l0x0419 "
"NoModify"=dword:00000001
"NoRepair"=dword:00000001
"UninstallString"="\"C:\\Program Files (x86)\\InstallShield Installation Information\\{EAEAAF8C-8E86-4CAC-AC08-1A33EDCA34AC}\\setup.exe\" -runfromtemp -l0x0419 -removeonly"
"LogFile"="C:\\Program Files (x86)\\InstallShield Installation Information\\{EAEAAF8C-8E86-4CAC-AC08-1A33EDCA34AC}\\setup.ilg"
"ProductGuid"="{EAEAAF8C-8E86-4CAC-AC08-1A33EDCA34AC}"
2.На этот реестр наверняка будет ссылаться autorun кнопка "Удаление". Мне нужно, чтоб при установке моего перепакованного установщика запись была именно в это место "{EAEAAF8C-8E86-4CAC-AC08-1A33EDCA34AC}", а не в "[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\'Принц Персии: Забытые Пески'_is1]" к примеру , чтоб потом можно было тем же autorun при нажатии "Удалить" - запускало мой файл деинсталяции "uninstall.exe" в папке установки.
Если этого не сделать - авторан вместо удаления - запускает снова установку.
Я надеюсь более менее понятно объяснил.
в авторане припиши
[Setup]
AppId={EAEAAF8C-8E86-4CAC-AC08-1A33EDCA34AC}
[Setup]
AppId={EAEAAF8C-8E86-4CAC-AC08-1A33EDCA34AC}
Nasgul1987
Дело в том, что авторан не я делал и все его настройки в .ехе
Дело в том, что авторан не я делал и все его настройки в .ехе
kuriozin
Реализовать думаю можно в скрипте, сам аторан нужен, что бы в этом убедится.
Реализовать думаю можно в скрипте, сам аторан нужен, что бы в этом убедится.
kuriozin
На чём сделано не важно, щас попробую ветку реестра подменить.
На чём сделано не важно, щас попробую ветку реестра подменить.
Snoopak96
я пытался недавно подменить, но что-то безрезультатно(( Чую, что без авторана буду.
Кстати, вот вся ветка удаления :
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{EAEAAF8C-8E86-4CAC-AC08-1A33EDCA34AC}]
"ModifyPath"="\"C:\\Program Files (x86)\\InstallShield Installation Information\\{EAEAAF8C-8E86-4CAC-AC08-1A33EDCA34AC}\\setup.exe\" -runfromtemp -l0x0419 "
"NoModify"=dword:00000001
"NoRepair"=dword:00000001
"UninstallString"="\"C:\\Program Files (x86)\\InstallShield Installation Information\\{EAEAAF8C-8E86-4CAC-AC08-1A33EDCA34AC}\\setup.exe\" -runfromtemp -l0x0419 -removeonly"
"LogFile"="C:\\Program Files (x86)\\InstallShield Installation Information\\{EAEAAF8C-8E86-4CAC-AC08-1A33EDCA34AC}\\setup.ilg"
"InstallLocation"="D:\\GAMES\\Prince of Persia Забытые пески"
"ProductGuid"="{EAEAAF8C-8E86-4CAC-AC08-1A33EDCA34AC}"
"InstallSource"="G:\\"
"DisplayName"="Prince of Persia® Забытые пески"
"Publisher"="Ubisoft"
"URLInfoAbout"="http://www.ubi.com"
"Readme"="D:\\GAMES\\Prince of Persia Забытые пески\\Support\\ReadMe\\ReadMe.txt"
"RegOwner"="Angel0chek"
"DisplayIcon"="D:\\GAMES\\Prince of Persia Забытые пески\\Prince of Persia.exe"
"InstallDate"="20120428"
"Language"=dword:00000419
"DisplayVersion"="1.0"
"Version"=dword:01000000
"VersionMajor"=dword:00000001
"VersionMinor"=dword:00000000
"LogMode"=dword:00000001
"EstimatedSize"=dword:ffe09148
, а чтоб появилась активной кнопка удаления , вот это нужно добавить в реестр:
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Ubisoft]
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Ubisoft\Prince of Persia - The Forgotten Sands]
"InstallDir"="D:\\GAMES\\Prince of Persia Забытые пески"
"Language"="Russian"
"Version"="1.0"
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Ubisoft\Prince of Persia - The Forgotten Sands\GameUpdate]
"execPath"="D:\\GAMES\\Prince of Persia Забытые пески\\Prince of Persia.exe"
"info"="f500a53a9ff24b618501e4db48b27c91"
"installdir"="D:\\GAMES\\Prince of Persia Забытые пески"
"language"="us"
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Ubisoft\Ubisoft Game Launcher]
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Ubisoft\Ubisoft Game Launcher\1.0.0.0]
я пытался недавно подменить, но что-то безрезультатно(( Чую, что без авторана буду.
Кстати, вот вся ветка удаления :
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{EAEAAF8C-8E86-4CAC-AC08-1A33EDCA34AC}]
"ModifyPath"="\"C:\\Program Files (x86)\\InstallShield Installation Information\\{EAEAAF8C-8E86-4CAC-AC08-1A33EDCA34AC}\\setup.exe\" -runfromtemp -l0x0419 "
"NoModify"=dword:00000001
"NoRepair"=dword:00000001
"UninstallString"="\"C:\\Program Files (x86)\\InstallShield Installation Information\\{EAEAAF8C-8E86-4CAC-AC08-1A33EDCA34AC}\\setup.exe\" -runfromtemp -l0x0419 -removeonly"
"LogFile"="C:\\Program Files (x86)\\InstallShield Installation Information\\{EAEAAF8C-8E86-4CAC-AC08-1A33EDCA34AC}\\setup.ilg"
"InstallLocation"="D:\\GAMES\\Prince of Persia Забытые пески"
"ProductGuid"="{EAEAAF8C-8E86-4CAC-AC08-1A33EDCA34AC}"
"InstallSource"="G:\\"
"DisplayName"="Prince of Persia® Забытые пески"
"Publisher"="Ubisoft"
"URLInfoAbout"="http://www.ubi.com"
"Readme"="D:\\GAMES\\Prince of Persia Забытые пески\\Support\\ReadMe\\ReadMe.txt"
"RegOwner"="Angel0chek"
"DisplayIcon"="D:\\GAMES\\Prince of Persia Забытые пески\\Prince of Persia.exe"
"InstallDate"="20120428"
"Language"=dword:00000419
"DisplayVersion"="1.0"
"Version"=dword:01000000
"VersionMajor"=dword:00000001
"VersionMinor"=dword:00000000
"LogMode"=dword:00000001
"EstimatedSize"=dword:ffe09148
, а чтоб появилась активной кнопка удаления , вот это нужно добавить в реестр:
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Ubisoft]
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Ubisoft\Prince of Persia - The Forgotten Sands]
"InstallDir"="D:\\GAMES\\Prince of Persia Забытые пески"
"Language"="Russian"
"Version"="1.0"
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Ubisoft\Prince of Persia - The Forgotten Sands\GameUpdate]
"execPath"="D:\\GAMES\\Prince of Persia Забытые пески\\Prince of Persia.exe"
"info"="f500a53a9ff24b618501e4db48b27c91"
"installdir"="D:\\GAMES\\Prince of Persia Забытые пески"
"language"="us"
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Ubisoft\Ubisoft Game Launcher]
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Ubisoft\Ubisoft Game Launcher\1.0.0.0]
kuriozin
К сожалению нет, подмена реестра ни к чему не привела, надо ковырять сам exe, что долго и муторно.
Проще к стати самому сделать, *.btn - это обычные zip архивы, внутри которых нужная графика.
К сожалению нет, подмена реестра ни к чему не привела, надо ковырять сам exe, что долго и муторно.
Проще к стати самому сделать, *.btn - это обычные zip архивы, внутри которых нужная графика.
Snoopak96
Да, все бы хорошо , но я не знаю как работать в AutoPlay Media Studio. хоть пример бы подкинуть.
Ну желательно, что нужно прописать, чтоб при нажатии на кнопку , установки -запустилась установка. потом ориентируясь на реестр - появились 2 кнопки играть и удалить которые тоже ориентировались на реестр выполняли свои функции. Я ж команд не знаю.
Да, все бы хорошо , но я не знаю как работать в AutoPlay Media Studio. хоть пример бы подкинуть.
Ну желательно, что нужно прописать, чтоб при нажатии на кнопку , установки -запустилась установка. потом ориентируясь на реестр - появились 2 кнопки играть и удалить которые тоже ориентировались на реестр выполняли свои функции. Я ж команд не знаю.
kuriozin - вот подсмотри в блокноте файл скомпиленного проекта авторана, сам код и переменные в нем чистые.
http://rghost.ru/37819138
http://rghost.ru/37819138
Kindly
вот капец -я читать не умею.
вот капец -я читать не умею.
kuriozin - я ж говорю в Блокноте обычном, и этот файл никуда не прикрутишь.
Например из скрипта:
GameRegistry = "Software\\Ubisoft\\Prince of Persia - The Forgotten Sands";
-- Enable/Disable Play and Install buttons if the game is installed
if (Registry.GetValue(HKEY_LOCAL_MACHINE, GameRegistry, "InstallDir", true) == "") then
Button.SetEnabled("ButtonPlay", false);
Button.SetEnabled("ButtonUninstall", false);
else
Button.SetEnabled("ButtonInstall", false);
end
Вот что по нажатии кнопки Uninstall:
setupFile = String.Concat(path, "\\setup.exe");
if( File.DoesExist(setupFile) == true) then
Shell.Execute(setupFile, "open", "",path, SW_SHOWNORMAL);
end;
Application.Exit(0);
Короче, это значит, что под твой инсталлятор надо делать авторан самому, т.к. InstallShield-овские имеют свойство при повторном запуске запускать деинсталлятор.
Например из скрипта:
GameRegistry = "Software\\Ubisoft\\Prince of Persia - The Forgotten Sands";
-- Enable/Disable Play and Install buttons if the game is installed
if (Registry.GetValue(HKEY_LOCAL_MACHINE, GameRegistry, "InstallDir", true) == "") then
Button.SetEnabled("ButtonPlay", false);
Button.SetEnabled("ButtonUninstall", false);
else
Button.SetEnabled("ButtonInstall", false);
end
Вот что по нажатии кнопки Uninstall:
setupFile = String.Concat(path, "\\setup.exe");
if( File.DoesExist(setupFile) == true) then
Shell.Execute(setupFile, "open", "",path, SW_SHOWNORMAL);
end;
Application.Exit(0);
Короче, это значит, что под твой инсталлятор надо делать авторан самому, т.к. InstallShield-овские имеют свойство при повторном запуске запускать деинсталлятор.
kuriozin - вот, нашел у с ебя простейший пример подобного авторана на AMS, адаптировал под последнюю 8-ую версию. Глянь проект, улови принцип действия авторана.
http://rghost.ru/37822269
ЗЫ: проект был написан очень давно, 6 лет назад так что не придираться если какие-то вопросы будут по авторану, задавайте их в программах темы по AMS - я уже давно отошел от темы. Такие автораны легко и в Inno состряпать
ЗЗЫ: т.к. автораны - это зло (потом думаю каждый осознает почему), то на диске хватает одного инсталлятора.
http://rghost.ru/37822269
ЗЫ: проект был написан очень давно, 6 лет назад так что не придираться если какие-то вопросы будут по авторану, задавайте их в программах темы по AMS - я уже давно отошел от темы. Такие автораны легко и в Inno состряпать
ЗЗЫ: т.к. автораны - это зло (потом думаю каждый осознает почему), то на диске хватает одного инсталлятора.
Вообщем , забил на этот авторан. Для меня это как с винды пересесть за никогда не юзавший линукс.
О, а в установщике inno setup существует такой скрипт, чтоб после установки и вновь запущенной установки не устанавливалось , а удалялось, ориентируясь на реестр? В таком случае авторан не нужно переделывать.
О, а в установщике inno setup существует такой скрипт, чтоб после установки и вновь запущенной установки не устанавливалось , а удалялось, ориентируясь на реестр? В таком случае авторан не нужно переделывать.
Nasgul1987
Хорошо, а как этот код совместить с моим? #
И еще вопрос:
У меня х64 ОС , и ветка удаления прописывается в wow6432node
А вот нужно, чтоб определяло , если х32 система - ключи проверяло в обичной ветке удаления. А если х64 , то wow6432node.
Хорошо, а как этот код совместить с моим? #
И еще вопрос:
У меня х64 ОС , и ветка удаления прописывается в wow6432node
А вот нужно, чтоб определяло , если х32 система - ключи проверяло в обичной ветке удаления. А если х64 , то wow6432node.
Цитата:
Хорошо, а как этот код совместить с моим?
с твоим чем?
если авторан через медиа студию, то не знаю
скриптом?
ну это самодостаточный пример. Вставь картинки, файлы секции и пользуйся.
Пи желании те же кнопки можно перенести на форму и сделать авторан на инно.
Ты разбери тот пример
в нём нет ничего сложного
Цитата:
если х32 система - ключи проверяло...
думаю инно с этим справится без всякого.
сам юзаю 64 бинтую систему и ничего не прописываю
а судя по тестам на других системах всё работает также
Nasgul1987
Я имел в виду со скриптом который прикрепил в сообщении под #.
Вот можете посмотреть, где я накосячил? У меня в верхнем левом углу установщика пишет "&Далее>".
http://rghost.ru/37832141
Я имел в виду со скриптом который прикрепил в сообщении под #.
Вот можете посмотреть, где я накосячил? У меня в верхнем левом углу установщика пишет "&Далее>".
http://rghost.ru/37832141
Ребят подскажите пожалуйста сайты где можно скачать скрипты инсталляторов....
Ребят подскажите пожалуйста как в скрипте на основе ISDone через ISExec прописать упаковку папки допустим data1, находящейся в корневом каталоге приложения, т.е. {app}/data1 в файл data.sar и последующее удаление папки data2, а потом то же самое проделать с папкой data2.
В sar-файлы эти папки упаковываются с помощью приложения unpakke.еxe, который для этого случая использует dll-ку upkk_sar.dll. Делал это батником содержания < unpakke upkk_sar.dll pack "data1" "data1.sar" >
del
В sar-файлы эти папки упаковываются с помощью приложения unpakke.еxe, который для этого случая использует dll-ку upkk_sar.dll. Делал это батником содержания < unpakke upkk_sar.dll pack "data1" "data1.sar" >
del
kuriozin
WizardForm.Caption := ExpandConstant(SetupMessage(msgButtonNext)); //// вот тут я накосячил. Зачем окну присваивать константу кнопки
вот правильно
WizardForm.NextButton.Caption := ExpandConstant(SetupMessage(msgButtonNext));
те при наличии ключа кнопка называется "продолжить"
в противном случае как обычно "далее"
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
небольшой апдейт
замени всю процедуру CancelButtonClick на эту:
procedure CancelButtonClick(CurPageID: Integer; var Cancel, Confirm: Boolean);
begin
if RegKeyExists(HKLM, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{#SetupSetting("AppID")}_is1')
then
Confirm:= False;
end;
по умолчанию инсталл при нажатии на кнопку отмена спрашивае Да или Нет
Тк было бы глупо при нажатии на кнопку "играть" спрашивать закрывать ли инсталл, то он закрывается без запроса
Теперь он закрывается без запроса, только при наличии ключа, те когда игра установлена.
WizardForm.Caption := ExpandConstant(SetupMessage(msgButtonNext)); //// вот тут я накосячил. Зачем окну присваивать константу кнопки
вот правильно
WizardForm.NextButton.Caption := ExpandConstant(SetupMessage(msgButtonNext));
те при наличии ключа кнопка называется "продолжить"
в противном случае как обычно "далее"
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
небольшой апдейт
замени всю процедуру CancelButtonClick на эту:
procedure CancelButtonClick(CurPageID: Integer; var Cancel, Confirm: Boolean);
begin
if RegKeyExists(HKLM, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{#SetupSetting("AppID")}_is1')
then
Confirm:= False;
end;
по умолчанию инсталл при нажатии на кнопку отмена спрашивае Да или Нет
Тк было бы глупо при нажатии на кнопку "играть" спрашивать закрывать ли инсталл, то он закрывается без запроса
Теперь он закрывается без запроса, только при наличии ключа, те когда игра установлена.
Nasgul1987
Только теперь Вместо кнопки с надписью "Завершить" - надпись "Далее >"
Только теперь Вместо кнопки с надписью "Завершить" - надпись "Далее >"
kuriozin
всё в порядке
проверено
http://rghost.ru/37834628
вот полный пример с файлом
компилируй
запускай, удаляй)
http://rghost.ru/37834655
всё в порядке
проверено
http://rghost.ru/37834628
вот полный пример с файлом
компилируй
запускай, удаляй)
http://rghost.ru/37834655
Nasgul1987
Не, я про страницу завершения
Разобрался. Не парясь, вообще удалил : WizardForm.NextButton.Caption := ExpandConstant(SetupMessage(msgButtonnext));
У меня еще 1 вопрос появился.
А можно сделать ,что после установки, ориентируясь на лог файл установки, тоесть, где будет перечисление файлов ,которые были установлены, - после последующей установки сверху прошлой, файлы , которых не хватало(толи, удалили, толи переместили) восстановило, а остальные не копировало, которые на своих местах?
Не, я про страницу завершения
Разобрался. Не парясь, вообще удалил : WizardForm.NextButton.Caption := ExpandConstant(SetupMessage(msgButtonnext));
У меня еще 1 вопрос появился.
А можно сделать ,что после установки, ориентируясь на лог файл установки, тоесть, где будет перечисление файлов ,которые были установлены, - после последующей установки сверху прошлой, файлы , которых не хватало(толи, удалили, толи переместили) восстановило, а остальные не копировало, которые на своих местах?
kuriozin
Цитата:
Цитата:
Цитата:
ориентируясь на лог файл установкинельзя.
Цитата:
после последующей установки сверху прошлой, файлы , которых не хватало(толи, удалили, толи переместили) восстановилокури справку - флаги к секции [Files]
Цитата:
кури справку - флаги к секции [Files]
Забивай флаг onlyifdoesntexist
*)
Страницы: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
Предыдущая тема: поиск
Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.