Форум: "Прочее";
Текущий архив: 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.004 c