-
function createprocesswithlogonw( lpusername: pchar; lpdomain: pchar; lppassword: pchar; dwlogonflags: dword; lpapplicationname: pchar; lpcommandline: pchar; dwcreationflags: dword; lpenvironment: pointer; lpcurrentdirectory: pchar; const lpstartupinfo: tstartupinfo; var lpprocessinformation: tprocessinformation ): bool; stdcall; external 'advapi32.dll' name 'CreateProcessWithLogonW';
function runasEx2(const username, password, command: string; Terminate : Integer = 0): Cardinal; const LOGON_WITH_PROFILE = $00000001; var si: tstartupinfo; pi: tprocessinformation; lasterror: dword; resultstring: string; res : BOOL; lCOmmand : String; begin
zeromemory(@si, sizeof(si)); si.cb:=sizeof(si); zeromemory(@pi, sizeof(pi)); lCOmmand := command; UniqueString(Lcommand); if not createprocesswithlogonw(PCHAR(username),'',PChar(password), LOGON_WITH_PROFILE, nil,PCHAR(Lcommand),CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, nil, si,pi) then RaiseLastOSError; if (WaitForSingleObject(pi.hProcess,20000) =WAIT_TIMEOUT) then begin if (Terminate > 0) then TerminateProcess(pi.hProcess,0); Result := 1; end else Result := 0; CloseHandle(pi.hThread); CloseHandle(pi.hProcess); end; end;
Функция выполняет команду с логином и паролем пользователя с административными правами на данной машине.
При вызове runasEx2('Admin','123','cmd /c dir'); Все Ок.
При попытке остановить службу
runasEx2('Admin','123','net stop myservice');
Ошибка 5. Отказано в доступе.
Delphi XE2. Windows 7, 8.
В Windows XP (как и полагается) оба запуска отрабатывают нормально.
-
-
Т.е. нельзя ожидать от этой функции выполнения процесса с административными правами?
-
Sashka (15.10.14 13:12) [2]
Можно, надо читать подробнее
-
-
> При попытке остановить службу а запустить?
Попробовать так:
sDomain := '.'; // sCommand := '"net stop myservice"';
ну и
function CreateProcessWithLogonW( lpUsername :PCHAR; lpDomain :PCHAR; lpPassword :PCHAR; dwLogonFlags :DWORD; lpApplicationName :PCHAR; lpCommandLine :PCHAR; dwCreationFlags :DWORD; lpEnvironment :Pointer; lpCurrentDirectory :PCHAR; lpStartupInfo :PSTARTUPINFOW; // var lpProcessInfo :TPROCESSINFORMATION ):LongBool; stdcall; external advapi32_dll name 'CreateProcessWithLogonW';
-
Проблемы с распознаванием команды никакой нет, поэтому брать в кавычки смысла тоже нет. Чем может помочь параметр домен в виде точки - тоже вопрос.
Не работает.
Пытаюсь перейти на вариант LogonUser CreateProcessAsUser
-
> тоже вопросВы проверели? а если runasEx2('Admin','123','cmd'); и там уже net stop myservice ?
-
По сути, задача стоит вот какая: Программа запускается с правами обычный пользователь Далее должна выполнить ряд действия с административными правами (копирование файлов, установка/остановка сервисов и т.п.) Логин и Пароль администратора - известен.
Запускать исходную программу сразу через RunAs - не удобно.
Как ни странно, но Поиск не находит типовое решение данной задачи для случая ОС >= Windows 7 + UAC
-
Вот такой запрос в гугле вроде даёт вполне подходящие обсуждения,но их надо порыть. Там все куда-нибудь ссылаются, но кода никто не приводит )
"повысить права процесса до администраторских WinAPI"
-
ам... Не разбирался как оно работает, но у многих программ есть такая штука - запускается от пользователя, а в меню у некоторых пунктов есть иконка "админ" и при нажатии идёт обычный запрос прав админа. Это нужно?
-
DQ, я так понял, что нет, не это.
На сколько я понял, нужно чтобы запускалась программа без прав администратора, но для выполнения какой-то функции эти права запрашивала и повышала приоритет своего же процесса до нужных прав.
На сколько я понял по изученным ссылкам, сие в общем случае - невозможно впринципе, т.к. процесс может получить только те токены привилегий, которые были ему назначены в момент запуска (за корректность терминологии не ручаюсь). Т.е., если процесс запустить "От администратора", то он в Win7 получит токет административных привилегий, хотя такие привилегии и не будут активны. Но в этом случае уже можно будет запросить поднятие привилегий процесса, т.к. токен такой есть - просто выскочит окно UAC и запрошенные привилегии для процесса будут "активированы".
Но если просто запустить процесс без прав админа - то ему не будет назначен нужный токен и "активировать" его уже не удастся вообще никак.
Описываются, как я понял, 2 сценария решения этой проблемы: 1) Использовать СОМ для порождения объекта с нужными правами, в этом случае в смысле интерфейса для пользователя всё можно сделать совершенно гладко, общаясь с созданным СОМ объектом стандартным образом, хоть он и будет фактически в рамках другого процесса запущен 2) Запускать из своего приложения новый процесс с нужными привилегиями (и запросом от UAC), но очевидно будет проблема сшивки GUI-интерфейса для пользователя.
-
sashka , NoUser © (15.10.14 17:00) [7] >а если >runasEx2('Admin','123','cmd'); >и там уже >net stop myservice ????! > Далее должна выполнить ряд действия с административными > правами (копирование файлов, установка/остановка сервисов > и т.п.) >Запускать исходную программу сразу через RunAs - не удобно.
- Запустите отдельное приложение с админ правами (или ещё одну копию своего с дополнительными параметрами в командной строке) где и выполняйте нужные админ действия. (Временно 'стать админом' не получится) - program RunAdm; uses Windows;
type TPChars = array [0..(MaxInt div SizeOf(PChar))-1] of PChar; PPChars =^ TPChars;
function CommandLineToArgvW(pCmdLine:PChar; var NumArgs:Integer):PPChars; stdcall; external 'shell32.dll' name 'CommandLineToArgvW'; function CreateProcessWithLogonW( lpUsername :PCHAR; lpDomain :PCHAR; lpPassword :PCHAR; dwLogonFlags :DWORD; lpApplicationName :PCHAR; lpCommandLine :PCHAR; dwCreationFlags :DWORD; lpEnvironment :Pointer; lpCurrentDirectory :PCHAR; lpStartupInfo :PSTARTUPINFOW; var lpProcessInfo :TPROCESSINFORMATION ):LongBool; stdcall; external 'advapi32.dll' name 'CreateProcessWithLogonW'; procedure RunAs(); const tCmd = 'cmd.exe'; tUser = 'admin'; tPass = '123'; tDomain = '.'; var pi :TPROCESSINFORMATION; si :TSTARTUPINFOW; i,n :Integer; pArgs :PPChars; sCmd :String; sDir :String; begin ZeroMemory(@pi, sizeof(pi)); ZeroMemory(@si, sizeof(si)); si.cb := sizeof(si); pArgs := CommandLineToArgvW(GetCommandLine(), n); if n>1 then begin for i := 1 to n-1 do sCmd := sCmd + pArgs[i] + ' '; SetLength(sCmd, Length(sCmd)-1); CreateProcessWithLogonW(tUser, tDomain, tPass, 1, nil, PChar(sCmd), 0, nil, nil, @si, pi); end else begin SetLength(sDir, 1024); SetLength(sDir, GetSystemDirectory(PChar(sDir), Length(sDir))); sCmd := sDir + '\'+ tCmd; CreateProcessWithLogonW(tUser, tDomain, tPass, 1, PChar(sCmd), nil, 0, nil, PChar(sDir), @si, pi); end; CloseHandle(Pi.hThread); CloseHandle(Pi.hProcess); LocalFree(NativeUInt(pArgs)); end;
begin RunAs(); end. RunAdm.exe net stop dnscache
RunAdm.exe net start dnscache
RunAdm.exe cmd /c start compmgmt.msc
>для случая ОС >= Windows 7 + UACпроблем не увидел.
-
BOOL SetUserObjectFullAccess(HANDLE UserObject)
DWORD StartProcess(CStr &FileName, CStr &UserName, CStr &UserPass, CStr &OpenFile)
Этот кусок кода сетевой службы, задача которой при получении пользовательского запроса запустить на сервере процесс (с параметрами) от имени пользователя (даже если он админ)
-
Итого: получилось вот такое решение проблемы... К сожалению, код Дмитрия проверить не успел... 1. Встраиваем в своем приложении AdminApplication.exe UAC-манифест запрашивающий повышения привилегий. Как описано см. тут: http://edn.embarcadero.com/article/339422. Пишем приложение Стартер, для запуска исходного приложения Uses ComObj; procedure TForm1.btn2Click(Sender: TObject); const S = 'e:\AdminApplication.exe'; var hw : THandle; i : Integer; WsShell : OleVariant; begin // запускаем Админ консоль через RunAS WsShell:=CreateOleObject('WScript.Shell'); WsShell.Run('runas /user:AdminUSERName cmd', 1, False); Sleep(200); //задержка WsShell.SendKeys('adminpassword', True); //посылаем пароль WsShell.SendKeys('{ENTER}', True); //переходим на новую строку Sleep(1000); // Ищем созданное окно консоли repeat sleep (200); hw := FindWindow ('ConsoleWindowClass',nil); until hw > 0; // передаем ему вызов приложения, которое следует запустить for I := 1 to lENGTH (s) do PostMessage(hw, WM_CHAR, Byte(S[i]), 1); PostMessage(hw, WM_Keyup, byte(VK_RETURN), 1); PostMessage(hw, WM_Keyup, byte(VK_RETURN), 1); SetForegroundWindow(hw); // закрываем консоль sleep (1000); for I := 1 to Length (s2) do PostMessage(hw, WM_CHAR, Byte(S2[i]), 1); PostMessage(hw, WM_Keyup, byte(VK_RETURN), 1); // закрываемся сами Close; end; Естественно предполагается, что окно консоли открыто только одно, иначе добавляем проверку заголовка. 3. Запускаем Стартер. Работаем в приложении AdminApplication с правами Админа.
-
> Sashka (21.10.14 17:20) [14]
Мдя, начали за здравие, закончили заупокойной...
-
> Мдя, начали за здравие, закончили заупокойной...
Не понял?
Я же написал, что запускать, что-то сразу с правами Администратора не удобно, потому что это приводит к запросу административного пароля , чего мне необходимо избежать.
Поэтому предложение
> Запустите отдельное приложение с админ правами...
теряет смысл.
Я бы тогда, просто запускал исходное приложение с правами Администратора.
Код программа RunAdm проблему не решает (но на всякий случае запустил на WIn 8 + UAC - результат - Ошибка 5. Отказано в доступе ). По сути это тоже самое, что и код моего первого поста. Полагаю что работает он у тебя в дебаге при запуске из IDE, которая запущена с правами Админа.
-
Sashka, По делу:1.) Соберите, пожалуйста, экзешничек из [12] и запустите его со следующими параметрами командной строки: net stop spooler Результаты (выполнилось ли нужное действие, был ли UAC) опишите в [18.1]. 2.) Запустите собранный экзешничек без параметров командной строки. В новооткрывшемся окне консоли введите такую команду net start spooler Результат опишите в [18.2]. Теперь эмоции:Значит >> Запустите отдельное приложение с админ правами... > теряет смысл.а > Запускаем Стартер. Работаем в приложении AdminApplication с правами Админа.эго, этот "смысл", находит! [14] Ж)))))))))): У-а-э, бу-га-га, танцы с бубном - да-да-да!
-
)) не поленился... Итак... ОС Windows 8.1 UAC Приложение запускается под пользователем User группа Пользователь Позволил себе внести несколько строчек в код [12] // *** , добавив WriteLn
program RunAdm;
uses
Windows;
type
TPChars = array [0..(MaxInt div SizeOf(PChar))-1] of PChar;
PPChars =^ TPChars;
function CommandLineToArgvW(pCmdLine:PChar; var NumArgs:Integer):PPChars; stdcall; external 'shell32.dll' name 'CommandLineToArgvW';
function CreateProcessWithLogonW( lpUsername :PCHAR;
lpDomain :PCHAR;
lpPassword :PCHAR;
dwLogonFlags :DWORD;
lpApplicationName :PCHAR;
lpCommandLine :PCHAR;
dwCreationFlags :DWORD;
lpEnvironment :Pointer;
lpCurrentDirectory :PCHAR;
lpStartupInfo :PSTARTUPINFOW;
var lpProcessInfo :TPROCESSINFORMATION
):LongBool; stdcall; external 'advapi32.dll' name 'CreateProcessWithLogonW';
procedure RunAs();
const
tCmd = 'cmd.exe';
tUser = 'MyAdminLogin'; tPass = 'MyAdminPassword'; tDomain = '.';
var
pi :TPROCESSINFORMATION;
si :TSTARTUPINFOW;
i,n :Integer;
pArgs :PPChars;
sCmd :String;
sDir :String;
begin
ZeroMemory(@pi, sizeof(pi));
ZeroMemory(@si, sizeof(si));
si.cb := sizeof(si);
pArgs := CommandLineToArgvW(GetCommandLine(), n);
if n>1 then begin
writeln ('Run1'); for i := 1 to n-1 do sCmd := sCmd + pArgs[i] + ' ';
SetLength(sCmd, Length(sCmd)-1);
sCmd := 'cmd /K ' + sCmd; if not CreateProcessWithLogonW(tUser, tDomain, tPass, 1, nil, PChar(sCmd), 0, nil, nil, @si, pi) then
writeln ('Run1 failed') end else begin
writeln ('Run2'); SetLength(sDir, 1024);
SetLength(sDir, GetSystemDirectory(PChar(sDir), Length(sDir)));
sCmd := sDir + '\'+ tCmd;
if not CreateProcessWithLogonW(tUser, tDomain, tPass, 1, PChar(sCmd), nil, 0, nil, PChar(sDir), @si, pi) then
writeln ('Run2 failed'); end;
CloseHandle(Pi.hThread);
CloseHandle(Pi.hProcess);
LocalFree(NativeUInt(pArgs));
end;
begin
RunAs();
end.
A) Запускаем c:\1\RunAdm.exe net stop spooler Результат - Ошибка 5. Отказано в доступе. https://cloud.mail.ru/public/e2e8df2de9d5%2Fpic1.PNGB) Запускаем c:\1\RunAdm.exe В новой консоли net stop spooler Результат - Ошибка 5. Отказано в доступе. https://cloud.mail.ru/public/ca620af1261d%2Fpic2.PNGПочему же Отказано в доступе? А потому что с включенным UAC запуск приложения под логином Админа недостаточен для выполнения ряда действий. Поэтому приходится еще и правой кнопкой мыши нажимать и выбирать "Запустить от имени администратора" (даже если фактически находимся под Админом в системе). Даже если сделать в Windows runas /user:Admin cmd и в административной уже консоли набрать net stop spooler результат будет тоже Ошибка 5. Отказано в доступе. https://cloud.mail.ru/public/f10266bff1bf%2Fpic3.PNGТеперь бу-га-га [14]Приложение Стартер - находит смысл, поскольку он запускается под пользователем User с обычными правами, а затем запускает основное приложение уже с правами Администратора, самостоятельно указывая необходимые регистрационные данные (логин и пароль). В довесок еще вариант по тематике http://mda-delphi.blogspot.ru/2009_03_01_archive.html
-
> sashka (23.10.14 11:52) [18]
Контрольный вопрос:
Как Вы получили/получаете пароль пользователя в 'чистом' виде?
ЗЫ.
Если приложения для себя - (> Почему же Отказано в доступе? ) используйте встроенную учётную запись администратора или крутите политики для других админ учёток.
Если приложения для всех - создайте службу и с её помощью решайте Ваши задачи.
|