Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2010.09.26;
Скачать: [xml.tar.bz2];

Вниз

Файлы в Windows 7   Найти похожие ветки 

 
AK-47   (2010-06-23 10:21) [0]

У меня возникла проблема с использованием программ в Windows7. Файлы в каталоге "Programm Files" меняются независимо для разных пользователей, то есть у одного пользователя поменялся какой-нибудь файл, у другого остался старый.
Вот, что я нашел по этому поводу в интернете:

С появлением Windows Vista/Windows 7 изменились некоторые принципы и правила программирования, которые необходимо знать программисту.

Очень многие программы по-прежнему копируют свои файлы в папки Program
Files, Windows или в корень системного диска (обычно диск C:). Также программы вносят изменения в реестр, используя ветку HKLM/Software. Но в Windows 7 возникает одна проблема: файлы или значения параметров в реестре не создаются или не обновляются. В чем дело?

Итак, обычные симптомы проблем:

   * ваша программа пытается писать в указанных папках или ветке реестра, но файлы там не появляются.
   * вы переключаетесь на другую учетную запись и ваше приложение не может найти файлы, записанные в папках Program Files, Windows или в корне системного диска
   * После отключения или включения User Account Control (UAC) ваше приложение не может найти файлы в папках Program Files или Windows

Эти проблемы возникают из-за виртуализации (UAC Virtualization). До выхода Windows Vista, обычно все работали с правами администратора и программы могли свободно переписывать системные файлы, значения в реестре и т.д. В Windows Vista принцип работы был изменен, и обычный пользователь с правами админа фактически работал уже с правами стандартного пользователя. Как это выглядело на практике.

Предположим, ваше приложение пытается внести изменения в файле C:\Program
Files\Contoso\Settings.ini, но обычный пользователь не имеет доступа к папке Program Files, и операция записи перенаправляется в файл C:\Users\Username\AppData\Local\VirtualStore\Program
Files\Contoso\settings.ini. Аналогично, если приложение пытается записать что-то в разделе реестра HKEY_LOCAL_MACHINE\Software\Contoso\, то запись перенаправляется в ветку HKEY_CURRENT_USER\Software\Classes\VirtualStore\MACHINE\Software\Contoso или
HKEY_USERS\UserSID_Classes\VirtualStore\Machine\Software\Contoso.

Как правильно вести себя в этих случаях? Виртуализация используется для совместимости с уже существующими программами. Если вы создаете свои новые программы, совместимые с  Windows 7, то вам следует избегать подобных случаев. Обязательно протестируйте свои программы под правами обычного пользователя, а не под правами администратора.

Если у вас уже есть старая программа, то измените ее в соответствии с новыми требованиями. Вам необходимо:

   * Удостовериться, что приложение сохраняет данные  только в пользовательских папках %alluserprofile% или в папках, имеющих полный доступ (настройки ACL).
   * Определить известную стандартную папку, в которую вы хотите записать данные. Данные, которыми будут пользоваться все пользователи, нужно записывать в соответствующие папки, доступные для всех. Данные для отдельного пользователя записываются в папку, доступную только этому пользователю.
   * Данные (логи, настройки, сохранение в играх) нужно сохранять в папку Documents
     (или указанную пользователем папку)
   * Не задавайте в коде жестко прописанные пути к файлам и папкам. Используйте стандартные функции для определения корректных путей к папке Windows и других известных папок: функция System.Environment.GetFolderPath позволяет получить пути к файлам Environment.SpecialFolder.CommonApplicationData
     Environment.SpecialFolder.LocalApplicationData
     Environment.SpecialFolder.ApplicationData.
     Также можно использовать следующие переменные среды:
     %ALLUSERSPROFILE%
     %LOCALAPPDATA%
     %APPDATA%

Используя Проводник, найдите ваши пропавшие файлы в папке VirtualStore, которая хранит перенаправленные файлы, которые вы пытались записать в запрещенные места.
Ищите эту папку в %localappdata%\VirtualStore. Если вы не можете найти эту папку, то попробуйте команду dir %userprofile%\yourfile.dat /s /a в командной строке (обычно папка находится в C:\Users\user name\AppData\Local\VirtualStore). Также файлы могут находиться в подпапках виртуализированной папки. Если там нашлись ваши файлы, то это служит лишним доказательством, что сработал механизм UAC virtualization и вам нужно принимать меры по исправлению ситуации.


Как программно сделать, чтобы каталог стал общим для всех пользователей?


 
RWolf ©   (2010-06-23 12:08) [1]

Может, всё-таки лучше использовать специально выделенные для этого каталоги? %AllUsersProfile%, %PROGRAMDATA%, %TEMP%?


 
Dennis I. Komarov ©   (2010-06-23 12:17) [2]


> Как программно сделать, чтобы каталог стал общим для всех
> пользователей?

Мелкомягкие понабрали по объявлением, а терь проги крутых перцов не работают на этих недоосях...


 
Демо ©   (2010-06-23 15:04) [3]


> а терь проги крутых перцов не работают на этих недоосях.
> ..


Скорее некоторые недопрограммеры не разбираются в операционных системах.


 
KilkennyCat ©   (2010-06-23 17:15) [4]


> * Не задавайте в коде жестко прописанные пути к файлам и
> папкам. Используйте стандартные функции для определения
> корректных путей к папке Windows и других известных папок:
>  функция System.Environment.GetFolderPath позволяет получить
> пути к файлам Environment.SpecialFolder.CommonApplicationData
>      Environment.SpecialFolder.LocalApplicationData
>      Environment.SpecialFolder.ApplicationData.
>      Также можно использовать следующие переменные среды:
>
>      %ALLUSERSPROFILE%
>      %LOCALAPPDATA%
>      %APPDATA%

это правило было всегда, вот только его используют не все, так что семерка не виноватая.


 
Кто б сомневался ©   (2010-06-23 21:44) [5]

Ну что тут можно сказать............... Не используйте тэг "код"!!! Невозможно же читать текст с таким расстояниями между буквами!


 
AK-47   (2010-06-28 17:18) [6]

Если кому-то интересно, то вот код для работы с правами доступа:


uses
 Windows, SysUtils, AclAPI, AccCtrl, ComObj, Forms;

const
 cAllUsers = "S-1-1-0"; // S-R-I-S-S пользователя "Все"

 // Следующие константы взяты из модуля JwaWinNT
 STANDARD_RIGHTS_WRITE    = READ_CONTROL;
 FILE_READ_DATA           = $0001;
 FILE_WRITE_DATA          = $0002;
 FILE_APPEND_DATA         = $0004;
 FILE_READ_EA             = $0008;
 FILE_WRITE_EA            = $0010;
 FILE_READ_ATTRIBUTES     = $0080;
 FILE_WRITE_ATTRIBUTES    = $0100;
 FILE_EXECUTE             = $0020;

 FILE_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED or SYNCHRONIZE or $1FF;

 FILE_GENERIC_READ = (STANDARD_RIGHTS_READ or FILE_READ_DATA or
   FILE_READ_ATTRIBUTES or FILE_READ_EA or SYNCHRONIZE);

 FILE_GENERIC_WRITE = (STANDARD_RIGHTS_WRITE or FILE_WRITE_DATA or
   FILE_WRITE_ATTRIBUTES or FILE_WRITE_EA or FILE_APPEND_DATA or SYNCHRONIZE);

 FILE_GENERIC_EXECUTE = (STANDARD_RIGHTS_EXECUTE or FILE_READ_ATTRIBUTES or
   FILE_EXECUTE or SYNCHRONIZE);

 MainFileRights = FILE_GENERIC_READ or FILE_GENERIC_WRITE or FILE_GENERIC_EXECUTE;

// Проверяет имеет ли диск на котором запущена программа файловую систему NTFS
function IsNTFS: Boolean;
// Проверяет есть ли у пользователя "Все" права на запись в указанный каталог
function IsCanWriteForAllUsers(const aDir: String): Boolean;
// Делает, чтобы у пользователя "Все" были права на запись
function SetDirSecurityForAllUsers(const aDir: String): Boolean;
// Возвращает имя пользователя "Все" или другой аналог названия этого пользователя в системе
function GetAllUsersName: String;

implementation

// Проверяет может ли указанный пользователь писать в указанный каталог
function IsCanWrite(const aDir: String; aSID: PSID): Boolean;
 // Проверка на то, что A входит в B
 function BIncludeA(const A, B: DWORD): Boolean;
 var
   i: Integer;
   vCurBit: DWORD;
 begin
   Result := True;
   for i := 0 to 31 do
   begin
     vCurBit := 1 shl i;
     if (A and vCurBit) > 0 then
     begin
       if (B And vCurBit) = 0 then
       begin
         Result := False;
         Exit;
       end;
     end;
   end;
 end;

type
 ACL_SIZE_INFORMATION = record
   AceCount: DWORD;
   AclBytesInUse: DWORD;
   AclBytesFree: DWORD;
 end;

 _ACE_HEADER = record
   AceType : BYTE;
   AceFlags : BYTE;
   AceSize : WORD;
 end;

 ACCESS_ACE = record
   Header : _ACE_HEADER;
   Mask : ACCESS_MASK;
   SidStart : DWORD;
 end;

var
 i: Integer;
 pDACL: PACL;
 pSD: PSECURITY_DESCRIPTOR;
 vRes: Cardinal;
 aclInfo: ACL_SIZE_INFORMATION;
 ace: ^ACCESS_ACE;
 SID: PSID;
begin
 Result := False;
 // Получаем текущую информацию о правах доступа
 vRes := GetNamedSecurityInfo(Pchar(aDir), SE_FILE_OBJECT,
   DACL_SECURITY_INFORMATION, nil, nil, PACL(@pDACL), nil, pSD);
 if vRes <> ERROR_SUCCESS then
   Exit;

 GetAclInformation(pDACL^, @aclInfo, sizeOf(aclInfo), AclSizeInformation);

 // Теперь запускаем цикл перебора всех записей
 for i := 0 to aclInfo.AceCount-1 do
 begin
   // получаем текущую запись
   if not (GetAce(pDACL^, i, Pointer(ace))) then
     continue;

   SID := PSID(@((ace)^.SidStart));

   if EqualSid(SID, aSID) then
   begin
     Result := BIncludeA(FILE_GENERIC_WRITE, ace^.Mask);
     Exit;
   end;
 end;
end;

function SetFileAccessRights(AFile, AUser: String; AMask: DWORD; INHERIT:Integer): Boolean;
var
 psd             : PSECURITY_DESCRIPTOR;
 dwSize          : DWord;
 bDaclPresent    : Bool;
 bDaclDefaulted  : Bool;
 OldAcl          : PACL;
 NewAcl          : PACL;
 sd              : SECURITY_DESCRIPTOR;
 ea              : EXPLICIT_ACCESS;
begin
 Result := False;
 if WIN32Platform <> VER_PLATFORM_WIN32_NT then
   Exit;
 psd := nil;
 NewAcl := nil;
 bDaclDefaulted := True;
 if not GetFileSecurity(PChar(AFile), DACL_SECURITY_INFORMATION, Pointer(1),
          0, dwSize) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) then
 begin
   try
     psd := HeapAlloc(GetProcessHeap, 8, dwSize);
     if psd <> nil then
     begin
       BuildExplicitAccessWithName(@ea, PChar(AUser), AMask, SET_ACCESS,INHERIT);

       //GetNamedSecurityInfo(PChar(AFile), SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, nil, nil, OldACL, nil, psd);
       Result := GetFileSecurity(PChar(AFile), DACL_SECURITY_INFORMATION, psd, dwSize, dwSize);

       Result := GetSecurityDescriptorDacl(psd, bDaclPresent, OldAcl, bDaclDefaulted);
       if not Result then
         Exit;
       Result := (SetEntriesInAcl(1, @ea, OldAcl, NewAcl) = ERROR_SUCCESS);
       if not Result then
         Exit;
       Result := InitializeSecurityDescriptor(@sd, SECURITY_DESCRIPTOR_REVISION);
       if not Result then
         Exit;
       Result := SetSecurityDescriptorDacl(@sd, True, NewAcl, False);
       if not Result then
         Exit;
       Result := SetFileSecurity(PChar(AFile), DACL_SECURITY_INFORMATION, @sd);
     end;
   finally
     if NewAcl <> nil then
       LocalFree(HLocal(NewAcl));
     if psd <> nil then
       HeapFree(GetProcessHeap, 0, psd);
   end;
 end;
end;

// Получаем имя пользователя по SID
function GetSidName(Sid : PSID; out aName: String): Boolean;
var
 lpName,lpDomain : PWideChar;
 cbName,cbDomain : Cardinal;
 peUse : Cardinal;
begin
 Result := False;
 cbName:=64;
 cbDomain:=64;

 GetMem(lpName,cbName*SizeOf(WideChar));
 GetMem(lpDomain,cbDomain*SizeOf(WideChar));
 try
   if not LookupAccountSidW(nil,Sid,lpName,cbName,lpDomain,cbDomain,peUse)
      and (GetLastError=122) then
   begin
     ReAllocMem(lpName,cbName*SizeOf(WideChar));
     ReAllocMem(lpDomain,cbDomain*SizeOf(WideChar));

     if not LookupAccountSidW(nil,Sid,lpName,cbName,lpDomain,cbDomain,peUse) then
       Exit;
   end;
   aName := lpName;
   Result := True;
 finally
   FreeMem(lpName);
   Freemem(lpDomain);
 end;
end;

function ConvertStringSidToSidW(StringSid : PWideChar; var Sid : PSID):Boolean;stdcall;external "advapi32.dll";

function GetAllUsersName: String;
var
 vSID: PSID;
begin
 vSID := nil;
 try
   if ConvertStringSidToSidW(cAllUsers, vSID) then
   begin
     if not GetSidName(vSID, Result) then
       Result := "Все";
   end
   else
     Result := "Все";
 finally
   if nil <> vSID then LocalFree(cardinal(vSID));
 end;
end;

function IsNTFS: Boolean;
var
 fso, drv: OleVariant;
begin
 fso := CreateOleObject("Scripting.FileSystemObject");
 drv := fso.GetDrive(fso.GetDriveName(Application.ExeName));
 IsNTFS := drv.FileSystem = "NTFS"
end;

function IsCanWriteForAllUsers(const aDir: String): Boolean;
var
 SID: PSID;
begin
 Result := False;
 if not DirectoryExists(aDir) then
   Exit;

 ConvertStringSidToSidW("S-1-1-0", Sid);

 Result := IsCanWrite(aDir, Sid);
end;

function SetDirSecurityForAllUsers(const aDir: String): Boolean;
var
 vUserName: String;
begin
 Result := False;
 if not DirectoryExists(aDir) then
   Exit;

 vUserName := GetAllUsersName;
 Result := SetFileAccessRights(aDir, vUserName, MainFileRights, SUB_CONTAINERS_AND_OBJECTS_INHERIT);
end;



Страницы: 1 вся ветка

Форум: "Прочее";
Текущий архив: 2010.09.26;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.006 c
15-1277833769
bss
2010-06-29 21:49
2010.09.26
Интересный вызов Initialization секции в BPL


2-1278037272
novai
2010-07-02 06:21
2010.09.26
Записать содержимое GetMem в файл


15-1277965959
MonoLife
2010-07-01 10:32
2010.09.26
Рабочий вопрос.


2-1277896975
linuxoid
2010-06-30 15:22
2010.09.26
пинг хоста


2-1277787890
zergost
2010-06-29 09:04
2010.09.26
данные поля на форме





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский