| 
| 
 | Вопрос # 3 779/ вопрос открыт / | 
 |  Здравствуйте, уважаемые эксперты!Мне необходимо из своей программы запустить приложение CyberLink PowerDVD. Пытаюсь я это сделать с помощью функции CreateProcess как показано в приложении. Результат - ничего и GetLastError выдает ошибку 998. Попытка запуска из командной строки тоже ни к чему не приводит. В чем может быть проблема?
 Приложение:Переключить в обычный режим procedure TForm1.startBluRayPlayer;var//  http://www.delphirus.com/modules.php?name=News&file=article&sid=32  applicationPath: PChar;  stringOfParametrs: PChar;  ProcessSecurityAttributes: TSecurityAttributes;  ThreadSecurityAttributes: TSecurityAttributes;  bInheritHandles: LongBool; // ôëàã
íàñëåäîâàíèÿ
òåêóùåãî
ïðîöåññà  CreationFlags: Longword; // ôëàãè
ñïîñîáîâ
ñîçäàíèÿ
ïðîöåññà  Environment: Pointer; //
óêàçàòåëü
íà áëîê
ñðåäû  CurrentDirectory: PChar; // òåêóùèé
äèñê è
êàòàëîã  StartupInfo:TStartupInfo; //
ñòðóêòóðà
STARTUPINFO  ProcessInformation: TProcessInformation; //
ñòðóêòóðà
PROCESS_INFORMATION   res: boolean;  Error: integer;begin  applicationPath := 'C:Program FilesCyberLinkPowerDVDPowerDVD.exe';  stringOfParametrs := nil;  bInheritHandles := false;  CreationFlags := NORMAL_PRIORITY_CLASS;  Environment := nil;  CurrentDirectory := nil;   StartupInfo.cb := SizeOf(TStartUpInfo);  StartupInfo.lpReserved := nil;  StartupInfo.dwX := 100;  StartupInfo.dwY := 100;  StartupInfo.dwXSize := 500;  StartupInfo.dwXSize := 350;  StartupInfo.cbReserved2 := 0;  StartupInfo.lpReserved2 := nil;   res := CreateProcess(applicationPath, stringOfParametrs, {ProcessSecurityAttributes} nil,    {ThreadSecurityAttributes} nil, bInheritHandles, CreationFlags, Environment,    CurrentDirectory, StartupInfo, ProcessInformation);   if (res) then  begin    WaitForInputIdle(ProcessInformation.hProcess, INFINITE);    CloseHandle(ProcessInformation.hThread); //
çàêðûâàåì
äåñêðèïòîð
ïðîöåññà    CloseHandle(ProcessInformation.hProcess); //
çàêðûâàåì
äåñêðèïòîð
ïîòîêà  end  else    Error := GetLastError;  Memo1.Lines.Add(IntToStr(Error));end;
|  |   Вопрос задал: 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 (статус: 1-ый класс), 16 февраля 2010, 14:36 [#3]:CreateProcess обычно используется для создания процесса под другой учетной записью, а для запуска программ лучше всего использовать WinExec('путь_имя_файла', SW_NORMAL) или если нужно открыть папку с нужной директорией ShellExecute(Handle,'explore', 'c:\Program Files\Borland', nil,nil,SW_RESTORE); |  
|   | AlexMPEI (статус: 1-ый класс), 16 февраля 2010, 14:47 [#4]:998 - NO_ACCESS 
 добавил очистку
 FillChar(StartUpInfo, SizeOf(TStartUpInfo), 0);
 теперь CreateProcess возвращает true, но приложение по прежнему не запускается
 |  
|   | Alexey6522 (статус: 1-ый класс), 16 февраля 2010, 15:20 [#5]:Чувак, я ж тебе написал как проще всего запустить приложение!!!! |  
|   | AlexMPEI (статус: 1-ый класс), 16 февраля 2010, 15:34 [#6]:Я прочитал и попробовал. WinExec('путь_имя_файла', SW_NORMAL) сработал. CreateProcess тоже заработал, если выставить bInheritHandles в true. Теперь проблема в том что если просто закрыть PowerDVD, то процесс остается в памяти и повторный запуск невозможен, хотя окно закрыто. Как с этим правильно поступить?
 
 то 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 (статус: 1-ый класс), 16 февраля 2010, 16:02 [#8]:Попробуй добавить CloseHandle(HWND:THWND) |  
|   | 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;
 |  Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте. |