Nazwa pliku .bat wywołującego proces.

0

Jeśli moja aplikacja została uruchomiona przy pomocy pliku .bat, to jak w programie mogę odczytać nazwę tego .bat'a?
Czy sposób pozyskania będzie różny dla różnych komend batcha:
start proces.exe
call proces.exe
process.exe
?

1

@m_Lesiu - najpierw poczytaj sobie o tym, czym te sposoby się różnią:

Sprawdź sobie też opis systemu pomocy w CMD (polecenia help start i help call) a zrozumiesz czym się te komendy różnią; IMO jeśli chcesz przekazać uruchamianej aplikacji nazwę pliku wywołującego (wsadowego), możesz to zrobić podając ścieżkę tego pliku w parametrze wywołania.

0

Chodzi o to, że moja aplikacja może być uruchamiana w przeróżny sposób. Ktoś może ją odpalić dwuklikiem, ktoś wsadzić ją do batcha i wywołać CALL'em ktoś wywołać STATR'em. A ja bym chciał wyświetlić w programie w jaki sposób i ew. z jakiego batcha został wywołany mój program.

0

@m_Lesiu - a czy rozpoznanie sposobu uruchomienia procesu jest dla Twojej aplikacji koniecznością? Czy ta aplikacja działa zależnie od sposobu uruchomienia? Bo jeśli nie, to takie wodotryski nie będą użytkownikowi potrzebne; Funkcjonalność tych komend jest różna, ale dla plików .exe nie ma większego znaczenia której się użyje;

Według mnie nie za bardzo istnieje możliwość sprawdzenia tego, bo rozruchem programu zajmuje się system i wspomnianych informacji raczej nie przekazuje dalej (oprócz parametrów); Bez względu na to, czy żądanie rozruchu napłynęło z powłoki systemu, pliku wsadowego czy innej aplikacji;

Oczywiście mogę się mylić - na wylot systemu nie znam, jednak nie podejrzewam, żeby była możliwość sprawdzenia i rozróżnienia elementu wywołującego.

0

Chodzi o to, że niektórzy użytkownicy uruchamiają ten program kilkanaście razy na jednym komputerze, każdą instancję z innymi parametrami.(Załóżmy, że każdy proces z innego batcha.) Okazuje się, że któraś instancja została źle skonfigurowana. I teraz biedny użytkownik nie wie w którym z miliona batchy ma to poprawić. Po czym bierze: widły, pochodnie, woła resztę użytkowników i przychodzą mi do pokoju.

1

To loguj parametry wywołania.
Takie próby "wyniuchania" czegoś o systemie zwykle są nieprzenośne i przy następnym Windows mogą nie działać.
Logowanie będzie zawsze działać, chyba że użyjesz Windows Events - wtedy tak jak wyżej.

http://stackoverflow.com/questions/30229826/writing-to-the-windows-event-log-using-delphi

5

Można uzyskać nazwę pliku BAT ale ten kod zadziała tylko w nowszych systemach (chyba od Vista)

type
  PROCESS_BASIC_INFORMATION = packed record
    ExitStatus: DWORD;
    PebBaseAddress: Pointer;
    AffinityMask: DWORD;
    BasePriority: DWORD;
    UniqueProcessId: DWORD;
    InheritedUniquePID:DWORD;
  end;

  function  NtQueryInformationProcess(ProcessHandle : THandle; ProcessInformationClass : DWORD; ProcessInformation : Pointer; ProcessInformationLength : ULONG; ReturnLength : PULONG ): LongInt; stdcall; external 'ntdll.dll';
//-----
implementation

{$R *.dfm}

uses
  ActiveX,
  ComObj;

function  GetCommandLineFromPid(ProcessId:DWORD): string;
var
  FSWbemLocator : OLEVariant;
  FWMIService   : OLEVariant;
  FWbemObjectSet: OLEVariant;
begin;
  Result:='';
  FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
  FWMIService   := FSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '', '');
  //if the pid not exist a EOleException exception will be raised with the code $80041002 - Object Not Found
  FWbemObjectSet:= FWMIService.Get(Format('Win32_Process.Handle="%d"',[ProcessId]));
  Result:=FWbemObjectSet.CommandLine;
end;

function GetParentCommandLine(): string;
var
  hProc: THandle;
  ProcessBasicInfo: PROCESS_BASIC_INFORMATION;
  ReturnLength: Cardinal;
begin
  result:= '';
  hProc:= OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, GetCurrentProcessID);
  if hProc > 0 then
  begin
    //pobranie rodzica procesu
    if (NtQueryInformationProcess(hProc, 0, @ProcessBasicInfo, sizeof(ProcessBasicInfo), @ReturnLength) = 0)
      and (ReturnLength=SizeOf(ProcessBasicInfo)) then
      result:= GetCommandLineFromPid(ProcessBasicInfo.InheritedUniquePID);
    CloseHandle(hProc);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);   //przyklad uzycia
begin
    CoInitialize(nil);
    try
     Caption:= GetParentCommandLine();
    finally
      CoUninitialize;
    end;
end;

bez względu na sposób uruchamiania w pliku BAT będziesz miał coś w stylu a z tego nazwę pliku to już raczej nie problem:
C:\Windows\system32\cmd.exe /c ""C:\Users\kAzek\Documents\Embarcadero\Studio\Projects\Win32\Debug\test.bat" "

Żeby nie było że to ja taki mądry najważniejsza funkcja GetCommandLineFromPid pochodzi z https://theroadtodelphi.com/2011/07/20/two-ways-to-get-the-command-line-of-another-process-using-delphi/ tam zaprezentowane są 2 sposoby pierwszy z użyciem funkcji WinApi a drugi WMI. Wybrałem drugi, bo pierwszy nie działa dla 64bit procesów (nie znam odpowiedników stałych OffsetProcessParametersx32 i OffsetCommandLinex32 a to najprawdopodobniej przez to nie działa) .

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