Dziwne zachowanie funkcji RunProcessAndWait

0

Witam serdecznie. Mam stworzoną aplikację w Lazarusie a w niej buttony uruchamiające aplikacje za pomocą funkcji RunProcessAndWait. No i teraz o co tak naprawdę mi chodzi. Jeżeli aplikacja którą chce wywołać za pomocą aplikacji(zrobionej przez Lazarusa) posiada na sobie prawa administratora, to jakby "wywoływanie" dzieje się w folderze w którym znajduje się aplikacja Lazarusa.

Przykład:
Aplikację z Lazarusa "autorun.exe" mam na pulpicie w folderze "kk" i nią chce wywołać plik bat(uprzednio skonwertowany do .exe), który znajduje się w "E:\setap.exe" i okienko z Windowsa pięknie nam przedstawia że coś jest nie tak ponieważ działania tej aplikacji dzieją się w folderze "kk" na pulpicie, a nie na dysku E jak powinno być. Poniżej przedstawię wycinek z konsoli:
title

Nie wiem czego to wina a potrzebuję otworzyć program który z kolei potrzebuje dodatkowe pliki do jego poprawnego działania i w efekcie wyskakuje error brakujących plików. W tym przypadku jak widać postanowiłem zrobić coś na bazie konsoli aby dokładnie zobaczyć co się dzieje no i już wiadomo jednak nie wiem co jest tego przyczyna i jak temu zaradzić. I jak mówiłem dzieje się to tylko na plikach, które mają na sobie nałożone "prawa administratora" tzn w właściwościach zaznaczone jest okienko uruchom jako administrator.

Pozdrawiam.

0

RunProcessAndWait to nie jest funkcja, a metoda proceduralna – tak samo jak RunProcessAsAdminAndWait. Poza tym, nie znajduje się w bibliotece standardowej, więc nikt nie wie (oprócz mnie) jak działa.

0

Niestety nie jestem obeznany w 100% i nie wiedziałem że to metoda proceduralna aczkolwiek podobno korzysta z "CreateProcess" więc może się ktoś wypowie na ten temat?

0

Ja nic nie zrozumiałem z tego co napisałeś, wrzuć kod źródłowy.

A dobra środowisko envirioment zawiera ścieżkę path aktualnego katalogu, zmień sobie i tyle.

0

Na pulpicie mam apke autorun.exe i przez nią uruchamiam plik, który znajduje się na dysku E(setap.exe z prawami administratora).

Problem w tym że autorun.exe normalnie wywołuje ten plik z "E" natomiast działania w konsoli(setap.exe) dzieją się tam gdzie znajduje sie aplikacja Lazarusa m.in autorun.exe. Wszystko zostało zobrazowane tak naprawdę w screenie jaki zapodałem wyżej.

Tutaj kodzik a raczej jego urywek - dodam że "FGamePath" ma szukać lokalizację na podstawie rejestru tak jak w tym przypadku jest to "E":

procedure TMainForm.CSetupButtonClick(ASender: TObject);
begin
  try
    FProcessing := True;

    PrepareButtons();
    Application.ProcessMessages();

    if FileExists(FGamePath + 'setap.exe') then
    begin
      if not RunProcessAndWait(FGamePath, 'setap.exe') then
        RunProcessAsAdminAndWait(FGamePath, 'setap.exe');
    end
    else
      ShowError('nie można odnaleźć pliku setap.exe', 'title');
  finally
    FProcessing := False;

    PrepareInstallationData();
    PrepareButtons();
  end;
end;   
1

A te setap jak ręcznie odpalisz na pulpicie, to gdzie się wykonuje?

0

@Trzeźwy Programista

Chciałeś powiedzieć kiedy go wywołuję z dysku E? To wtedy działa poprawnie i otwiera plik znajdujący się obok(screen obrazuje działanie).

Plik setap.exe ma uruchomić plik setup.exe a oba znajdują się obok siebie. Kiedy wywołuje setap.exe to ten powinien uruchomić program obok natomiast tak się nie dzieje i szuka on tego pliku obok aplikacji Lazarusa.

1

Jak dla mnie ten converter bat na exe statycznie zlinkował położenie, daj jeszcze plik bat.

0

Raczej nie ma takiej możliwości bo jak pisałem wywołując bezpośrednio tego problemu nie ma. Przypominam też ze dzieje się to na plikach z uprawnieniami administratora. A cały ten pliczek .bat stworzyłem po to bo właściwa aplikacja którą chce wykorzystać zachowuje się podobnie i chciałem sobie zobrazować co może być nie tak - potrzebuje ona dodatkowe pliki i uruchamiając bezpośrednio z dysku działa bez problemu natomiast przez Lazarusa brakuje jej dodatkowych plików niezbędnych do działania.

echo Nacisnij dowolny klawisz aby kontynuowac...
start setup.exe
pause

0

Tutaj kod jak się te 2 procedury zachowują - być może gdzieś tu jest błąd?

function TMainForm.RunProcessAndWait(const APath, AFileName: String): Boolean;
var
  LStartup: TStartupInfo;
  LProcess: TProcessInformation;
var
  LCommand: String;
  LFlags: DWORD;
begin
  Result := False;

  FillChar(LStartup{%H-}, SizeOf(LStartup), 0);
  FillChar(LProcess{%H-}, SizeOf(LProcess), 0);

  LStartup.cb := SizeOf(LStartup);
  LStartup.dwFlags := STARTF_USESHOWWINDOW;
  LStartup.wShowWindow := SW_SHOW;

  LCommand := APath + AFileName;
  LFlags := NORMAL_PRIORITY_CLASS;

  Result := CreateProcess(nil, PChar(LCommand), nil, nil, False, LFlags, nil, PChar(APath), LStartup, LProcess);

  if Result then
  begin
    repeat
      Application.ProcessMessages();
    until (WaitForSingleObject(LProcess.hProcess, 20) <> WAIT_TIMEOUT);

    CloseHandle(LProcess.hProcess);
    CloseHandle(LProcess.hThread);
  end;

  Application.ProcessMessages();
end;


procedure TMainForm.RunProcessAsAdminAndWait(const APath, AFileName: String);
var
  LShellInfo: TShellExecuteInfo;
  LExitCode: DWORD = 0;
begin
  FillChar(LShellInfo{%H-}, SizeOf(LShellInfo), 0);

  LShellInfo.cbSize := SizeOf(TShellExecuteInfo);
  LShellInfo.wnd := Self.Handle;
  LShellInfo.fMask := SEE_MASK_FLAG_DDEWAIT or SEE_MASK_NOCLOSEPROCESS;
  LShellInfo.lpVerb := PChar('runas');
  LShellInfo.lpFile := PChar(APath + AFileName);
  LShellInfo.nShow := SW_SHOW;

  if ShellExecuteExA(@LShellInfo) then
  repeat
    Application.ProcessMessages();
    GetExitCodeProcess(LShellInfo.hProcess, LExitCode);
  until LExitCode <> STILL_ACTIVE;

  Application.ProcessMessages();
end;                                
0
echo Nacisnij dowolny klawisz aby kontynuowac...
start setup.exe
pause

I taki skrypt na pulpicie odpala setup.exe z dysku E?

0

Ehh, pisałem że on znajduje się na E a wywoływany jest z aplikacji Lazarusa "która" jest na pulpicie...

0
echo Nacisnij dowolny klawisz aby kontynuowac...
cd E:\folderodsetup\
start setup.exe
pause
0

@Chory Programista - kompletnie się nie rozumiemy. Jeżeli chcesz pomóc co byłoby mile widziane to przeczytaj jeszcze raz z czym mam problem. Pozdrawiam.

0

@Eazy: a ten uruchamiany program – setup.exe z dysku E: – sam pisałeś?

0

Co to za różnica skoro dzieje się to na każdym pliku mających na sobie admina chociazby nawet firefox.exe...

0

Wiem że mogą się wydawać śmieszne słowa wypisywane przez osobę która się na tym kompletnie nie zna ale... podejrzewam że błąd gdzieś leży w:

function TMainForm.RunProcessAndWait(const APath, AFileName: String): Boolean;

i

procedure TMainForm.RunProcessAsAdminAndWait(const APath, AFileName: String);

W końcu to od nich zależy jak plik zostanie wywołany.

0
Eazy napisał(a):

Co to za różnica skoro dzieje się to na każdym pliku mających na sobie admina chociazby nawet firefox.exe...

Duża różnica, bo jeśli ten program jest Twój to możesz mu przesłać jego ścieżkę w parametrze, a on może sobie ją z parametru odczytać (ParamStr(1)) i ustawić jako working directory.

Eazy napisał(a):

Wiem że mogą się wydawać śmieszne słowa wypisywane przez osobę która się na tym kompletnie nie zna ale... podejrzewam że błąd gdzieś leży w […]

No to próbuj to naprawić.

0

Niestety nie jest mój.

0

Spróbuj objąć wartość zmiennej LCommand znakami " (podobnie z wartością parametru APath).

0
 LCommand := "APath" + "AFileName";    

Czy o to chodzi? Bo w ten sposób się nie chce kompilować.

1

O matko…:

LCommand := '"' + APath + AFileName + '"';
0

O matko nie pomogło.

1

Spróbuj zrobić to samo z parametrem APath. Albo i ze zmienną LCommand i parametrem APath.

0

Wszystko fajnie tylko że dla mnie to brzmi jak czarna magia co można było przekonać się przed chwilą...

1

W wywołaniu CreateProcess, zamiast PChar(APath) daj PChar('"' + APath + '"').

0

Nie pomogło. I jeżeli mogę coś dodać to my modyfikujemy funkcję "RunProcessAndWait" a ta działa poprawnie natomiast jest problem z "RunProcessAsAdminAndWait". Chyba że ta 2 korzysta też z 1,

0

W tej drugiej nie ma co zmienić – wydaje się w porządku.

2

W funkcji RunProcessAsAdminAndWait dodaj linijkę:

 LShellInfo.lpDirectory:= PChar(APath);
0

@Sauler o kurczę nie wierzę... w końcu działa jak należy :) Naprawdę wielkie dzięki długo starałem się znaleźć rozwiązanie tego problemu.

1 użytkowników online, w tym zalogowanych: 0, gości: 1