1

Тема: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

В аналогичной теме AHK просили откомментировать скрипт под спойлером с некоторой правкой:

'================================== VBS ===================================
' Назначение: создание URL-ярлыка со ссылкой из параметра или буфера обмена

' Параметры (необязательные): <гиперссылка> "<путь к каталогу назначения>"
' Примеры: 1) https://ya.ru   |   2) "" C:\MyURLs

' Если ссылка не задана, то берётся из буфера.
' При отсутствии 2-го параметра местом сохранения будет рабочий каталог.
'==========================================================================
Option Explicit: Dim nConv
'======================== Путь у утилите NConvert =========================
nConv = "%ProgramFiles%\nConvert\nconvert.exe"
'==========================================================================

Dim WSH, FSO, Dir, URL, R, A, Test, S, Title, FN, i
' Создание объектов FSO и WSH:
Set FSO = CreateObject("Scripting.FileSystemObject")
Set WSH = CreateObject("WScript.Shell")

' Вывод сообщения и выход, если задан ложный путь к nConvert:
If Not FSO.FileExists(WSH.ExpandEnvironmentStrings(nConv)) Then _
MsgBox "Укажите верный путь к nConvert!", 4144, " Создание URL-ярлыка" : WScript.Quit

' Работа с параметрами
With WScript.Arguments
  Select Case .Count  ' сопоставление кол-ва
    Case 0 Dir = WSH.CurrentDirectory  ' если ничего, то каталог назначения - рабочий
    Case 1 URL = .Item(0) ' если есть первый, то используется как URL
    Case 2 Dir = .Item(1) ' если есть второй, то используется как каталог назначения
  End Select
End With

If IsEmpty(URL) Then ' если URL пуст или не задан
  ' Передаём переменной URL текст из буфера с отсеканием концевых пробелов:
  R = "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\3\1407"
  On Error Resume Next
  A = WSH.RegRead(R): If A > 0 Or Err.Number <> 0 Then WSH.RegWrite R, 0, "REG_DWORD"
  URL = Trim(CreateObject("htmlfile").ParentWindow.ClipboardData.GetData("text"))
  If A > 0 Then WSH.RegWrite R, A, "REG_DWORD"
  On Error Goto 0
End If

' Проверка пуст ли буфер, а также первые 4 символа на http/www.
' Если их нет, то вывод окна с указанным текстом и завершение скрипта:
Test = Left(URL, 4)
If Test = "" Or (Test <> "www." And Test <> "http") Then MsgBox "Буфер " &_
"обмена не содержит гиперссылки!", 4144, " Создание URL-ярлыка" : WScript.Quit

' Запись в переменную S заменяемых символов, а в R - номеров юникодных аналогов для ChrW:
S = Split(": ? * "" ; \ / | < >")
R = Array(-230,-225,-246,698,894,-24,-24,-24,706,707)

' Создание объекта IE с параметром для событий:
With WScript.CreateObject("InternetExplorer.Application", "IE_")
' Скрытие его окна, устанавка тихого режима, убор адресной строки,
' гл. меню, панели инструментов, строки состояния:
  .Visible = 0 : .Silent = 1 : .AddressBar = 0
  .MenuBar = 0 : .ToolBar = 0 : .StatusBar = 0
' Открытие URL без записи в историю и сохранения в кэш:
  .Navigate URL, 10
' Проверка в цикле по событию появления заголовка (не в виде ссылки):
  While IsEmpty(Title) Or Left(Title, 4) = "http" WScript.Sleep 20 :Wend
' С появлением останавливаем загрузку страницы, закрываем IE
  .Stop : .ExecWB 45, 2
End With

' Процедура, возвращающая в T, а после в Title заголовок без концевых пробелов:
Sub IE_TitleChange(T) Title = Trim(T) : End Sub

' Запись в FN заголовка с добавками и расширением:
FN = Title & " @ + .url"

' 10-кратный проход циклом с заменой в заголовке запрещённых в именах символов:
For i = 0 To 9 : FN = Replace(FN, S(i), ChrW(R(i))) : Next

Dim HTTP, Reg, URL1, Domain, FP, Pr, M, SCode, Icon, IName, FIcon
'Создание объектов WinHttpRequest, RegExp:
Set HTTP = CreateObject("WinHttp.WinHttpRequest.5.1")
Set Reg  = New RegExp : Reg.IgnoreCase = True
' Установка опций для правильного соединения:
HTTP.Option(4) = 13056 : HTTP.Option(6) = True
HTTP.Option(12) = True : HTTP.Option(14) = 5

' Вычленение с пом. рег. выраж. URL c доменом (URL1) и самого домена (Domain):
Reg.Pattern = "^((https?://www\.|https?://|www\.)([^/]+))/?.*"
With Reg.Execute(URL)(0)
  URL1 = .Submatches(0) : Domain = .Submatches(2)
End With

' Запись в FP полного пути к url-ярлыку:
FP = FSO.BuildPath(Dir, Year(Date) & "." & Right("0" & Month(Date),_
     2) & "." & Right("0" & Day(Date), 2) & " " & Domain & " " & FN)
' Если длина этого пути больше 259, то:
If Len(FP) > 259 Then
  Pr = "\\?\" ' в Pr заносится префикс \\?\
 ' если длина пути назначения меньше 260-ти, показываем сообщение с выбором обрезать/оставлять:
  If Len(Dir) < 260 Then
    M = MsgBox("Путь к ярлыку слишком длинный!" & vbCr & vbCr & "Да -" &_
    " оставить. Нет - обрезать справа.", 4132, " Создание URL-ярлыка")
    ' Если нажата кн. "Нет", то обрезаем до 259 символов:
    If M = 7 Then FP = Left(FSO.GetBaseName(FP), 255) & ".url"
  End If
End If

Connect URL1 ' соединение с сайтом:
' Вытащить из исходного кода страницы адрес иконки:
Reg.Pattern = ".* ?href=""?\.?\.?((|https?://)" &_
"[^ ]*?/?favicon[^\s""]*?\.ico(|\?v=[\w]+))[\s""]"
SCode = HTTP.ResponseText  ' запись исходного кода в SCode
HTTP.Abort ' обрыв соединения
If Reg.Test(SCode) Then ' если в нём есть favicon.ico
' Запись адреса иконки:
  Icon = Reg.Execute(SCode)(0).Submatches(0)
  If Left(Icon, 4) <> "http" Then ' если в нём нет http спереди
    ' Если слева у адреса //, то у URL1 остаётся только протокол:
    If Left(Icon, 2) = "//" Then URL1 = Left(URL1, InStr(URL1, "//") - 1)
    Icon = FSO.BuildPath(URL1 & "/", Icon) ' Запись полного URL иконки
  End If
' если нет, то запись URL favicon.ico из корня сайта в переменную Icon:
Else Icon = URL1 & "/favicon.ico" End If

' Если это иконка (и она существует по данному адресу), то:
If Connect(Icon) Then
  ' Запись в переменную полного имени иконки
  IName = Domain & " @favicon.ico"
  ' Запись в переменную полного локального пути для сохранения:
  Icon = Pr & FSO.BuildPath(Dir, IName)
  ' Если иконки с заданным именем в папке нет, то:
  If Not FSO.FileExists(Icon) Then
    ' происходит запись на диск в бинарном виде:
    With CreateObject("SAPI.SpFileStream")
      .Format.Type = 1 : .Open Icon, 3 : .Write HTTP.ResponseBody : .Close
    End With
  End If : HTTP.Abort ' обрыв соединения
  With CreateObject("WIA.ImageFile")
    ' Если настоящий тип - не ico, то выполняется конвертация в него:
    .LoadFile Icon : If LCase(.FileExtension) <> "ico" Then WSH.Run """" & nConv _
     & """ -quiet -out ico -overwrite -transparent 100 """ & Icon & """", 0, True
  End With
  ' Запись недостающей части в редакции url-файла, включая путь к иконке:
  FIcon = vbCrLf & "IconFile=%FaviconFolder%\" & IName & vbCrLf & "IconIndex=0"
End If

' Создание url-файла:
With FSO.CreateTextFile(Pr & FP, 1, 1)
  ' запись в него URL и ключей для иконки, если она была найдена:
  .Write "[InternetShortcut]" & vbCrLf & "URL=" & URL & FIcon : .Close
End With : WSH.SendKeys "^r" ' Обновляем окно для отображения новых файлов

Function Connect(URI)
' Открытие соединения с адресом иконки:
  HTTP.Open "GET", URI, false
  ' Отключение кэшируемых данных:
  HTTP.SetRequestHeader "Pragma", "no-cache"
  HTTP.SetRequestHeader "Cache-Control", "no-cache"
  ' Посылка пакетов:
  HTTP.Send
  ' Ожидание ответа в теч. макс. 5 сек:
  HTTP.WaitForResponse 5, True
  ' Запись типа файла потенциальной иконки
  Dim FT : FT = HTTP.GetResponseHeader("Content-Type")
  ' Передача функции булева значения соответствия типу иконки:
  Connect = Eval(Left(FT, 6) = "image/" And Right(FT, 4) = "icon")
End Function

2

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

Спасибо, щас протестировал скрипт работает, сохраняет ярлык и иконку, но в ярлыке нет имени иконки:


[InternetShortcut]
URL=http://favicon.ru/
IconFile=%FaviconFolder%\.ico
IconIndex=0

Насколько я посмотрел в коде, это пустая переменная Name.
В моем скрипте, который я писал на AHK был анализ страницы и путь к иконке брался из тега link "shortcut icon", ведь иконка не всегда может лежать в корне сайта.
Еще некоторые пожелания:
*в именах сайты без "www."
*чтобы скрипт мог брать адрес из параметра запуска

3

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

Исправил (кроме поиска иконки). C www. случайно вышло, не в той последовательности компоненты регулярки стояли.

upsi_daezium пишет:

ведь иконка не всегда может лежать в корне сайта.

Пару примеров хотелось бы.

4

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

Да, теперь имя ярлыка без www.
Но "IconFile=%FaviconFolder%\.ico" повторяется.

5

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

Не верю. Я проверял:

[InternetShortcut]
URL=http://forum.script-coding.com/
IconFile=%FaviconFolder%\forum.script-coding.com @favicon.ico
IconIndex=0

6

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

Извиняюсь, мой недосмотр, все работает.
Я протестировал на сайтах и вот что получилось:
http://xn----ctbtwbliac6kg.xn--p1ai/ (все Ок)
http://твоя-россия.рф/ (все Ок)
https://ru.wikipedia.org/wiki/%D0%97%D0%B0%D0%B3%D0%BB%D0%B0%D0%B2%D0%BD%D0%B0%D1%8F_%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0 (сохраняет только ярлык, без favicon)

7

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

Исправил.

8

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

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

9

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

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

P.S.: Ответ поздний, т.к. эти дни отсутствовала возможность в связи с отбытием.

10

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

Работа со скриптом.
Разобрался с передачей параметров, все отлично.
За все время использования попался пока только один сайт, где не сохранил иконку, это https://www.pochta.ru/ .
Можно ли, чтобы скрипт еще добавлял в начале имени файла ярлыка текущую дату в формате ГГММДД и пробел?

11

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

Насчёт почты. Сам ярлык создался или вообще ничего?
Дату, может, всё-таки в формате YYYY.MM.DD?

В общем, я пока поправил так, как вижу. Там посмотрим.

12 (изменено: upsi_daezium, 2016-09-27 00:22:35)

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

Ярлык создался, создалась и иконка, но сам файл как-бы пустой, открыть его не получилось.
Если вручную открыть https://www.pochta.ru/favicon.ico, то открывается пустой лист (у меня в хроме, во всяком случае).
Если открыть из исходника  <link href="https://www.pochta.ru/portal-theme/images/favicon.ico" rel="Shortcut Icon" />, то открывается правильная иконка.
Теперь по-поводу даты. Да, формат именно такой ГГММДД ("160924 ", с пробелом после даты).
Спасибо за изменения скрипта. Сейчас посмотрел его, кажется проблема в данном случае вот в чем, скрипт пытается сначала скачать из корня, если не выходит, то пытается выудить иконку регуляркой. А этот сайт возвращает иконку из корня, но она неправильная (формат не тот), скрипт ее скачивает и все. Может быть сделать приоритет чтобы брать из "shortcut icon"?
А вот сейчас подумал, примеры не приведу --- не помню, иногда иконку указывают с относительным путем, то есть это тоже придется учитывать.
Проблема с иконками оказалась несколько шире, чем мы ожидали.

13

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

ОК. С адресами решено. Но формат даты корявый. Ну, будет 161211 или 161117. И где тут что? Я бы оставил как есть, да и сепарация точками не помешает.

14

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

Спасибо Вам большое за проделанную работу! Скрипт работает, полет нормальный, отдельное спасибо за комменты, если что надо будет поменять, то смогу разобраться, где что, хотя в ближайшее  время  маловероятно, что мне это понадобится, настолько вы приблизились к идеалу. И еще спасибо за отличную обратную связь.
П.С.: По поводу даты, это у меня система хранения файлов такая.

15

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

Я бы пересмотрел алгоритм скачиванмя favicon.
https://www.inbox.lv/index?language=ru
https://www.instagram.com/vladimir_markoni/

16

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

Только не скачивания, а парсинга. Допилил.

17

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

Кстати говоря, есть ещё проблема, когда в код пихают другие форматы (png, gif) под видом ico. Пример. Конвертировать или оставить как есть?

18

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

Надо, что в windows ico формат отображался правильно, чтобы там иконка была.

19

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

upsi_daezium
Т.е. конвертировать? Я думал, что WIA.ImageProcess поддерживает ico, ан нет.
Тогда утилитой. Что берём? nConvert, IrfanView, Any2Icon?
Можно, конечно, попробовать через сервис, но сейчас лениво копаться.

20

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

nConvert, я пользуюсь XnView и мне нравится, думаю подойдет лучше всего.

21

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

Вообще-то нет. Лучше справляется convert от IM (очищает больше альфа-каналов, что может сокращать размер в неск. раз).
Дополнил пока c nConvert.

22

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

Можно без сторонних утилит через GDI+.

23

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

Это если на ASP.NET писать с системой Виста+ с FrameWork.
Поэтому где-нибудь на XP стороннего там будет много.


upsi_daezium
Так оставляем или на convert меняем? Чего отмалчиваемся?

24

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

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

25

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

upsi_daezium
В смысле "так и не заработал"? Он работал. Просто на днях они иконку убрали из корня. Поправил регулярку.
Но я спрашивал про преобразование, а не скачивание.

26

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

Не качает.
https://7bitcasino.com/en/

27

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

favicon-ico-32x32.ico?v=5d44538e

Ну, не знаю. Это же не favicon.ico в чистом виде.

Ладно, поправил выражение. Но что-то есть некоторые опасения по другим потенциалам. Посмотрим.

28

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

Почему? Там гиф.
Но для этого вы, как я понял, и взяли nconvert.

29

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

Да. Не в этом суть. А в самом названии файла. Вроде как о ...bla-bla... вариантах речь не велась.
Так мы сейчас вообще до favicon.png и иже с ними доползём..

30

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

Мне вообще не понятна задача, для чего gif замаскированый в ico конвертировать надо, а просто gif или png нет.
Это уже топикстартер должен объяснить.

31

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

Ну, логично же. Речь про favicon.ico, который в любом случае скачивается. А коли фейк попал на диск, то не должен висеть мёртвым грузом и быть сконвертированным в реальный ico.

32

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

Можно просто его стирать, так как он не формата ico, если таки нужны только чистые ico.
Или нужна только та иконка, которая называется favicon.ico, не беря во внимании, что внутри?
Или нужна любая иконка сайта, но сконвертируемая в ico?

33

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

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

favicon, если конечно, она в подходящем формате ico

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

34 (изменено: Malcev, 2016-10-07 05:13:46)

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

Вообще favicon - это общее название для иконки сайта.
Поэтому у меня и возникли вопросы.
А проверять ico это или не ico можно скачивая только первые байты файла.
Иконки должны начинаться с '0x00 0x00 0x01 0x00'.
А если нужно скачать любую иконку, то я бы скачивал пнг с помощью гугла и потом кодировал бы его в ico.
https://www.google.com/s2/favicons?doma … google.com

35

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

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

Про гугл не знал, что есть такая фича. Надо подумать.
Даже этот работает o_O: https://www.google.com/s2/favicons?domain=forum.teamspeak.com

36

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
WebRequest.Open("GET", "http://forum.script-coding.com/favicon.ico")
WebRequest.SetRequestHeader("Range", "bytes=0-3")
WebRequest.Send()
Body := WebRequest.ResponseBody
loop 4
   var .= "0x0" body[A_Index-1] " "
StringTrimRight, var, var, 1
msgbox "%var%"

37

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

Body := WebRequest.ResponseBody

Это и есть скачивание, только в память. Я имел в виду через поток. Если предположить, что файл (не иконка, а вообще) весит 10 Гб, например, то получение данных будет очень долгим.

38

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

Нужны именно ico-файлы.
Flasher последний вариант скрипта работает отлично, проверил на всех сайтах, с которых раньше не скачивались. Напишу, если попадется где не будет работать.

39

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

upsi_daezium
Гуд. Со скачиванием-то понятно. С выбором утилиты что?

40

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

Это и есть скачивание, только в память. Я имел в виду через поток. Если предположить, что файл (не иконка, а вообще) весит 10 Гб, например, то получение данных будет очень долгим.

Так за это отвечает:

WebRequest.SetRequestHeader("Range", "bytes=0-3")

41

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

Flasher а что с утилитой?? Все работает, иконки сохраняет, с прозрачностью все ок. Я пользуюсь XnView из этого же пакета и "доволен как слон".
Хотите предложить "лучшее --- враг хорошего"?)
Хотя, можно придраться к тому, что иконки идут одного заданного размера (в ico файле их может быть много, разных размеров), если сделать, например, огромные значки вида папок, а сама иконка маленькая (open-tor.org), то она смотрится ужасно. Это скорее из области дурацкого перфекционизма.
Теперешнее положение дел меня вполне устраивает, говоря по-простому.
Спасибо вам за ваш труд, сам бы я, конечно, не смог бы написать нечто подобное еще очень долго.
Пиво с меня, если вы с Питера)

42

Re: VBS: Создание URL-ярлыка по ссылке с записью скачиваемого favicon.ico

upsi_daezium
Как что? Я же объяснял.
Можно взять любой прозрачный 256x256.ico и сравнить результаты команд:

nconvert.exe -quiet -out ico -transparent 100 256x256.ico
convert.exe 256x256.ico -quiet -transparent 100 256x256_1.ico

Насчёт размеров догадывался, что будет несмотрибельно на эскизах и крупных значках, но так поставлена задача.
Я же размеры не трогаю. Это ico-исходники. Создавать же группу значков в ico можно только при наличии больших favicon.png, которых может и не оказаться вовсе. Про нюансы добавочного парсинга уже выше писал.

Пожалуйста, конечно.
Не, я не с Питера, я из Москвы.