The .bat file works correctly when launched from a Delphi application with administrative rights, but without rights it simply does not find the file. The application is installed in the Program Files folder. In other non-system folders, without rights is performed correctly. How to bypass this restriction?

procedure RunBatchFile; var List: TStringList; ShExecInfo: SHELLEXECUTEINFO; begin if not FileExists(ExtractFilePath(Application.ExeName) + 'config.ini') then try try if (FileExists(ExtractFilePath(Application.ExeName) + 'get_ip.bat')) or (FileExists(ExtractFilePath(Application.ExeName) + 'ip.txt')) then begin DeleteFile(ExtractFilePath(Application.ExeName) + 'get_ip.bat'); DeleteFile(ExtractFilePath(Application.ExeName) + 'ip.txt'); end; List := TStringList.Create; List.Add('@echo off'); List.Add('cls'); List.Add('for /f "usebackq tokens=4" %%A in (`route print ^| findstr "\<0.0.0.0"`) do echo %%A > ip.txt'); List.SaveToFile(ExtractFilePath(Application.ExeName) + 'get_ip.bat'); ZeroMemory(@ShExecInfo, SizeOf(SHELLEXECUTEINFO)); with ShExecInfo do begin cbSize := SizeOf(SHELLEXECUTEINFO); fMask := SEE_MASK_NOCLOSEPROCESS; lpFile := PChar(ExtractFilePath(Application.ExeName) + 'get_ip.bat'); nShow := SW_HIDE; end; ShellExecuteEx(@ShExecInfo); WaitForSingleObject(ShExecInfo.hProcess, INFINITE); List.LoadFromFile(ExtractFilePath(Application.ExeName) + 'ip.txt'); edtIP.Text := Trim(List.Text); edtPort.Text := '5432'; edtUser.Text := 'postgres'; edtPassword.Text := 'passwd'; Exit; except on E: Exception do ShowMessage(SysErrorMessage(GetLastError)); end; finally List.Free; end; 
  • Where is the error check? What does GetLastError return? - Anton Shchyrov
  • Updated the question, added verification. Writes "Access Denied" - user214690
  • Where do you get the exception? It should not be. ShellExecute is a function and it returns the result - Anton Shchyrov
  • Cited the full code, an exception occurs when you try to save the batch file in Program Files \ MyApp. It also does not delete if the file already exists. ShellExecuteEx runs get_ip.bat , but the code itself does not save data to the Program Files \ MyApp folder. When running from the administrator, the code is executed correctly, without permissions - "Access denied" - user214690
  • one
    Are you kidding me? You have an error when deleting, and the question is "how to start?" - Anton Shchyrov

1 answer 1

Work with the file in the Temp directory

 function GetTempPath: string; var LLen: Cardinal; begin LLen := Win32Check(Windows.GetTempPath(0, nil)); SetLength(Result, LLen - 1); Win32Check(Windows.GetTempPath(LLen, @Result[1])); end; procedure RunBatchFile; var List: TStringList; ShExecInfo: SHELLEXECUTEINFO; Name: string; begin if FileExists(ExtractFilePath(Application.ExeName) + 'config.ini') then Exit; try List := TStringList.Create; try List.Add('@echo off'); List.Add('cls'); List.Add('for /f "usebackq tokens=4" %%A in (`route print ^| findstr "\<0.0.0.0"`) do echo %%A > %temp%\ip.txt'); Name := GetTempPath + 'get_ip.bat'; List.SaveToFile(Name); ZeroMemory(@ShExecInfo, SizeOf(SHELLEXECUTEINFO)); with ShExecInfo do begin cbSize := SizeOf(SHELLEXECUTEINFO); fMask := SEE_MASK_NOCLOSEPROCESS; lpFile := PChar(Name); nShow := SW_HIDE; end; Win32Check(ShellExecuteEx(@ShExecInfo)); WaitForSingleObject(ShExecInfo.hProcess, INFINITE); CloseHandle(ShExecInfo.hProcess); List.LoadFromFile(GetTempPath + 'ip.txt'); edtIP.Text := Trim(List.Text); edtPort.Text := '5432'; edtUser.Text := 'postgres'; edtPassword.Text := 'passwd'; finally List.Free; end; except on E: Exception do ShowMessage(E.Message); end; end; 
  • Not all antiviruses love temp. - Qwertiy
  • @Qwertiy It was designed for writing temporary files of the application - Anton Shchyrov
  • Yes, but this does not prevent some antiviruses from locking the launch from there. - Qwertiy
  • @Anton Shchyrov, thank you. I apologize for the misunderstanding - user214690