V
Vadik(R)
Тема в принципе заезженная, поэтому решил написать в ветке FAQ (да и вообще, моей любимой ).
В общем, проблема такая. Когда делаешь какую-либо программу на Delphi 7, и в ней, допустим, пытаешься создать какой-либо файл в корне диска, то в Windows XP все работает нормально, а в Windows 7 - файл вместо корня диска создается в папке C:\Users\Vadim\AppData\Local\VirtualStore.
Ну, как и следует, видимо из соображений безопасности. Для того, чтобы создать файл именно в корне диска C - приходиться запускать программу с правами администратора, щелкать по кнопке OK в UAC-окне. Проблема в следующем, что мне надоело каждый раз принудительно щелкать правой кнопкой мыши и запускать программу с администраторскими правами. Решение есть - поставить в свойствах галочку - запустить программу с правами администратора. Но оно меня не очень устраивает, поскольку, если сменить расположение программы, то галочку приходится ставить заново, да и вообще, выходит мне так придеться ставить галочки почти для каждой написанной мною программы? - Не выход. Отключать UAC я тоже не хочу, все же раз придумали эту штуку как средство защиты, пускай есть, пригодится. Потому пришёл к выводу, что надо сделать так, чтобы программа сама запускала себя сразу с правами администратора. Погуглив, я нашёл способ сделать такое с помощью manifest-файла, правда везде этот способ описывался для Visual Studio C++. А мне надо для Delphi 7, все же, хоть и мертвый язык, для меня он привычней
Вот, стал гуглить, как запустить программу с правами администратора для Delphi, а параллельно наткнулся на код, который определяет, запущена ли программа уже с правами администратора или нет:
Но, проблема в том, что этот код не рабочий. Он всегда выдает сообщение, что программа запущена с правами администратора.
Поэтому, я нашёл другой выход из этой ситуации, правда кривой на мой взгляд. А именно, программе без администраторских прав запрещено создавать exe-файлы в корне диска, даже если в файл будет создаваться в VirtualStore. Потому я пытаюсь создать какую-либо exe-шку в корне диска, и, если это сделать не получается, то программа запущена без администраторских прав, иначе все хорошо Способ, понятное дело, очень не хороший, так как программа с таким именем может уже существовать в корне диска, да и в целом, левый способ. Хотя, если бы можно было внедрять manifest-файл в Delphi, так же, как и в Visual Stidio C++, то проблема определения, запущена ли программа с администраторскими правами, отпадет сама
Но это только половина дела, определить, как запущена программа, ведь если она запущена не под админом, то ей стоит перезапустить саму себя уже с администраторскими правами. Вот, опять погуглил эту проблему, нашёл код с функцией CreateProcessWithLogonW:
Но эта функция всегда выводит мне сообщение "Краххх.."
Не знаю, почему так. Кто-то говорит, что это из-за того, что пароль стоит пустой, и таким образом это такая защита...
В общем, проблема такая, что надо программно запустить самого себя с правами администратора. Сделать это надо средствами Delphi 7, было бы обидно, что если такая возможность была только в C++.
В общем, проблема такая. Когда делаешь какую-либо программу на Delphi 7, и в ней, допустим, пытаешься создать какой-либо файл в корне диска, то в Windows XP все работает нормально, а в Windows 7 - файл вместо корня диска создается в папке C:\Users\Vadim\AppData\Local\VirtualStore.
Ну, как и следует, видимо из соображений безопасности. Для того, чтобы создать файл именно в корне диска C - приходиться запускать программу с правами администратора, щелкать по кнопке OK в UAC-окне. Проблема в следующем, что мне надоело каждый раз принудительно щелкать правой кнопкой мыши и запускать программу с администраторскими правами. Решение есть - поставить в свойствах галочку - запустить программу с правами администратора. Но оно меня не очень устраивает, поскольку, если сменить расположение программы, то галочку приходится ставить заново, да и вообще, выходит мне так придеться ставить галочки почти для каждой написанной мною программы? - Не выход. Отключать UAC я тоже не хочу, все же раз придумали эту штуку как средство защиты, пускай есть, пригодится. Потому пришёл к выводу, что надо сделать так, чтобы программа сама запускала себя сразу с правами администратора. Погуглив, я нашёл способ сделать такое с помощью manifest-файла, правда везде этот способ описывался для Visual Studio C++. А мне надо для Delphi 7, все же, хоть и мертвый язык, для меня он привычней
Вот, стал гуглить, как запустить программу с правами администратора для Delphi, а параллельно наткнулся на код, который определяет, запущена ли программа уже с правами администратора или нет:
Код:
const
SECURITY_NT_AUTHORITY: TSIDIdentifierAuthority = (Value: (0, 0, 0, 0, 0, 5));
SECURITY_BUILTIN_DOMAIN_RID = $00000020;
DOMAIN_ALIAS_RID_ADMINS = $00000220;
function IsAdmin: Boolean;
var
hAccessToken: THandle;
ptgGroups: PTokenGroups;
dwInfoBufferSize: DWORD;
psidAdministrators: PSID;
x: Integer;
bSuccess: BOOL;
begin
Result := False;
bSuccess := OpenThreadToken(GetCurrentThread, TOKEN_QUERY, True, hAccessToken);
if not bSuccess then
begin
if GetLastError = ERROR_NO_TOKEN then bSuccess := OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, hAccessToken);
end;
if bSuccess then
begin
GetMem(ptgGroups, 1024);
bSuccess := GetTokenInformation(hAccessToken, TokenGroups, ptgGroups, 1024, dwInfoBufferSize);
CloseHandle(hAccessToken);
if bSuccess then
begin
AllocateAndInitializeSid(SECURITY_NT_AUTHORITY, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, psidAdministrators);
{$R-}
for x := 0 to ptgGroups.GroupCount - 1 do
if EqualSid(psidAdministrators, ptgGroups.Groups[x].Sid) then
begin
Result := True;
Break;
end;
{$R+}
FreeSid(psidAdministrators);
end;
FreeMem(ptgGroups);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
if isAdmin then ShowMessage('Logged in as Administrator');
end;
Поэтому, я нашёл другой выход из этой ситуации, правда кривой на мой взгляд. А именно, программе без администраторских прав запрещено создавать exe-файлы в корне диска, даже если в файл будет создаваться в VirtualStore. Потому я пытаюсь создать какую-либо exe-шку в корне диска, и, если это сделать не получается, то программа запущена без администраторских прав, иначе все хорошо Способ, понятное дело, очень не хороший, так как программа с таким именем может уже существовать в корне диска, да и в целом, левый способ. Хотя, если бы можно было внедрять manifest-файл в Delphi, так же, как и в Visual Stidio C++, то проблема определения, запущена ли программа с администраторскими правами, отпадет сама
Но это только половина дела, определить, как запущена программа, ведь если она запущена не под админом, то ей стоит перезапустить саму себя уже с администраторскими правами. Вот, опять погуглил эту проблему, нашёл код с функцией CreateProcessWithLogonW:
Код:
function CreateProcessWithLogonW(lpUsername: PWideChar; lpDomain: PWideChar; lpPassword: PWideChar; dwLogonFlags: DWORD; lpApplicationName: PWideChar; lpCommandLine: PWideChar; dwCreationFlags: DWORD; lpEnvironment: Pointer; lpCurrentDirectory: PWideChar; const lpStartupInfo: STARTUPINFO; var lpProcessInfo: PROCESS_INFORMATION): BOOL; stdcall; external 'advapi32.dll' name 'CreateProcessWithLogonW';
...
var
si: STARTUPINFO;
pi: PROCESS_INFORMATION;
begin
...
ZeroMemory(@si, SizeOf(si));
si.cb := SizeOf(si);
if CreateProcessWithLogonW('administrator', nil, '', 1, nil, PWideChar(Application.ExeName), 0, nil, nil, si, pi) then ShowMessage('Yahoo') else ShowMessage('Krahhh...');
end;
Не знаю, почему так. Кто-то говорит, что это из-за того, что пароль стоит пустой, и таким образом это такая защита...
В общем, проблема такая, что надо программно запустить самого себя с правами администратора. Сделать это надо средствами Delphi 7, было бы обидно, что если такая возможность была только в C++.