Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 3 779

/ вопрос открыт /

Здравствуйте, уважаемые эксперты!
Мне необходимо из своей программы запустить приложение CyberLink PowerDVD. Пытаюсь я это сделать с помощью функции CreateProcess как показано в приложении. Результат - ничего и GetLastError выдает ошибку 998. Попытка запуска из командной строки тоже ни к чему не приводит. В чем может быть проблема?

Приложение:
  1. procedure TForm1.startBluRayPlayer;
  2. var
  3. // http://www.delphirus.com/modules.php?name=News&file=article&sid=32
  4. applicationPath: PChar;
  5. stringOfParametrs: PChar;
  6. ProcessSecurityAttributes: TSecurityAttributes;
  7. ThreadSecurityAttributes: TSecurityAttributes;
  8. bInheritHandles: LongBool; // ôëàã íàñëåäîâàíèÿ òåêóùåãî ïðîöåññà
  9. CreationFlags: Longword; // ôëàãè ñïîñîáîâ ñîçäàíèÿ ïðîöåññà
  10. Environment: Pointer; // óêàçàòåëü íà áëîê ñðåäû
  11. CurrentDirectory: PChar; // òåêóùèé äèñê è êàòàëîã
  12. StartupInfo:TStartupInfo; // ñòðóêòóðà STARTUPINFO
  13. ProcessInformation: TProcessInformation; // ñòðóêòóðà PROCESS_INFORMATION
  14.  
  15. res: boolean;
  16. Error: integer;
  17. begin
  18. applicationPath := 'C:Program FilesCyberLinkPowerDVDPowerDVD.exe';
  19. stringOfParametrs := nil;
  20. bInheritHandles := false;
  21. CreationFlags := NORMAL_PRIORITY_CLASS;
  22. Environment := nil;
  23. CurrentDirectory := nil;
  24.  
  25. StartupInfo.cb := SizeOf(TStartUpInfo);
  26. StartupInfo.lpReserved := nil;
  27. StartupInfo.dwX := 100;
  28. StartupInfo.dwY := 100;
  29. StartupInfo.dwXSize := 500;
  30. StartupInfo.dwXSize := 350;
  31. StartupInfo.cbReserved2 := 0;
  32. StartupInfo.lpReserved2 := nil;
  33.  
  34. res := CreateProcess(applicationPath, stringOfParametrs, {ProcessSecurityAttributes} nil,
  35. {ThreadSecurityAttributes} nil, bInheritHandles, CreationFlags, Environment,
  36. CurrentDirectory, StartupInfo, ProcessInformation);
  37.  
  38. if (res) then
  39. begin
  40. WaitForInputIdle(ProcessInformation.hProcess, INFINITE);
  41. CloseHandle(ProcessInformation.hThread); // çàêðûâàåì äåñêðèïòîð ïðîöåññà
  42. CloseHandle(ProcessInformation.hProcess); // çàêðûâàåì äåñêðèïòîð ïîòîêà
  43. end
  44. else
  45. Error := GetLastError;
  46. Memo1.Lines.Add(IntToStr(Error));
  47. end;


AlexMPEI Вопрос ожидает решения (принимаются ответы, доступен мини-форум)

Вопрос задал: AlexMPEI (статус: 1-ый класс)
Вопрос отправлен: 16 февраля 2010, 12:23
Состояние вопроса: открыт, ответов: 0.


Мини-форум вопроса

Всего сообщений: 9; последнее сообщение — 16 февраля 2010, 16:57; участников в обсуждении: 3.
Егор

Егор (статус: 10-ый класс), 16 февраля 2010, 13:34 [#1]:

а в гугле не пробовал набрать что-нить типа "GetLastError 998"?
Опасайтесь багов в приведенном выше коде; я только доказал корректность, но не запускал его.
— Donald E. Knuth.
Егор

Егор (статус: 10-ый класс), 16 февраля 2010, 13:37 [#2]:

ну, или CreateProcess GetLastError 998
Опасайтесь багов в приведенном выше коде; я только доказал корректность, но не запускал его.
— Donald E. Knuth.
Alexey6522

Alexey6522 (статус: 1-ый класс), 16 февраля 2010, 14:36 [#3]:

CreateProcess обычно используется для создания процесса под другой учетной записью, а для запуска программ лучше всего использовать WinExec('путь_имя_файла', SW_NORMAL) или если нужно открыть папку с нужной директорией ShellExecute(Handle,'explore', 'c:\Program Files\Borland', nil,nil,SW_RESTORE);
AlexMPEI

AlexMPEI (статус: 1-ый класс), 16 февраля 2010, 14:47 [#4]:

998 - NO_ACCESS

добавил очистку
FillChar(StartUpInfo, SizeOf(TStartUpInfo), 0);
теперь CreateProcess возвращает true, но приложение по прежнему не запускается
Alexey6522

Alexey6522 (статус: 1-ый класс), 16 февраля 2010, 15:20 [#5]:

Чувак, я ж тебе написал как проще всего запустить приложение!!!!
AlexMPEI

AlexMPEI (статус: 1-ый класс), 16 февраля 2010, 15:34 [#6]:

Я прочитал и попробовал. WinExec('путь_имя_файла', SW_NORMAL) сработал. CreateProcess тоже заработал, если выставить bInheritHandles в true.
Теперь проблема в том что если просто закрыть PowerDVD, то процесс остается в памяти и повторный запуск невозможен, хотя окно закрыто. Как с этим правильно поступить?

то Alexey6522: я не игнорю твои ответы, чувак, я проверяю все на практике + форум подглючивает - сообщения могут вклиниваться каким-то образом, когда я отправил ответ Егору твоего сообщения еще небыло, но потом оно вклинилось по времени.
Alexey6522

Alexey6522 (статус: 1-ый класс), 16 февраля 2010, 16:00 [#7]:

вот что я нашел
uses
   AccCtrl, AclAPI;
 
 
function GetOSVersion: Cardinal;
var
  OSVersionInfo: TOSVersionInfo;
begin
  Result:= 0;
  FillChar(OSVersionInfo, Sizeof(OSVersionInfo), 0);
  OSVersionInfo.dwOSVersionInfoSize:= SizeOf(OSVersionInfo);
  if GetVersionEx(OSVersionInfo) then
  begin
    if OSVersionInfo.dwPlatformId = VER_PLATFORM_WIN32_NT then
    begin
      if OSVersionInfo.dwMajorVersion = 5 then
      begin
        if OSVersionInfo.dwMinorVersion = 0 then
          Result:= 50
        else if OSVersionInfo.dwMinorVersion = 2 then
          Result:= 52
        else if OSVersionInfo.dwMinorVersion = 1 then
          Result:= 51
      end;
      if OSVersionInfo.dwMajorVersion = 6 then
      begin
        if OSVersionInfo.dwMinorVersion = 0 then
          Result:= 60
        else if OSVersionInfo.dwMinorVersion = 1 then
          Result:= 61;
      end;
    end;
  end;
end;
 
function RunAsSystem(ApplicationName: String): Boolean;
var
  lpStartupInfo: TStartupInfo;
  lpProcessInformation: TProcessInformation;
  ppSecurityDescriptor: PPSecurity_Descriptor;
  ppDacl: PACL;
  hProcess, hToken: Cardinal;
begin
  Result:= False;
  if (GetOSVersion > 50) and (GetOSVersion < 60) then
    hProcess:= OpenProcess(PROCESS_QUERY_INFORMATION, False, 4)
  else
    hProcess:= OpenProcess(PROCESS_QUERY_INFORMATION, False, 8);
  if hProcess <> 0 then
  begin
    try
      OpenProcessToken(hProcess, MAXIMUM_ALLOWED, hToken);
      if hToken <> 0 then
      begin
        if GetSecurityInfo(hToken, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, nil, nil, @ppDacl, nil,
ppSecurityDescriptor) = ERROR_SUCCESS then
        begin
          if SetSecurityInfo(hToken, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, nil, nil, nil, nil) = ERROR_SUCCESS
then
          begin
            CloseHandle(hToken);
            OpenProcessToken(hProcess, MAXIMUM_ALLOWED, hToken);
            if hToken <> 0 then
            begin
              try
                if ImpersonateLoggedOnUser(hToken) then
                begin
                  ZeroMemory(@lpStartupInfo, SizeOf(lpStartupInfo));
                  lpStartupInfo.cb:= SizeOf(lpStartupInfo);
                  if CreateProcessAsUser(hToken, PChar(ApplicationName), '', nil, nil, False, CREATE_DEFAULT_ERROR_MODE,
nil, nil, lpStartupInfo, lpProcessInformation) then
                    Result:= True;
                  RevertToSelf;
                end;
                SetSecurityInfo(hToken, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, nil, nil, ppDacl, nil);
              finally
                CloseHandle(hToken);
              end;
            end;
          end;
        end;
      end;
    finally
      CloseHandle(hProcess);
    end;
  end;
end;
 
использование функции
  RunAsSystem('C:\Windows\run.exe');
У тебя не хватает closehandel
Alexey6522

Alexey6522 (статус: 1-ый класс), 16 февраля 2010, 16:02 [#8]:

Попробуй добавить CloseHandle(HWND:THWND)
AlexMPEI

AlexMPEI (статус: 1-ый класс), 16 февраля 2010, 16:57 [#9]:

Спасибо, Алексей. Я уже решил использовать твою WinExec. а с процессом я справляюсь путем его убийства перед запуском очередной копии, используя функцию убийства процесса по имени exe.

function TForm1.KillTask(ExeFileName: string): Integer;
const
PROCESS_TERMINATE = $0001;
var
ContinueLoop: BOOL;
FSnapshotHandle: THandle;
FProcessEntry32: TProcessEntry32;
begin
Result := 0;
FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
FProcessEntry32.dwSize := SizeOf(FProcessEntry32);
ContinueLoop := Process32First(FSnapshotHandle, FProcessEntry32);

while Integer(ContinueLoop) <> 0 do
begin
if ((UpperCase(ExtractFileName(FProcessEntry32.szExeFile)) =
UpperCase(ExeFileName)) or (UpperCase(FProcessEntry32.szExeFile) =
UpperCase(ExeFileName))) then
Result := Integer(TerminateProcess(
OpenProcess(PROCESS_TERMINATE,
BOOL(0),
FProcessEntry32.th32ProcessID),
0));
ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32);
end;
CloseHandle(FSnapshotHandle);
end;

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 22 февраля 2025, 11:27
Выполнено за 0.02 сек.