2009-11-11 2 views
5

мое приложение включает в себя исполняемый файл самообновления, который используется для обновления приложения.Запись доступа к папке Program Files

Одним из первых шагов обновления выполняет, чтобы проверить, что у него есть разрешение на запись в папку приложения

IPermission perm = new FileIOPermission(FileIOPermissionAccess.AllAccess, _localApplicationCodebase);

 if (!SecurityManager.IsGranted(perm)) 
     { 
      OnProgressChanged("Security Permission Not Granted \n The updater does not have read/write access to the application's files (" + 
           _localApplicationCodebase + ")",MessageTypes.Error); 
      return false; 
     } 

     OnProgressChanged("Updater have read/write access to local application files at " + _localApplicationCodebase); 
     return true; 

При выполнении под Win7/Vista, этот код прохода (это означает, что в соответствии с CAS, код имеет доступ на запись), однако, когда я пытаюсь записать файлы, у меня есть Access Denied (и я подтвердил, что файлы НЕ используются)

Я понимаю, что Vista/Win7 UAC мешает пользователям записывая файлы в папки программных файлов. Однако то, что я не понимаю, почему разрешение выдается, если на самом деле это не

С уважением,

Eric Girard

PS: Если я запускаю тот же код, используя «Run As Administrator» , он отлично работает

+0

ли приложение пытается перезаписать себя в то время как он работает? –

+0

Как я уже писал, нет, обновление не является другим .exe, так как никаких зависимостей от какой-либо локальной dll –

+0

Я считаю, что если вы не являетесь администратором, вам не разрешается писать какой-либо исполняемый файл в любых программных файлах вложенная папка. Ваш updater пытается написать исполняемые файлы? –

ответ

4

Лучший способ написать автообновление - иметь вторичное приложение. Первая программа вызывает вторую с повышенными привилегиями, запрашивая UAC. Затем второе приложение может установить исправления.

+0

Или сделайте вызов приложения снова с повышенными привилегиями. Если у него нет этих привилегий, он должен снова запускаться, запрашивая UAC для получения дополнительных прав ... –

+0

Это именно то, что я делаю прямо сейчас, но это все еще не отвечает на мой вопрос: почему SecurityManager. IsGranted возвращает TRUE для этой папки, если на самом деле она не предоставляется для папки программных файлов? –

4

Важная информация о UAC заключается в том, что по умолчанию не работает с правами администратора и, следовательно, не может записываться в каталог Program Files. Даже если вы вошли в систему как администратор, приложения запускаются со стандартными пользовательскими привилегиями.

Существует два способа обойти это. Вы можете запустить приложение с помощью пункта меню «Запуск от имени администратора». Но это зависит от того, что пользователь что-то помнит. Лучше было embed a manifest в ваш исполняемый файл, который запрашивает права администратора. В манифесте установите requestExecutionLevel в requireAdministrator. Это заставит UAC запрашивать у пользователя учетные данные администратора сразу после запуска приложения.

Как сказал Даниэль, лучшим решением является включение функций обновления в отдельное приложение. Ваше основное приложение будет иметь манифест, который устанавливает requestExecutionLevel в «asInvoker» и ваше приложение для обновления с запросом «requireAdministrator». Основное приложение может работать со стандартными привилегиями. Но когда обновление должно произойти, используйте Process.Start для запуска приложения-обновления, которое требует от пользователя ввода учетных данных администратора.

1

Я не уверен, что это то, что вы пытаетесь сделать, но я нашел это сообщение полезным. Включенный код позволит вам определить, работает ли приложение на Vista, если UAC включен и если пользователь поднят.

http://www.itwriting.com/blog/198-c-code-to-detect-uac-elevation-on-vista.html

перезапустите приложение с RunAs, чтобы позволить пользователю права возвысить

ProcessStartInfo processInfo = new ProcessStartInfo(); 
processInfo.Verb = "runas"; 
processInfo.FileName = Application.ExecutablePath; 
Process.Start(processInfo);