Comments 30
А ещё советую взглянуть в сторону Torrent-клиента. Можно использовать для более быстрого скачивания обновлений — Клиенты будут делиться друг с другом, снижая нагрузку на ваши сервера.
Я-же писал более сложный алгоритм создания «Патчей»: Архивов, содержащих в себе .diff файлы (для текста и конфигов) и кое-что аналогичное для бинарных данных. Благо файлы на клиенте хранились не единым архивом, а практически в открытую.
Бонусом была кнопочка «Перепроверить всё», заставляющая клиента просчитать CRC для всех файлов и сравнить с данными сервера (И скачивать, в случае различий).
А насколько имеет смысл заморачиваться с diff'ами ради текста и конфигов (я так понимаю ваших, а не тех, что бы изменены пользователем)? Обычно размер подобных файлов достаточно мал и можно скачать целиком
Но основная причина — это механизм обновления бинарных файлов кусками, который использовал практически туже механику, что и diff-файлы.
Я както натыкался на «обновлялку», внутри которой был завернут GIT-клиент… а измененное докачивало лиш измененные части, а не файл целиком).
Но основная причина — это механизм обновления бинарных файлов кусками, который использовал практически туже механику, что и diff-файлы.
Я надеюсь, вы в курсе, что Git как раз не докачивает диффы, а делает снепшоты файлов?
На ней например DriverPack Solution работает.
С тех пор, как я узнал об SVN, так и не понял, почему люди не встраивают vcs, а продолжают лепить свои поделки.
ещё одна утилита? Всё просто: для обновления файлов игры нужно выполняться с правами администратора.
Программу можно научить перезапускать себя с запросом UAC
void execAdmin(const wchar_t *path, const wchar_t *params)
{
SHELLEXECUTEINFOW sei = {0};
sei.cbSize = sizeof (sei);
sei.fMask = SEE_MASK_NOCLOSEPROCESS;
sei.hwnd = 0;
sei.lpVerb = L"runas";
sei.lpFile = path;
sei.lpParameters = params;
sei.lpDirectory = 0;
sei.nShow = SW_SHOW;
sei.hInstApp = 0;
if (ShellExecuteExW (&sei))
{
WaitForSingleObject (sei.hProcess, INFINITE);
CloseHandle (sei.hProcess);
}
}
bool isAdmin()
{
BOOL fRet = FALSE;
HANDLE hToken = NULL;
if( OpenProcessToken( GetCurrentProcess( ),TOKEN_QUERY,&hToken ) ) {
TOKEN_ELEVATION Elevation;
DWORD cbSize = sizeof( TOKEN_ELEVATION );
if( GetTokenInformation( hToken, TokenElevation, &Elevation, sizeof( Elevation ), &cbSize ) ) {
fRet = Elevation.TokenIsElevated;
}
}
if( hToken ) {
CloseHandle( hToken );
}
return fRet;
}
В Винде, по любому, можно провернуть туже операцию. Просто это чуть сложнее.
Причина не в этом. Никсовые файловые системы основаны на inode — запись в каталоге это отдельная сущность от всех прочих данных и метаданных файла. Операция удаления файла удаляет только первую часть, а inode отстается жить, пока на файл есть хотя бы ещё одна ссылка. Открытый файл тоже считается ссылкой. В Винде это не так.
А старый либо поставить в очередь на удаление при следующем запуске винды либо удалить из нового экзешника.
Это не отменяет же необходимость получения повышенных прав, отдельный апдейтер нужен прежде всего именно для этого. Но есть и другие причины:
- так проще переносить апдейтер из проекта в проект;
- юзеру удобно обновлять игру вручную, достаточно просто запустить GetNewVersion.exe — это весьма полезно на этапе бета-теста, когда в игре часто выкладываются необязательные обновления (багофиксы), и людям, которые ждут эти фиксы, не нужно переустанавливать итгру целиком;
- у меня в апдейтере GUI сделан на VCL, и мне не хотелось добавлять в игру зависимость от этих библиотек;
- апдейтер один раз написал, подписал и забыл — больше не нужен сертификат подписи кода (у меня как-раз истёк его срок действия). А игру можно продолжать обновлять :)
CredUIPromptForCredentials() или CredUIPromptForWindowsCredentials()
LogonUser()
ImpersonateLoggedOnUser()
RevertToSelf()
CloseHandle()
О запуске нового процесса здесь речи не идет. Магия заключается в том, что полученный в результате LogonUser токен может быть использован не только для запуска процесса но и для процесса имперсонации в текущем контексте выполнения и защиты процесса.
Этот механизм чаще я применял в ASP.NET в случае если web приложение работает от одного пользователя, а действия в БД типа MS SQL нужно выполнить от имени другого, который работает с приложением на данный момент.
.net пример и msdn
Как сделать автоматическое обновление клиента онлайн-игры