Sprawdzanie obecności dyskietki

0

Jak sprawdzić czy w stacji znajduje się dyskietka?? Szukałem trochę po necie i wszystko co znalazłem albo sprawdzało mi czy mam stację dyskietek, albo przed sprawdzeniem czy jest dyskietka wywalało mi najpierw błąd, że nie ma dyskietki z tymi 3 przyciskami i dopiero po ignoruj przechodziło dalej. A jak już o tym to da się jakoś przechwycić ten komunikat, żeby mi go nie pokazywało, a wykonywało konkretne operacje?? Jest mi to potrzebne do szkoły bo nam się małolaty włamują na konto admina i chciałem im zrobić mały żarcik w postaci blokady klawiatury i obecność konkretnego pliku na dyskietce ma mi to odblokowywać. Na razie mam na sprawdzaniu godziny i w czasie gdy my mamy lekcje to jest odblokowane inaczej się blokuje, ale jak wiadomo czasem trzeba coś naprawić i trzeba posiedzieć lekcję dłużej niż się ma a wtedy posłuszny program nie zrobi wyjątku.
Z góry dziękuję za pomoc

0

skoro potrzebny Ci plik na dyskietce to sprawdzaj czy jest plik a nie cała dyskietka. I kto jeszcze dyskietek używa O.o

0

Spróbuj jakimś FindFirst wyszukać A:\*.*. Sprawdź czy jest jakaś różnica w zachowaniu funkcji (kod błędu, wyjątek) między brakiem dyskietki a włożoną pustą dyskietką.

0

Nie mam stacji dyskietek i nie sprawdzę ale powinno działać rozwiązanie które podałem w temacie dotyczącym napędu optycznego Płyta w napędzie optycznym

0
roket napisał(a):

Jak sprawdzić czy w stacji znajduje się dyskietka??

Funkcja GetVolumeInformation wszystko ci powie.

0
kAzek napisał(a):

Nie mam stacji dyskietek i nie sprawdzę ale powinno działać rozwiązanie które podałem w temacie dotyczącym napędu optycznego Płyta w napędzie optycznym

Dzięki - pomogło!! Wystarczyła tylko jedna linijka o niewyświetlaniu komunikatu o braku dyskietki w połączeniu z tym kodem który miałem na początku :D

0
 function CzyDyskGotowy(Dysk: string): Boolean;
var
 Oem: Word;
 D1, D2: Dword;
begin
 {
 Jeśli jest to folder to pomiń
 można to poznać po dłuższej etykiecie niż X:\
 }
 if Length(Dysk) > 3 then
   begin
    Result := True;
    
    Exit;
   end;
   
 Oem := SetErrorMode(SEM_FAILCRITICALERRORS);
 {lub:
  Oem := SetErrorMode(sem_NoOpenFileErrorBox);
 lub:
  Oem := SetErrorMode(SEM_FAILCRITICALERRORS and sem_NoOpenFileErrorBox);
 }
 if Length(Dysk) = 1 then Dysk := Dysk + ':\';
 Result := GetVolumeInformation(pChar(Dysk), nil, 0, nil, D1, D2, nil, 0);
 SetErrorMode(Oem);
end;

{Wykorzystanie}
if Dysk('A:\') then ShowMessage('Dysk [A] jest gotowy!')
else ShowMessage('Dysk [A] nie jest gotowy!');

{Lub}
procedure TForm1.Button1Click(Sender: TObject);
begin
 {$I-}
 SetErrorMode(sem_NoOpenFileErrorBox);   // <- ciche sprawdzenie bez komunikatów
 if fileexists(...) then showmessage('jest') else showmessage('nie ma');
 IOResult;
 {$I+}
end;
1

Rany, co to za horror??

  1. Zdecyduj się, czy funkcja nazywa się Dysk, czy może zmienna
function CzyDyskGotowy(Dysk: string): Boolean;

{...}

if Dysk('A:\') then ShowMessage('Dysk [A] jest gotowy!')
  1. Co to za zwracanie True, jeśli podano nieprawidłowe dane??
 if Length(Dysk) > 3 then
   begin
    Result := True;
 
    Exit;
   end;
  1. Jaki rezultat zwraca funkcja CzyDyskGotowy? (pomijając to koszmarne True)?

  2. Dlaczego to nie jest w osobnej metodzie, tylko wklejone w OnClick?

 {$I-}
 SetErrorMode(sem_NoOpenFileErrorBox);   // <- ciche sprawdzenie bez komunikatów
 if fileexists(...) then showmessage('jest') else showmessage('nie ma');
 IOResult;
 {$I+}
  1. Jak zachowa się funkcja jeśli podamy folder sieciowy?

  2. Jest coś takiego jak "IncludeTrailingPathDelimiter(nazwa_udziału)", konstrukcja

if Length(Dysk) = 1 then Dysk := Dysk + ':\';

jest rodem z majaczeń początkującego programisty.

  1. Jak można napisać 942 posty nie umiejąc porządnie programować w tak prostym i eleganckim języku? Tylko nie tłumacz, że przeklejałeś z istniejącego rozwiązania i Ci się poplątało, chcesz pomóc to rób to porządnie, a nie na kolanie. W tak krótkim kawałku kodu popełniłeś tyle kaszan, że u mnie wyleciałbyś za drzwi z hukiem.

K-O-S-Z-M-A-R

0

6a)

if Dysk('A:\') then ShowMessage('Dysk [A] jest gotowy!') 

Polecam rozważenie konstrukcji:

if Dysk('B:\') then ShowMessage('Dysk [A] jest gotowy!')

Raaaanyyyyyyyyy...

0

To rozwiązanie nie jest takie złe; Stosowałem je co prawda nie dla dyskietek, a dysków twardych, przenośnych i optycznych przed pobraniem label'a; Przydawał się wtedy, gdy potrzebowałem nadać label dla napędu optycznego - jeśli był dostępny (płyta była w napędzie) to pobierałem jej nazwę, a jeśli nie - ustawiałem domyślną (np. Stacja dysków (H:));

Jedyną różnicą jest fakt, że najpierw sprawdzałem czy w ogóle taki dysk istnieje, potem jeśli jego typ był taki jak mam obsługiwać (czyli np. [DRIVE_FIXED, DRIVE_REMOVABLE, DRIVE_CDROM]) i jeśli pasuje to dopiero wtedy sprawdzałem jego dostępność; Tyle, że wyszukiwanie wszystkich dysków oparte było na pętli ['A' .. 'Z'], np. coś w tym stylu:

uses
  Windows,
  SysUtils;

  function DriveAvailable(const ADriveChr: Char): Boolean;
  var
    wErrorMode: Word;
  begin
    Result := False;
    wErrorMode := SetErrorMode(SEM_FAILCRITICALERRORS);

    try
      Result := DiskSize(Ord(ADriveChr) - $40) <> -1;
    finally  //zmienione z except
      SetErrorMode(wErrorMode);
    end;
  end;

  function GetVolumeLabel(const ADriveChr: Char): String;
  var
    dwNotUsed, dwFlags, dwSerialNr: Cardinal;
    aBuffer: array [0 .. MAX_PATH] of Char;
  begin
    GetVolumeInformation(PChar(ADriveChr + ':\'), aBuffer, Succ(MAX_PATH),
                         @dwSerialNr, dwNotUsed, dwFlags, nil, 0);
    SetString(Result, aBuffer, StrLen(aBuffer));
  end;

var
  cDriveChr: Char;
  dwDriveType: Cardinal;
  sDriveLbl: String;
begin
  for cDriveChr := 'A' to 'Z' do
  begin
    dwDriveType := GetDriveType(PChar(cDriveChr + ':\'));

    if dwDriveType in [DRIVE_FIXED, DRIVE_REMOVABLE, DRIVE_CDROM] then
    begin
      if DriveAvailable(cDriveChr) then
        sDriveLbl := GetVolumeLabel(cDriveChr) + ' (' + cDriveChr + ':)';

      case dwDriveType of
        DRIVE_FIXED, DRIVE_REMOVABLE: { do something } ;
        DRIVE_CDROM: begin
                       if sDriveLbl = '' then
                         sDriveLbl := 'Stacja dysków (' + cDriveChr + ':)';

                       { do something }
                     end;
      end;
    end;
  end;

  { do something }
  ReadLn;
end.

I działało bez zarzutów; Sugerowałem się kiedyś wypowiedzią @kAzek'a oraz notką z MSDN - GetVolumeInformation:

Remarks napisał(a)

When a user attempts to get information about a floppy drive that does not have a floppy disk, or a CD-ROM drive that does not have a compact disc, the system displays a message box for the user to insert a floppy disk or a compact disc, respectively. To prevent the system from displaying this message box, call the SetErrorMode function with SEM_FAILCRITICALERRORS.

Ale tak jak napisał @pelsta - wszystko powie sama funkcja GetVolumeInformation bez kombinowania z cichym pobieraniem rozmiaru nośnika;

0

W podobny sposób wyszukiwałem podłączone do czytnika karty pamięci.

var
  Drive:Char;
  VolumeName:array[0..MAX_PATH] of Char;
  mcl,fsf,vsn:DWORD;
  Path,Name:string;
  f:TextFile;
  p:Integer;
begin
  for Drive:='A' to 'Z' do
  begin
    Path:=Drive+':\';
    if (GetDriveType(PChar(Path))=DRIVE_REMOVABLE) and GetVolumeInformation(PChar(Path),VolumeName,SizeOf(VolumeName),@vsn,mcl,fsf,nil,0)) then
    begin
      Name:='';
      if FileExists(Path+'autorun.inf') then
      begin
        AssignFile(f,Path+'autorun.inf');
        Reset(f);
        while not Eof(f) do
        begin
          Readln(f,Name);
          p:=Pos('label=',LowerCase(Name));
          if p=0 then Name:=''
          else
          begin
            Name:=Copy(Name,p+6,MaxInt);
            Break;
          end;
        end;
        CloseFile(f);
      end;
      if Name='' then Name:=VolumeName;
      if Name='' then Name:='Dysk wymienny';
      //...
      //dalsze wykorzystanie Drive i Name
      //...
    end;
  end;
end;
1

Pętla po wszystkich literach alfabetu nie jest elegancka :)

Google + Delphi enum disk drives, pierwszy link na liście:

http://www.swissdelphicenter.ch/torry/showcode.php?id=562

Rozwiązanie "nie takie złe" jest koszmarne - obsługa błędów która tak naprawdę nic nie obsługuje, zwracanie true gdy podano złe dane wejściowe, zaszywanie w kodzie na stałe danych, brak znajomości podstawowych wbudowanych funkcji... wystarczy.

0

Jezus Maria!! A wy się tu rozpisujecie z tymi kodami :D . Ja już mówiłem czego mi brakowało :D

unit Diskette;

interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

function DisketteExists(ExpectedResult:boolean) : boolean;

implementation

function DisketteExists(ExpectedResult:boolean) : boolean;
var
plik : file;
ER:boolean;
  ErrorMode: Word;
begin
   ErrorMode := SetErrorMode(SEM_FAILCRITICALERRORS) ;
  AssignFile(plik, 'A:\plik.xxx');
  try
    Rewrite(plik);
    CloseFile(plik);
    Erase(plik);
    ER:=true;  //jesli może zapisac - true
  except
    on EInOutError do
       begin
        ER:=false;   //iesli nie moze zapisac - false
       end;
  end;
case ExpectedResult of
true : Result:=ER;
false : Result:= not ER;
end;
end;

end.
 
0

@Furious Programming jak się powołujesz na mnie to gdzie ja w tym wypadku stosowałem try except ?
@Opi wypadało by jakiś try finally w celu podanym niżej
@pelsta co to ma wspólnego z tematem nie szukamy napędu tylko sprawdzamy czy dysk (w tym wypadu dyskietka) jest w napędzie.
@roket jak już się produkujesz i wykorzystujesz SetErrorMode to później wypadało by przywrócić pierwotną obsługę błędów.

Tak w ogóle to już autor sobie poradził więc nie wiem po co nagle tyle i to nieprawidłowo napisanych kodów.

0

Mój kod jest dobry i ma związek z tematem, tylko trzeba dokładnie przeczytać przed krytyką...

Ten fragment sprawdza, czy karta/dyskietka jest w czytniku/napędzie:

if (GetDriveType(PChar(Path))=DRIVE_REMOVABLE) and GetVolumeInformation(PChar(Path),VolumeName,SizeOf(VolumeName),@vsn,mcl,fsf,nil,0)) then
0
kAzek napisał(a):

@roket jak już się produkujesz i wykorzystujesz SetErrorMode to później wypadało by przywrócić pierwotną obsługę błędów.

Dzięki!! Dopisałem to na końcu

ErrorMode := SetErrorMode(0) ;

;)

0

@peista

Pętla po literach alfabetu jest w tym przyp. bardziej eleganckim i czytelnym rozwiązaniem. Jeśli tego nie rozumiesz to twój problem.

Jeśli uważasz, że brute force jest bardziej eleganckie - współczuję Twoim klientom :]

I oczywiście prościej jest iterować po nieistniejących dyskach, ergo - wykonać 26 razy konkretne czynności (nie chce mi się sprawdzać jaki jest timeout) niż sprawdzić jakie naprawdę są w systemie... Powodzenia.

0

"przecież jeśli mowa o dyskietkach, to wystarczy sprawdzić A: i B: - Azarien"

Odpowiedź na jedno z moich pytań z dzieciństwa została udzielona :D - zawsze się zastanawiałem dlaczego dyski zaczynaja się od C:, a nie B:\ :D

0

"W moim następnym poście pokazałem ci, w jaki prosty sposób można sprawdzić, czy nośnik jest w dowolnym napędzie. Zrób sobie z tego funkcję jak chcesz. - pelsta"

Tu konkretnie chodziło o dyskietkę, więc do tego jest to dobre. Gorzej gdyby sprawdzać płytę w ten sposób, bo wtedy nie da się zapisać pliku.

0

W czym problem?
Mój sposób dokonuje sprawdzenia czy nośnik jest w napędzie/czytniku bez dokonywania próby zapisu.

0

Ale kombinujecie. Podałem odpowiedź już na początku wątku.

uses sysutils;

var sr:TSearchRec;

begin
   writeln(FindFirst('a:\*.*', faAnyFile, sr));
   findclose(sr);
end.

brak stacji:
-3

jest stacja, brak dyskietki:
-152

dyskietka uszkodzona (nieczytelna):
-237

pusta dyskietka:
-18

dyskietka z plikiem
0

dyskietka z plikiem ukrytym
0

To samo trzeba by zrobić dla b:\*.*.

0

Ciekawy pomysł, ale...

W przypadku nie przyporządkowania literze fizycznego napędu zwraca wartość 3 (np brak napędu dyskietek w laptopie);

W przyp. braku nośnika w napędzie zwraca wartość 21 (np CDROM);

W przyp. czytnika kart podłączonego przez USB:

  • jeżeli brak nośnika, pojawia się komunikat systemowy "Brak dysku..." i zwraca wartość 21;
  • jeżeli brak plików na nośniku, zwraca wartość 2.

Dlatego w moim programie musiałem trochę pokombinować aby pominąć komunikat systemowy i takie rozwiązanie zaproponowałem.

0

Owszem ale konieczność reakcji usera na komunikat

Clipboard01.png

jest wkurzająca.
Tego chciałem uniknąć.

0

w moim kodzie jest rozwiązanie ;)

0

a ja mam pod a: nagrywarkę dvd. być może nawet jest w niej płyta.

0

@zaraz_zaraz
Podany przeze mnie kod jest z archiwum. Prezentuje metodę, ale wymaga optymalizacji.
Skoro już się czepiasz, to zauważ, że nie odpowiedziałem tobie tylko pytającemu, któremu to może wystarczyć lub sobie to usprawni. Ma podbudowę pod rozwój tej metody.

1
Opi napisał(a):

@zaraz_zaraz
Podany przeze mnie kod jest z archiwum. Prezentuje metodę, ale wymaga optymalizacji.
Skoro już się czepiasz, to zauważ, że nie odpowiedziałem tobie tylko pytającemu, któremu to może wystarczyć lub sobie to usprawni. Ma podbudowę pod rozwój tej metody.

No tym razem "się nie czepiałem", tylko pokazałem kilka co najmniej wątpliwej jakości miejsc w kodzie. Żadnego z tych miejsc obronić nie potrafisz, bo nie da się. A wpuszczanie kogoś w źle skonstruowaną i wykonaną obsługę błędów z twierdzeniem, że to podbudowa którą sobie może usprawnić - to sadyzm, bo to trzeba byłoby napisać od nowa :)

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