|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
||||
|
||||
Запуск системной утилиты из приложения
Доброго времени суток, уважаемы форумчане!
Что-то не могу найти на форумах похожих тем (наверное плохо ищу), поэтому буду рад любой помощи. Суть вот в чем. При запуске из командной строки (с правами администратора) какой-нибудь системной утилиты (например sfc /scannow или powercfg /energy) все работает отлично и замечательно. Но стоит запустить эти же утилиты из приложения - начинаются проблемы. Пробовал решить их и так, и сяк - ничего не получается. Под "и так, и сяк" я понимаю ShellExecute(), WinExec(); CreateProcess(). Всегда одно и то же. Привожу пример выполнения команды powercfg /energy: С помощью CreateProcess: Код:
if (Radiobutton1.Checked = True) then FillChar(si,SizeOf(si),0); si.cb := SizeOf(si); si.dwFlags := STARTF_USESHOWWINDOW; si.wShowWindow := SW_SHOWNORMAL; if CreateProcess(nil, 'cmd.exe /K "powercfg /energy"', nil, nil, false, 0, nil, nil, si, pi) then begin CloseHandle(pi.hProcess); end else begin MessageBox(0, PChar(IntToStr(GetLastError())), nil, 0); end; С помощью ShellExecute: Код:
if (Radiobutton1.Checked = True) then begin Nrg_btn:='/K powercfg /energy'; ShellExecute(Handle, nil, 'cmd.exe', PChar(Nrg_btn), nil, SW_SHOW); end; P.S. Ошибка при выполнении: Цитата:
|
#2
|
||||
|
||||
Очевидно же,в вопросе и сам ответ:
Цитата:
Код:
const SE_CREATE_TOKEN_NAME = 'SeCreateTokenPrivilege'; SE_ASSIGNPRIMARYTOKEN_NAME = 'SeAssignPrimaryTokenPrivilege'; SE_LOCK_MEMORY_NAME = 'SeLockMemoryPrivilege'; SE_INCREASE_QUOTA_NAME = 'SeIncreaseQuotaPrivilege'; SE_UNSOLICITED_INPUT_NAME = 'SeUnsolicitedInputPrivilege'; SE_MACHINE_ACCOUNT_NAME = 'SeMachineAccountPrivilege'; SE_TCB_NAME = 'SeTcbPrivilege'; SE_SECURITY_NAME = 'SeSecurityPrivilege'; SE_TAKE_OWNERSHIP_NAME = 'SeTakeOwnershipPrivilege'; SE_LOAD_DRIVER_NAME = 'SeLoadDriverPrivilege'; SE_SYSTEM_PROFILE_NAME = 'SeSystemProfilePrivilege'; SE_SYSTEMTIME_NAME = 'SeSystemtimePrivilege'; SE_PROF_SINGLE_PROCESS_NAME = 'SeProfileSingleProcessPrivilege'; SE_INC_BASE_PRIORITY_NAME = 'SeIncreaseBasePriorityPrivilege'; SE_CREATE_PAGEFILE_NAME = 'SeCreatePagefilePrivilege'; SE_CREATE_PERMANENT_NAME = 'SeCreatePermanentPrivilege'; SE_BACKUP_NAME = 'SeBackupPrivilege'; SE_RESTORE_NAME = 'SeRestorePrivilege'; SE_SHUTDOWN_NAME = 'SeShutdownPrivilege'; SE_DEBUG_NAME = 'SeDebugPrivilege'; SE_AUDIT_NAME = 'SeAuditPrivilege'; SE_SYSTEM_ENVIRONMENT_NAME = 'SeSystemEnvironmentPrivilege'; SE_CHANGE_NOTIFY_NAME = 'SeChangeNotifyPrivilege'; SE_REMOTE_SHUTDOWN_NAME = 'SeRemoteShutdownPrivilege'; SE_UNDOCK_NAME = 'SeUndockPrivilege'; SE_SYNC_AGENT_NAME = 'SeSyncAgentPrivilege'; SE_ENABLE_DELEGATION_NAME = 'SeEnableDelegationPrivilege'; SE_MANAGE_VOLUME_NAME = 'SeManageVolumePrivilege'; // Enables or disables privileges debending on the bEnabled function NTSetPrivilege(sPrivilege: string; bEnabled: Boolean): Boolean; var hToken: THandle; TokenPriv: TOKEN_PRIVILEGES; PrevTokenPriv: TOKEN_PRIVILEGES; ReturnLength: Cardinal; begin Result := True; // Only for Windows NT/2000/XP and later. if not (Win32Platform = VER_PLATFORM_WIN32_NT) then Exit; Result := False; // obtain the processes token if OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken) then begin try // Get the locally unique identifier (LUID) . if LookupPrivilegeValue(nil, PChar(sPrivilege), TokenPriv.Privileges[0].Luid) then begin TokenPriv.PrivilegeCount := 1; // one privilege to set case bEnabled of True: TokenPriv.Privileges[0].Attributes:= SE_PRIVILEGE_ENABLED; False:TokenPriv.Privileges[0].Attributes:= 0; end; ReturnLength := 0; // replaces a var parameter PrevTokenPriv := TokenPriv; // enable or disable the privilege AdjustTokenPrivileges(hToken, False, TokenPriv, SizeOf(PrevTokenPriv), PrevTokenPriv, ReturnLength); end; finally CloseHandle(hToken); end; end; // test the return value of AdjustTokenPrivileges. Result := GetLastError = ERROR_SUCCESS; if not Result then raise Exception.Create(SysErrorMessage(GetLastError)); end; Я не понял Вашего вопроса, но всё же Вам на него отвечу! |
Этот пользователь сказал Спасибо Alegun за это полезное сообщение: | ||
ffpereverzev (18.02.2017)
|
#3
|
||||
|
||||
Решение, конечно, элегантное и не лишено смысла, но не помогло. Результат точно такой же.
Да, я написал, что от имени администратора все хорошо, но забыл упомянуть, что все хорошо, когда я ОТДЕЛЬНО запускаю командную строку от имени администратора. Если я запускаю свою программу от имени администратора, то, вроде как, командная строка запускается тоже от имени администратора (факт), но результат, почему-то другой. Цитата:
|
#4
|
||||
|
||||
Цитата:
Код:
type PTOKEN_GROUPS = TOKEN_GROUPS^; function RunningAsAdministrator(): Boolean; var SystemSidAuthority: SID_IDENTIFIER_AUTHORITY = SECURITY_NT_AUTHORITY; psidAdmin: PSID; ptg: PTOKEN_GROUPS = nil; htkThread: Integer; { HANDLE } cbTokenGroups: Longint; { DWORD } iGroup: Longint; { DWORD } bAdmin: Boolean; begin Result := false; if not OpenThreadToken(GetCurrentThread(), // get security token TOKEN_QUERY, FALSE, htkThread) then if GetLastError() = ERROR_NO_TOKEN then begin if not OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, htkThread) then Exit; end else Exit; if GetTokenInformation(htkThread, // get #of groups TokenGroups, nil, 0, cbTokenGroups) then Exit; if GetLastError() <> ERROR_INSUFFICIENT_BUFFER then Exit; ptg := PTOKEN_GROUPS(getmem(cbTokenGroups)); if not Assigned(ptg) then Exit; if not GetTokenInformation(htkThread, // get groups TokenGroups, ptg, cbTokenGroups, cbTokenGroups) then Exit; if not AllocateAndInitializeSid(SystemSidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, psidAdmin) then Exit; iGroup := 0; while iGroup < ptg^.GroupCount do // check administrator group begin if EqualSid(ptg^.Groups[iGroup].Sid, psidAdmin) then begin Result := TRUE; break; end; Inc(iGroup); end; FreeSid(psidAdmin); end; Я не понял Вашего вопроса, но всё же Вам на него отвечу! |
#5
|
||||
|
||||
Чего-то я не очень понимаю, куда мне деть этот код. У меня не консольное приложение. А при объявлении новой категории
Код:
type PTOKEN_GROUPS = TOKEN_GROUPS^; Цитата:
|
#6
|
||||
|
||||
Кстати, по-поводу запуска приложения от имени администратора. Если я запускаю приложение обычным способом и затем выполняю операцию вызывающую командную строку, то вижу такую картину:
А если запуск был от имени администратора, то тогда такую: Может это и не важно (или не говорит ни о чем). Я поэтому и обратился к знающим людям. |
#7
|
||||
|
||||
У меня этот код работает на W7Х32, под W10Х64 не пошел, всегда проблемы в 64х разрядных системах такого рода возникают,требуется более тонкая настройка среды, конкретно - это индивидуально для каждого случая - больше подсказать нечего, извнт
Я не понял Вашего вопроса, но всё же Вам на него отвечу! |
Этот пользователь сказал Спасибо Alegun за это полезное сообщение: | ||
ffpereverzev (18.02.2017)
|
#8
|
||||
|
||||
У меня как раз W10. Ну что ж....будем думать, размышлять и обмозговывать...
|
#9
|
||||
|
||||
Во, через вызов ShellExecuteEx удалось в десятке запустить нужную вам ситемную утилиту с правами одмина
Код:
procedure TForm1.Button1Click(Sender: TObject); var shInfo: PSHELLEXECUTEINFOA; s: string; begin s:= 'cmd.exe'; New(shInfo); shInfo^.cbSize:= sizeof(SHELLEXECUTEINFO); shInfo^.fMask:= 0; shInfo^.Wnd:= 0; shInfo^.lpVerb:= 'runas'; shInfo^.lpFile:= PAnsiChar(ExtractFileName(s)); shInfo^.lpParameters:= '/K powercfg /energy'; shInfo^.lpDirectory:= PAnsiChar(ExtractFilePath(s)); shInfo^.nShow:= SW_SHOWNORMAL; shInfo^.hInstApp:= 0; ShellExecuteEx(shInfo); Dispose(shInfo); shInfo:= nil; end; Я не понял Вашего вопроса, но всё же Вам на него отвечу! |
Этот пользователь сказал Спасибо Alegun за это полезное сообщение: | ||
ffpereverzev (28.02.2017)
|
#10
|
||||
|
||||
Цитата:
Начинающий программист уверен, что в 1 килобайте 1000 байт.
Законченный программист уверен, что в 1 километре 1024 метра. |
Этот пользователь сказал Спасибо Karsh за это полезное сообщение: | ||
ffpereverzev (28.02.2017)
|
#11
|
||||
|
||||
Цитата:
Я не понял Вашего вопроса, но всё же Вам на него отвечу! |
#12
|
||||
|
||||
Цитата:
Начинающий программист уверен, что в 1 килобайте 1000 байт.
Законченный программист уверен, что в 1 километре 1024 метра. Последний раз редактировалось Karsh, 19.02.2017 в 23:44. |
Этот пользователь сказал Спасибо Karsh за это полезное сообщение: | ||
Alegun (20.02.2017)
|
#13
|
||||
|
||||
Оффтоп:
Да, действительно, здесь вы совершенно правы - оказалось я в торопях по ошибке не ту версию виндовстэн под проверку загружал, всё зло от мультизагрузки, так вот выпендриться побыстрее хотелось, сейчас перепроверил - всё точно как в описании автора, значит "делфийцам-семеристам" этот путь в Х64 заказан, жаль Спасибо, УК Karsh! Я не понял Вашего вопроса, но всё же Вам на него отвечу! Последний раз редактировалось Alegun, 20.02.2017 в 00:37. |
#14
|
||||
|
||||
Спасибо!
Спасибо ВСЕМ огромное за столь быстрые, качественные и информативные ответы!
|