Jak usunąć plik .sys?

0

Witam, mam mały problem z usunięciem pliku z katalogu \System32\Drivers\plik.sys

Otóż gdy chcę skasować plik ręcznie to uruchamia się kontrola UAC i muszę potwierdzić że chcę usunąć plik jako administrator.
Napisałem prosty program który ma kasować plik i gdy uruchamiam go jako administrator to niestety pliku nie kasuje, dlaczego?

Ale gdy uruchamiam plik del_plik.bat
Oto zawartość pliku del_plik.bat

@echo off
del c:\windows\system32\drivers\plik.sys

to plik zostaje usunięty.

Poszedłem o krok dalej i napisałem programik który ma uruchamiać plik del_plik.bat jako administrator:

procedure RunAsAdmin(const aFile: string; const aParameters: string = ''; Handle: HWND = 0);
var
  sei: TShellExecuteInfo;
begin
  FillChar(sei, SizeOf(sei), 0);
 
  sei.cbSize := SizeOf(sei);
  sei.Wnd := Handle;
  sei.fMask := SEE_MASK_FLAG_DDEWAIT or SEE_MASK_FLAG_NO_UI;
  sei.lpVerb := 'runas';
  sei.lpFile := PChar(aFile);
  sei.lpParameters := PChar(aParameters);
  sei.nShow := SW_SHOWNORMAL;

  if not ShellExecuteexA(@sei) then
    RaiseLastOSError;
end;

procedure TForm1.Button1Click(Sender: TObject);
RunAsAdmin('plik del_plik.bat');
end;

program uruchamia plik del_plik.bat jako administrator ale plik nie jest skasowany.

Wyłączyłem kontrolę UAC i nadal nic, domyślam się że trzeba jakoś programowo potwierdzić że chcę usunąć plik jako administrator ale nie wiem jak to zrobić, co ciekawe nie działa nawet sprawdzanie czy plik istnieje:

if FileExists('c:\windows\system32\drivers\plik.sys') then

i nie ma znaczenia czy program uruchamiam jako administrator czy normalnie, po prostu nie działa.

Czy ktoś ma pomysł jak usunąć plik systemowy z "c:\windows\system32\drivers\plik.sys"

Z góry dziękuję za pomoc.

dodanie znaczników <code class="winbatch"> i <code class="delphi"> - Furious Programming

0

Kod nie jest wstawiony w odpowiednie znaczniki, także go ignoruje. Co do rozwiązania. To o ile wiem, można spróbowac zrobić ShellExecute z zamiast open to runas dla tego batcha. Są przykłady na Google takich rozwiązan i w Delphi. Ja bym kobminował tak, że dodał bym do zasobów taki manifest i miałbym pewnośc, że program można uruchomić tylko jako admin. I wtedy z UAC nie ma problemów. Poza tym nie wiem, co to za program kombinujesz z usuwaniem *.sys czy to util na Twoje potrzeby czy modzisz jakieś malware. Bo jeżeli używasz komputera z głową, a program ma chodzić na Twoim komputerze i być używany przez Ciebie. To pozostaje jeszcze rozwiązanie extremalne, wyłączyć UAC.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" 
          manifestVersion="1.0"> 
<dependency> 
    <dependentAssembly> 
        <assemblyIdentity 
            type="win32" 
            name="Microsoft.Windows.Common-Controls" 
            version="6.0.0.0" 
            processorArchitecture="X86" 
            publicKeyToken="6595b64144ccf1df" 
            language="*" 
        /> 
    </dependentAssembly> 
</dependency> 
<v3:trustInfo xmlns:v3="urn:schemas-microsoft-com:asm.v3">
  <v3:security>
    <v3:requestedPrivileges>
      <v3:requestedExecutionLevel level="requireAdministrator" />
    </v3:requestedPrivileges>
  </v3:security>
</v3:trustInfo>
</assembly>
0

Dzięki za odpowiedź Olesio, radzisz mi wyłączyć UAC a ja pisałem że już sprawdzałem z wyłączonym UAC i nic to nie dało, nadal nie można usunąć pliku.sys. Dla wiadomości osób czytających ten post nie piszę żadnego malware tylko chcę skasować jeden pliczek bo on mi blokuje urządzenie serwisowe i wtedy muszę czekać na odblokowanie czasami kilka dni, a tak się składa że korzystam z tego urządzenia na kilku komputerach w firmie i w domu i sprawdzanie za każdym razem ręcznie czy ten plik istnieje i usuwanie go ręcznie jest po prostu uciążliwe i chcę to zautomatyzować, tak że przyda się każda rada.
Możesz podać jakiś mały przykład jak to zrobić z tym manifestem? I skoro moja metoda uruchamiania pliku.bat za pomocą RunAsAdmin nie działa to czy będzie działać ta metoda ShellExecute z runas?

0

Wywołanie runas powinno pokazać monit UAC, ale nie wiem czy to pomoże. Manifest dołączasz normalnie poprzez zasoby, w pliku *.rc dla starszych Delphi ma być jako rodzaj 24. Nie podawać tam stałej MANIFEST jak robi to za usera na przykład edytor ResEd. Bo wtedy brcc32.exe nie dołaczy tego w exeku jako manifest, tylko jakiś zasób z danymi.

Ewentualnie spróbuj użyć http://lockhunter.com i może on pozwoli odblokować plik. Jeżeli na chwilę wyłączysz UAC dla testów lub spróbujesz usunąc ten *.sys z pod TotalCommandera uruchomionego na prawach admina (poprzez potwierdzenie monitu od UAC przy uruchomieniu). I to się nadal nie powiedzie, to znaczy, że i tak plik jest używany i nie da się go w łatwy sposób usunąć.

Bo o ile wiem, to na ogół jeżeli nie jest uruchomiony jakiś program lub usługa, większośc plików daje się usunąć. Wyjątkiem jest pagefile.sys i niektóre dllki oraz chyba fizyczne pliki w ktorych jest Rejestr. I to co powiązane z shell'em, jeżeli dobrze kojarze.

1

Jeśli plik jest używany to można ew. próbować go rename'ować, ale nie wiem czy to Ci się przyda.

UAC działa z grubsza tak:

  • uruchamiasz aplikację jako admin, ona pobiera sobie jakieś tam uprawnienia i może trochę więcej, w ekstremalnych przypadkach zawsze się pyta (np. msconfig)
  • nie uruchamiasz aplikacji jako admin, to przy próbie czegoś tam zrobienia ona się pyta o konto admina

Żeby aplikacja za każdym razem się nie pytała, musiałaby być odpalona jako serwis lub zadanie w harmonogramie.

0

To nie rozwiązuje problemu, problemem jest to:

user image

dopiero po kliknięciu kontynuuj można usunąć plik, czy ktoś wie jak zrobić to programowo z poziomu delphi?

0

Trochę się pogubiłem w tym temacie. Bo jeśli dobrze zrozumiałem, to wywołanie programu w Delphi, który ma manifest wymuszajacy uruchomienie tylko na prawach admina. I w nim funkcja WinAPI DeleteFile nie skutkuje? Jeżeli tak jest to coś nadal używa pliku.

0

Olesio sprawdziłem to z manifestem i nadal nie działa:

Dodałem manifest do projektu, a pliczek kasuje w ten sposób:

"ShellExecute(0, 'runas', ('cmd.exe'), PChar('/c del c:\windows\system32\drivers\afd.sys'), PChar(''), SW_Normal);"

ale to też nie działa.

W tej sytuacji wystarczy mi program który by sprawdził czy plik istnieje, macie jakieś pomysły jak to zrobić?
Jak sprawdzić czy ten plik istnieje:

c:\windows\system32\drivers\afd.sys

bo ten kod też nie działa:

procedure TForm1.Button2Click(Sender: TObject);
begin
if FileExists('c:\windows\system32\drivers\afd.sys') then
begin
showmessage('istnieje')
end else
showmessage('nie istnieje');
end;

Zwraca wartość "nie istnieje"

Oczywiście do projektu też dodałem manifest UAC, domyślam się że tu nie chodzi o kontrole UAC tylko o brak dostępu do pliku chroniony przez system, ale żeby nawet nie można sprawdzić czy plik istnieje?

1

Hmmm, czyli samo DeleteFile też się pewnie nie powiedzie. Bo nadal nie wiem dlaczego upierasz się na rozwiązanie z cmd.exe. Srawdź dla pewności czy pod na przykład TotalCommanderem da się usunąć ten plik. Jeżeli tak, to może problemem jest to, co opisano tutaj w opisie funkcji i przykładzie jej użycia http://msdn.microsoft.com/en-us/library/windows/desktop/aa365743(v=vs.85).aspx tylko mnie wydawało się, że to dotyczy innego folderu, ale pewnie i system32 również.

0

Uruchamiam Total Commander jako administrator i gdy chcę usunąć plik z folderu \System32\Drivers\ mam komunikat "Odmowa dostępu"
Na razie nie mam pomysłu jak to obejść...

Ale dziwne jest to że nie da się nawet sprawdzić w normalny sposób czy istnieje plik w tym katalogu: \System32\Drivers\ bo zwykłe:

if FileExists('c:\windows\system32\drivers\plik.sys') then

nie działa

0

Nie obejdziesz tego w takim razie, bo coś nadal używa pliku. Co do tego żeby FileExists lub inny kod oparty o wyszukiwanie pliku zadziałał spróbuj tego na poniższej stronie. Innych pomysłów nie mam.

http://msdn.microsoft.com/en-us/library/windows/desktop/aa365744(v=vs.85).aspx

2

Dokładne jeżeli aplikacja 32 bit na 64bit systemie to musi być wywołane Wow64DisableWow64FsRedirection dlatego podana niżej funkcja znajduje plik afd.sys w folderze c:\windows\system32\drivers\

function WinApiFileExist(AFileName: string): Boolean;
{$IF CompilerVersion < 25}
{$DEFINE CPUX86} //od delphi XE5 mzna kompilowac 64bit w starszych zawsze 32bit
{$IFEND}
  function CheckFileExist(AFileName: string): Boolean;
  var
    FindFileData: WIN32_FIND_DATA;
    hFind: Cardinal;
  begin
    result:= False;
    hFind:= FindFirstFile(PChar(AFileName), FindFileData);
    if hFind <> INVALID_HANDLE_VALUE then
    begin
      {$IF CompilerVersion >= 23}WinApi.{$IFEND}Windows.FindClose(hFind);
      result:= True;
    end;
  end;
{$IFDEF CPUX86}
type
  TIsWow64Process = function(hProcess: THandle; var Wow64Process: LongBool): LongBool; stdcall;
  TWow64DisableWow64FsRedirection = function(var Wow64FsEnableRedirection: LongBool): LongBool; stdcall;
  TWow64EnableWow64FsRedirection = function (Wow64FsEnableRedirection: LongBool): LongBool; stdcall;
var
  hKernelLib: Cardinal;
  pIsWow64Proc: TIsWow64Process;
  pWow64DisableWow64FsRedirect: TWow64DisableWow64FsRedirection;
  pWow64EnableWow64FsRedirect: TWow64EnableWow64FsRedirection;
  IsWow64, Wow64FsEnableRedirection: LongBool;
{$ENDIF CPUX86}
begin
  {$IFDEF CPUX86}
  result := False;
  hKernelLib:= LoadLibrary('kernel32.dll');
  if hKernelLib <> INVALID_HANDLE_VALUE then
  begin
    IsWow64:= False;
    pIsWow64Proc:= GetProcAddress(hKernelLib, 'IsWow64Process');
    if Assigned(pIsWow64Proc) then
      pIsWow64Proc(GetCurrentProcess, IsWow64);
    if IsWow64 then
    begin
      pWow64DisableWow64FsRedirect:= GetProcAddress(hKernelLib, 'Wow64DisableWow64FsRedirection');
      pWow64EnableWow64FsRedirect:= GetProcAddress(hKernelLib, 'Wow64EnableWow64FsRedirection');
      if Assigned(pWow64DisableWow64FsRedirect) then
        pWow64DisableWow64FsRedirect(Wow64FsEnableRedirection);
      result:= CheckFileExist(AFileName);
      if Assigned(pWow64EnableWow64FsRedirect) then
        pWow64EnableWow64FsRedirect(Wow64FsEnableRedirection);
    end
    else
    {$ENDIF CPUX86}
      result:= CheckFileExist(AFileName);
    {$IFDEF CPUX86}
    FreeLibrary(hKernelLib);
  end;
  {$ENDIF CPUX86}
end;

Funkcja trochę długa bo oparta na WinApi a do tego funkcje importuje dynamicznie ponieważ w starszych systemach ich nie ma. Myślę że jeżeli wcześniej wywołasz Wow64DisableWow64FsRedirection to zwykłe FileExists też się powiedzie a nawet prawdopodobnie usunięcie pliku (oczywiście z prawami admina) też pewnie dlatego nie działało.

EDIT Poprawa zgodności Dla starych i nowych Delphi

0

Dzięki kAzek to może rozwiązać ten problem, czy możesz podać zastosowanie tej funkcji, jak ją wywołać?

0

No nie załamuj nas. Przecież funkcja, którą podał poprzednik jest oczywista w użyciu. Natomiast te z Wow64 są opisane na MSDNie.

0

Olesio możesz podać przykład użycia tej funkcji?

Nie każdy jest tak dobrym programistą jak Ty, a nie którzy muszą od czegoś zacząć tak jak ja, być może jest to oczywiste jak wywołać tę funkcję.

I może przydać się innym początkującym programistą.

0

Z funkcjami api jest zwykle tak, że:

  • są wymienione w postaci "reference" w co najmniej 3 miejscach w sieci
  • do tego są "tutorial"-e
  • a oprócz tego wypowiedzi takie jak powyższa (im starsza funkcja i bardziej problematyczna tym więcej)

Naprawdę mało jest przypadków gdy do funkcji API trzeba podawać przykład bo go nie ma.

Co dotychczas znalazłeś? Z czym masz problem?
Czy wykonujesz pełną obsługę błędów wywołania funkcji?

Podpowiedź: wywołaj po KAŻDEJ funkcji API to:

ShowMessage(SysErrorMessage(GetLastError)))

lub to:

RaiseLastOSError;
0

Dzięki vpiotr, ale zamiast odsyłać mnie do tutoriali łatwiej było by jak byś podał przykład użycia w/w kodu.

Jak wywołać tę funkcję i sprawdzić czy plik istnieje?

kAzek możesz wkleić kod który sprawdza czy plik istnieje? I możesz napisać czy sprawdzałeś czy da się usunąć za pomocą tej funkcji plik .sys?

0

Używam Delphi 2007

0

Nie sądziłem że użycie tej funkcji jest takie proste :)

 procedure TForm1.Button1Click(Sender: TObject);
begin
begin if WinApiFileExist('c:\windows\system32\drivers\afd.sys') then
begin
showmessage('istnieje')
end else
showmessage('nie istnieje');
end;
end;

Kod działa, dzięki za pomoc :)

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