История

Цель
Реализовать идею, затратив при этом как можно меньше «ресурсов» на реализацию и сделать так чтобы процесс от создания скриншота до замены обоев происходил незаметно.
Используемые средства
- PhantomJS — для получения скриншотов с веб ресурсов
- NConvert — для преобразования картинок в различные форматы
- Wallpaper — для обновления обоев в Windows Vista и 7
- VBScript — для выполнения всех необходимых команд
- Планировщик заданий Windows — для регулярного обновления обоев
Реализация
Первым делом скачиваем свежие версии PhantomJS, NConvert и Wallpaper.
Увы архив с файлом «wallpaper.exe» не доступен, поэтому его можно скачать из архива с исходниками к статье, ссылка на который будет опубликована в конце.
На момент написания статьи использовались PhantomJS 1.3.0 Windows (Static build) и NConvert v5.91. Затем создаем папку «meteo_wall», в ней создаем подпапку «tools». Переходим в эту подпапку и распаковываем содержание архива «PhantomJS» в одноименную папку. Так же в папку «tools» помещаем NConvert и wallpaper.exe. Далее необходимо будет скопировать из папки примеров файл «rasterize.js» и поместить его в папку «tools». Немного подправим файл «rasterize.js» для того, чтобы можно было указывать необходимое расширение скриншотов.
var page = new WebPage(),
address, output, size;
if (phantom.args.length < 2 || phantom.args.length > 3) {
console.log('Usage: rasterize.js URL filename [paperwidth*paperheight|paperformat]');
console.log(' paper (pdf output) examples: "5in*7.5in", "10cm*20cm", "A4", "Letter"');
phantom.exit();
} else {
address = phantom.args[0];
output = phantom.args[1];
page.viewportSize = { width: 600, height: 600 };
if (phantom.args.length === 3 && phantom.args[1].substr(-4) === ".pdf") {
size = phantom.args[2].split('*');
page.paperSize = size.length === 2 ? { width: size[0], height: size[1], border: '0px' }
: { format: phantom.args[2], orientation: 'portrait', border: '1cm' };
}/* xrays add */
else if(phantom.args.length === 3){
size = phantom.args[2].split('*');
page.viewportSize = { width: size[0], height: size[1] };
};/* end */
page.open(address, function (status) {
if (status !== 'success') {
console.log('Unable to load the address!');
} else {
window.setTimeout(function () {
page.render(output);
phantom.exit();
}, 200);
}
});
}
После чего можно приступать к написанию VBScript'a. Создаем файл «wallpaper.vbs» в папке «tools» и для начала описываем в нем необходимые и заполняем важные переменные:
Dim WshShell
Set WshShell = WScript.CreateObject("Wscript.Shell")
Dim url, history, logon
' заполняем важные переменные
url = "http://www.artmeteo.ru/4335/" ' ссылка на город
history = 1 ' оставлять загруженные ранее картинки
logon = 1 ' изменять картинку в экран приветствия Windows
Признаюсь честно, до этого я не писал код на VBScript. Для того, чтобы получать скриншоты автоматически необходимо знать разрешение экрана:
' получаем расширение экрана
Dim obj, monSize
Set obj = CreateObject("htmlfile")
monSize = obj.parentWindow.screen.width & "*" & obj.parentWindow.screen.height
Далее:
' получаем необходимые пути
' получаем необходимые пути
Dim toolsPath, path
Set obj = CreateObject("Scripting.FileSystemObject") ' Получаем доступ к обьекту obj
toolsPath = obj.GetParentFolderName(WScript.ScriptFullName) & "\" ' путь до папки со скриптом
path = obj.GetParentFolderName(toolsPath) & "\" ' путь до главной папки
' формируем необходимые пути и загружаем скриншот сайта
Dim phantom, bmpname
phantom = toolsPath&"phantomjs\" ' путь до phantomjs
bmpname = path&"url.bmp " ' имя для bmp файла
WshShell.Run phantom & "phantomjs.exe " & toolsPath & "rasterize.js " & url & " " & bmpname & monSize, 0, True ' скачиваем картинку с сайта
Примечании: в конце последней строки используются параметры
0, True
необходимые для того, чтобы код выполнился в фоне и дальнейшие команды, описанные в скрипте, ожидали выполнения этого кода. Как можно заметить, то скриншот сохраняется в формате bmp, сделано это потому что версии ОС Windows младше Vista плохо воспринимают обои в другом формате. Далее определяем версию ОС:
Dim OSType
OSType = Left(Trim(WshShell.RegRead("HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\CurrentVersion")),1) ' определяем версию windows
Dim convert, n, time, jpgname, wallpaper
Так как скрипт должен быть максимально универсальным, но с разными версиями ОС нужно тоже считаться, то для начала описываем код для Windows Vista и 7:
If OSType>5 Then ' если это Windows Vista или Windows 7
' преобразование из bmp в jpg
Dim quality
quality = 95 ' качество для jpg картинки
convert = toolsPath & "nconvert.exe -out jpeg -q " & quality & " -i -overwrite -o "
n = Now ' используем для сокращения глобальной переменной
time = Right("00" & Day(n), 2) & "-" & Right("00" & Month(n), 2) & "-" & Right("00" & Year(n), 2) & "_" & Right("00" & Hour(n), 2) & "_" & Right("00" & Minute(n), 2) & "_" & Right("00" & Second(n), 2) ' создаем имя
jpgname = path & time & ".jpg " ' имя для jpg файла
WshShell.Run convert & jpgname & bmpname, 0, True ' преобразуем из bmp в jpeg
' изменяем фон на текущую картинку
wallpaper = WshShell.ExpandEnvironmentStrings("%APPDATA%") & "\Microsoft\Windows\Themes\TranscodedWallpaper.jpg" ' путь до обоев
obj.CopyFile jpgname, wallpaper ' копируем jpg картинку в станд.папку для обоев
WshShell.RegWrite "HKCU\Control Panel\Desktop\Wallpaper", wallpaper ' изменяем запись в реестре о пути до фона рабочего стола
' картинка для logon
Dim logonname
logonname = WshShell.ExpandEnvironmentStrings("%windir%") & "\System32\oobe\info\backgrounds\backgroundDefault.jpg " ' путь до logon картинки
If logon = 1 Then ' если нужно изменить logon
Dim logonconvert, goodlogon
Set file = obj.GetFile(jpgname) ' получаем инфу о картинке для logon
If Round(file.size/1024) < 256 Then ' если картинка уже < 256, то продолжаем без подбора качества
goodlogon = 1
obj.CopyFile jpgname, logonname
Else
goodlogon = 0
quality = quality - 3
End If
' подбираем качество картинки для logon
While goodlogon = 0
logonconvert = toolsPath & "nconvert.exe -out jpeg -q " & quality & " -i -overwrite -o " ' -canvas 1280 800 top-left
WshShell.Run logonconvert & logonname & bmpname, 0, True
Set file = obj.GetFile(logonname) ' получаем инфу о картинке для logon
If Round(file.size/1024) < 256 Then ' если размер < 256 Kb, то переходим дальше
goodlogon = 1
Else
quality = quality - 3 ' иначе уменьшаем качество картинки
End If
Wend
WshShell.RegWrite "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI\Background\OEMBackground", 1, "REG_DWORD"
Else
If obj.FileExists(logonname) Then
obj.DeleteFile logonname, True ' удаляем logon картинку, чтоб вернуть стандартную
End If
End If
If history = 0 Then ' если не нужно сохранять историю картинок, то удаляем jpg картинку
obj.DeleteFile jpgname, True
End If
WshShell.Run toolsPath & "wallpaper.exe", 0, True ' даем Windows понять что пора обновить обои
Можно заметить, что в этом коде происходит изменение logon картинки(картинка экрана приветствия), к которой применяются требования Windows. Суть этих требований заключается в том, что файл не может быть больше 256 Кб, поэтому происходит запуск цикла по уменьшению качества картинки, пока не будет достигнут допустимый порог ограничения.
Теперь пришёл черед описать код для младших версий ОС Windows:
Else ' если это младшие версии Windows
' изменяем фон на текущую картинку
wallpaper = WshShell.ExpandEnvironmentStrings("%appdata%") & "\Wallpaper.bmp" ' путь до обоев
obj.CopyFile bmpname, wallpaper ' копируем bmp картинку в станд.папку для обоев
WshShell.RegWrite "HKCU\Control Panel\Desktop\Wallpaper", wallpaper ' изменяем запись в реестре о пути до фона рабочего стола
' картинка для logon
Dim Background, Winlogon
If logon = 1 Then ' если нужно изменить logon
Background = 1
Winlogon = 0
WshShell.RegWrite "HKEY_USERS\.DEFAULT\Control Panel\Desktop\TileWallpaper", 1, "REG_SZ" ' Значение: (0 = по умолчанию; 1 = плитка (замостить))
Else
Background = 0
wallpaper = ""
Winlogon = 1
End If
WshShell.RegWrite "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI\Background\OEMBackground", Background, "REG_DWORD" ' изменяем состояние исользования стандартной logon картинки
WshShell.RegWrite "HKEY_USERS\.DEFAULT\Control Panel\Desktop\Wallpaper", wallpaper, "REG_SZ"' изменяем запись в реестре о пути до logon картинки
' WshShell.RegWrite "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\LogonType", Winlogon, "REG_DWORD" ' 1 - используется страница приветствия, 0 - используется классический вход в систему
If history = 1 Then ' если нужно сохранять историю картинок, то удаляем преобразуем картинку из bmp в jpg (95% качество)
convert = toolsPath & "nconvert.exe -out jpeg -q 95 -overwrite -o "
n = Now
time = Right("00" & Day(n), 2) & "-" & Right("00" & Month(n), 2) & "-" & Right("00" & Year(n), 2) & "_" & Right("00" & Hour(n), 2) & "_" & Right("00" & Minute(n), 2) & "_" & Right("00" & Second(n), 2) ' создаем имя
jpgname = path & time & ".jpg "
WshShell.Run convert & jpgname & bmpname, 0, True ' из bmp в jpg
End If
WshShell.Run "%windir%\System32\RUNDLL32.EXE user32.dll,UpdatePerUserSystemParameters", 0, True ' даем винде понять что пора обновить обои
End If
Заключительные «окорды» скрипта:
obj.DeleteFile bmpname, True ' удаляем bmp картинку
Set WshShell = Nothing
На этом написания скрипта закончено. Автоматическое выполнение скрипта, например каждые 5 минут, сделаем, воспользовавшись встроенным планировщиком заданий Windows. Для этого создаем новое задание и указываем в качестве запускаемой программы путь до скрипта «wallpaper.vbs», а так же не забываем в свойствах для срабатывания триггера выбрать ежедневно и повтор каждые 5 минут.
Итоги
Работа скрипта проверена на 2 компьютерах с Windows 7, на одном с Windows 2003 Server и на одном с Windows XP. Для того чтобы в Windows XP были видны изменения экрана приветствия необходимо либо в «Панель управления -> Учетные записи пользователей -> Изменения входа пользователей в систему» убрать галочку с пункта «Использовать страницу приветствия», либо раскомментировать 100 строку в исходнике скрипта. Исходники скрипта, со всем дополнительным софтом можно забрать от сюда.
Обновления
Появилась возможность проверить работу скрипта на ещё одном компьютере с Windows 7, но удачный запуск не увенчался успехом. Проблема заключалась в том, что появлялась ошибка об отсутствии пути до файла, в котором хранится картинка экрана приветствия. Опытным путем было найдено решение, которое заключается либо в создании вручную следующего пути
"%windir%\System32\oobe\info\backgrounds\"
, либо в изменении параметров контроля учетных записей(UAC) до самого низкого, с последующей перезагрузкой компьютера и обновлением скрипта, который можно скачать здесь.