вторник, 22 февраля 2011 г.

Запуск процесса с повышенным уровнем привилегий

Это, наверное, и так все знают, но я забываю, поэтому запишу тут. Если нужно запустить процесс с повышением уровня привилегий (run elevated process), то можно применить следующий подход: берем структуру SHELLEXECUTEINFO, заполняем как обычно, потом добавляем опцию lpVerb как показано в примере:
SHELLEXECUTEINFO shExecInfo;
shExecInfo.cbSize = sizeof(shExecInfo);
shExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
shExecInfo.hwnd = NULL;
shExecInfo.lpVerb = L"runas"; // start with elevated privileges
shExecInfo.lpFile = filename.c_str();
shExecInfo.lpParameters = args.c_str();
shExecInfo.lpDirectory = NULL;
shExecInfo.nShow = SW_SHOW;
shExecInfo.hInstApp = NULL;
Затем запускаем через ShellExecuteEx:
if ( TRUE == ShellExecuteEx(&shExecInfo) ) {
  WaitForSingleObject( shExecInfo.hProcess, PROPER_TIMEOUT );
  CloseHandle( shExecInfo.hProcess );
}
Это все. Если на компьютере включен UAC, то появится диалог с вопросом пользователю — можно ли. Если пользователь одобрит, то ваш процесс запустится в God mode.

четверг, 17 февраля 2011 г.

Развлечение на Bash. Финал.

Продолжая небольшой эксперимент на Bash, оформил предыдущие скрипты в виде одного. Добавлено удаление картинок, которые создались с ошибкой. Также, обратите внимание на наличие функции, которая принимает аргумент (имя файла) и возвращает результат.

Скрипт выложен на https://github.com/jia3ep/samsungthumbnailer и развиваться будет там.

воскресенье, 13 февраля 2011 г.

Развлечение на Bash

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

Итак, задача нагенерить jpeg-файлов. Особенность в том, что расширение jpeg-файла должно быть размером соответсвующего ему видеофайла, который поделили на 1000. Если размер больше 4Гб, то надо сначала вычесть 232 из размера, а потом делить. Думал, писать программку на C++, но подумалось,что скриптовые языки тоже не зря придумали. Результатом стали два скрипта на bash, которые можно видеть в конце.

Для геренации превьюшек существует небольшой опенсорс проект — FFMpegThumbnailer. Интересен он тем, что там реализован алгоритм выбора удачного кадра. В отличие от тех сложных идей, с которыми приходилось встречаться ранее, вроде поиска лица, кожи и т.п., тут реализована очень простая идея. Считается гистограмма по сотне кадров и усредняется. Потом выбирается кадр, гистограмма которого наиболее близка к средней. Работает алгоритм на удивление хорошо.

Скрипт генерации одной превьюшки:
#!/bin/bash
# gen_th.sh

FILENAME=$1
# get file size in bytes
printf "$FILENAME\t"
FILESIZE=$(stat -c%s "$FILENAME" 2>/dev/null)
if [ $? -ne 0 ] ; then
 echo "[FAIL]" # no file or access denied
 exit 1
fi

# generate file extension, so Samsung TV could use thumbnail
if [ $FILESIZE -lt 4294967296 ] ; then
 EXT=$(( $FILESIZE / 1000 ))
else
 EXT=$(( ($FILESIZE - 4294967296) / 1000))
fi


NEWFN="${FILENAME%.*}.$EXT"
if [ -f "$NEWFN" ] ; then
 echo "[SKIP]" # already exist
 exit 3
else
 ffmpegthumbnailer -s230 -cjpeg -i"$FILENAME" -o"$NEWFN" 2>/dev/null
 if [ $? -eq 0 ] ; then
  echo "[OK]"
  exit 0
 else
  echo "[FAIL]"
  exit 1
 fi
fi

Генерация сразу для кучи файлов рекурсивно (используется предыдущий):
#!/bin/bash
# gen_all.sh

# Absolute path to this script. /home/user/bin/foo.sh
SCRIPT=$(readlink -f "$0")
# Absolute path this script is in. /home/user/bin
SCRIPTPATH=`dirname "$SCRIPT"`

FAILED=0
OK=0
SKIPPED=0
count=0

# set custom delimiter for the strings
IFS=$'\n'

# process each file
for NAME in $(find $1/ -type f -regex ".*\.\(avi\|mkv\|ts\)$")
do
 "$SCRIPTPATH/gen_th.sh" "$NAME"
 ecode=$? # keep exit code here because every command will change $?
 if [ "${ecode}" -eq "1" ] ; then let "FAILED+=1"; fi
 if [ "${ecode}" -eq "0" ] ; then let "OK+=1"; fi
 if [ "${ecode}" -eq "3" ] ; then let "SKIPPED+=1"; fi
 let "count+=1"
done

# display results
echo "Total files processed: $count"
echo "Skipped: $SKIPPED"
echo "Failed: $FAILED"
echo "Images generated: $OK"

Все исходные коды проекта доступны на GitHub.