Delphide gelistirdigim bir program SD karta bir dosya yaziyor ve ekranda "Islem Tamam" mesaji veriyor.
Bende bu mesaji gorunce SD karti cikartiyorum. Biraz sonra windows gecikmeli yazma islemi var erken cikarttiniz gibi hata veriyor. Halbuki en az 1 sn beklemisim.
Neyse;
Delphi program Islem Tamam mesaji vermeden once dosyanin gercekten yazilip yazilmadigini test etsin ardindan islem tamam mesaji versin istiyorum.
Nasil bir cozum gerekiyor?
(OS: XP)
Hocam az buçuk C bilgim var. Buna galiba flush işlemi deniyor. Eğer delphinin flush işlemi tamamlandi mi tamamlanmadi mi diye windows un api lerini kullanip size geri döndürecek bir araci varsa onu deneyebilirsiniz.
Aygıtı çıkar seçeneğini denersen garanti olur.
Aygıt meşgul cevabını alırsın.
meşguliyet bittiğinde zaten aygıtı ayırmış olursun.
format türünü değiştirmek işe yarayabilir. Fat,FaT32,ntfs,exFAT
Aygıt yöneticisinde , disk sürücülerin altındaki disk sürücünüzü bulup , sağ tuş özellikler ve ardından ilkeler e tıklayıp. önbelleğe yazma ilkesindeki , aygıta yazma önbelleğini (cache) kapatın. Bu durumda uygulamanız direkt diske yazmaya başlayacaktır. Umarım bu şekilde sorununuz çözülür.
Format turunu degistiremem. (Zormat bana ozel)
mesaj birleştirme:: 06 Kasım 2014, 09:32:34
@Diot
Bu islemi programa nasil yaptiririm?
Cunku program her hangi bir kisiye verilecek. O kisiden bu tur islemler yapmasini istemem.
registry den ilgili anahtarı değiştirmeniz lazım ama hangi anahtar bunu şu an bilmiyorum.
mesaj birleştirme:: 06 Kasım 2014, 09:42:44
HKLM\System\CurrentControlSet\Enum\IDE\<yourDiskName>\<serial no>\Device
Parameters\Disk\UserWriteCacheSetting = 0x0
0x0 = disable and 0x00000001 = enabled. It is a REG_DWORD.
olması lazım bir kontrol et istersen
Hocam son yazdığın bilgiyi yazıp yazmadığını kontrol etsen? Yani sonuçta ramden sd karta yazıyorsun. SD kartta dosyanın sonuna gitsen ve file pointerini okusan. Sonuçta sd karta yazacağın verilerin senin ram in de ve sen onları dosyaya yazıyorsun. File pointer ve veri karşılaştırması sorunu çözer mi acaba?
Registryde degisiklik yapmadim. Buna her makine yetki vermeyebilir.
Sorunum hala devam ediyor.
64 K uzunlugunda dosya SD karta yazildi mesaji verdigimde SD kartta 64 K dosyami goruyorum.
65536. kayita git dedigimde gidiyor da.
Isletim sisteminde debug ile icine girip geziyorum her sey ok.
Fakat SD karti sokmeye kalktigimda gecikmeli yazma islemi hatasi aliyorum.
Isin kotusu bu hata SD kartin MBR unda check disk yapilmali bitinin set olmasina neden oluyor bu da uygulamamda hataya neden oluyor.
Hocam işletim sistemi ile kullandığınız dll arasında bir iletişimsizlikten kaynaklı olabilir mi. Yani yazdıktan sonra yapılması gerekli bir close işlemi vb.. Kullandığınız dll in manueline bakmak gerekiyordur belki.
Yukarıdada belirtmiştim. HDD cache aktif iken bu sorunlar devam edecektir. 2. bir yöntemden bahsedeyim. windows'a usb porta bağlı cihazı güvenli kaldırma istegi yollayın.
DLL falan kullanmiyorum. SD kart isletim sistemi tarafindan depolama elemani olarak goruluyor zaten.
Dosyayi klasik fileopen filewrite komutlari olusturuyorum.
Isletim sisteminde tanimlamalara mudahale etmek istemiyorum. Bu benim isimi gorur ama yazdigim programi musterilerime donanim ile birlikte verecegim ve bu programi gunluk kullanacaklari PC'ye yukleyecekler.
Adamlara registryde ayarlamalari soyle soyle yapin diyemem. Desem de bazi makineler admin passwordu ile korunuyor. En nefret ettigim is, adminle muhatap olmak.
Bu yuzden @Diot bu cozume sicak bakmiyorum.
Benim istedigim su;
Programim yazma islemini yaptiktan sonra isterse 1dk beklesin onemli değil. Yeterki SD karti alabilirsiniz dediginde gecikmeli yazma hatasi ile karsilasmayayim.
Mevcut durumda dosyayi SD kartta olusturuyor ve dosyayi kapatiyorum. Okuma amacli aciyor ve dosya sonunda seek ediyorum. Baktim hatasiz seek de ediyor ediyor SD kartta dosyaniz hazir diye kullaniciya mesaj veriyorum.
Mesaji gorunce SD karti yuvasindan cikartiyorum biraz sonra windows kucuk bir pencerede gecikmeli yazma isleminde hata oldu diyor.
-----------
Eger eject etme isini yazilima yaptirabilirsem sorun kalkacak zira program SD karta dosyaniz hazir dediginde isletim sisteminde mouse ile SD karti eject et dersem bu sorun olusmuyor.
sisteminizdeki Antivirus programı da SD kartı bırakmıyor olabilir. Antivurslerdeki On Access scan kısmı harici medyanın takılıp/takılmadığını ve Dosya okuma/yazma işlemini kontrol ediyor. Ve normalde windowsun işi bitmişken Antivirus programı yüzünde bekleme yapmanız gerekiyor.
Bu durumda NT kernelindeki dosya yazma ve okuma fonksiyonlarını kullanmayıp ASM biliyorsanız . Bios dan destekli INT13H ve DOS çekirdek destekli INT21H kullanarak yazma ve okuma rutinlerini kendiniz yazacaksınız. Şu an aklıma başka bir çözümde gelmiyor. Fakat sd kartı bios altından göreceği konusunda şüphelerim var.
SD kartı yeni nesil kartlarda görebilir zira butür medyalarda boot eyme seçenği var bazı bioslarda
Alıntı yapılan: z - 17 Kasım 2014, 14:59:16
Eger eject etme isini yazilima yaptirabilirsem sorun kalkacak ..
şurda C# için:
http://www.codeproject.com/Articles/13530/Eject-USB-disks-using-C (http://www.codeproject.com/Articles/13530/Eject-USB-disks-using-C)
şurda C++ için:
http://support.microsoft.com/kb/165721 (http://support.microsoft.com/kb/165721)
ve bingo:
http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_24811252.html (http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_24811252.html)
burda da var:
http://stackoverflow.com/questions/434688/how-can-i-remove-a-usb-flash-disk-programmatically-using-delphi (http://stackoverflow.com/questions/434688/how-can-i-remove-a-usb-flash-disk-programmatically-using-delphi)
şuraya da kopyalayalım kaybolur maybolur:
function OpenVolume(ADrive: char): THandle;
var
RootName, VolumeName: string;
AccessFlags: DWORD;
DriveType:Cardinal;
begin
RootName := ADrive + ':\';
DriveType := GetDriveType(PChar(RootName));
case DriveType of
DRIVE_REMOVABLE:
AccessFlags := GENERIC_READ or GENERIC_WRITE;
DRIVE_CDROM:
AccessFlags := GENERIC_READ;
// DRIVE_FIXED:
// AccessFlags := GENERIC_READ or GENERIC_WRITE;
else
Result := INVALID_HANDLE_VALUE;
exit;
end;
VolumeName := Format('\\.\%s:', [ADrive]);
Result := CreateFile(PChar(VolumeName), AccessFlags,
FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
if Result = INVALID_HANDLE_VALUE then
RaiseLastWin32Error;
end;
function LockVolume(AVolumeHandle: THandle): boolean;
const
LOCK_TIMEOUT = 10 * 1000; // 10 Seconds
LOCK_RETRIES = 20;
LOCK_SLEEP = LOCK_TIMEOUT div LOCK_RETRIES;
// #define FSCTL_LOCK_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 6, METHOD_BUFFERED, FILE_ANY_ACCESS)
FSCTL_LOCK_VOLUME = (9 shl 16) or (0 shl 14) or (6 shl 2) or 0;
var
Retries: integer;
BytesReturned: Cardinal;
begin
for Retries := 1 to LOCK_RETRIES do begin
Result := DeviceIoControl(AVolumeHandle, FSCTL_LOCK_VOLUME, nil, 0,
nil, 0, BytesReturned, nil);
if Result then
break;
Sleep(LOCK_SLEEP);
end;
end;
function DismountVolume(AVolumeHandle: THandle): boolean;
const
// #define FSCTL_DISMOUNT_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 8, METHOD_BUFFERED, FILE_ANY_ACCESS)
FSCTL_DISMOUNT_VOLUME = (9 shl 16) or (0 shl 14) or (8 shl 2) or 0;
var
BytesReturned: Cardinal;
begin
Result := DeviceIoControl(AVolumeHandle, FSCTL_DISMOUNT_VOLUME, nil, 0,
nil, 0, BytesReturned, nil);
if not Result then
RaiseLastWin32Error;
end;
function PreventRemovalOfVolume(AVolumeHandle: THandle;
APreventRemoval: boolean): boolean;
const
// #define IOCTL_STORAGE_MEDIA_REMOVAL CTL_CODE(IOCTL_STORAGE_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS)
IOCTL_STORAGE_MEDIA_REMOVAL = ($2d shl 16) or (1 shl 14) or ($201 shl 2) or 0;
type
TPreventMediaRemoval = record
PreventMediaRemoval: BOOL;
end;
var
BytesReturned: Cardinal;
Pmerhabauffer: TPreventMediaRemoval;
begin
Pmerhabauffer.PreventMediaRemoval := APreventRemoval;
Result := DeviceIoControl(AVolumeHandle, IOCTL_STORAGE_MEDIA_REMOVAL,
@Pmerhabauffer, SizeOf(TPreventMediaRemoval), nil, 0, BytesReturned, nil);
if not Result then
RaiseLastWin32Error;
end;
function AutoEjectVolume(AVolumeHandle: THandle): boolean;
const
// #define IOCTL_STORAGE_EJECT_MEDIA CTL_CODE(IOCTL_STORAGE_BASE, 0x0202, METHOD_BUFFERED, FILE_READ_ACCESS)
IOCTL_STORAGE_EJECT_MEDIA = ($2d shl 16) or (1 shl 14) or ($202 shl 2) or 0;
var
BytesReturned: Cardinal;
begin
Result := DeviceIoControl(AVolumeHandle, IOCTL_STORAGE_EJECT_MEDIA, nil, 0,
nil, 0, BytesReturned, nil);
if not Result then
RaiseLastWin32Error;
end;
function EjectVolume(ADrive: char): boolean;
var
VolumeHandle: THandle;
begin
Result := FALSE;
// Open the volume
VolumeHandle := OpenVolume(ADrive);
if VolumeHandle = INVALID_HANDLE_VALUE then
exit;
try
// Lock and dismount the volume
if LockVolume(VolumeHandle) and DismountVolume(VolumeHandle) then begin
// Set prevent removal to false and eject the volume
if PreventRemovalOfVolume(VolumeHandle, FALSE) then
AutoEjectVolume(VolumeHandle);
end;
finally
// Close the volume so other processes can use the dr
CloseHandle(VolumeHandle);
end;
end;
@Bocek
Denedikten sonra cevap yazmayi unutmusum. Sorunumu bu yazilim eklentisi cozdu. Tesekkurler.
Cozum beraberinde kucuk bir sorunu getirdi ama ilki kadar dert degil. Dosya karta yazildiktan sonra eject yapilinca isletim sistemi, gecikmeli yazma islemine oncelik verip yazma isini derhal bitiriyor ardindan SD karti sistem surucu listesinden siliyor.
Kullanici bu asamada bir sey yapmayi unuttugunu farkediyor ve programi tekrar calistiriyor. Ancak SD kart fiziksel olarak takili oldugu halde soft eject isleminden dolayi sistemde SD kart yok gorunuyor. Tek cozumu SD karti sokup tekrar takmak.
Ama hic dert etmiyorum artik.
Hocam işinizin görülmesine sevindim. Bahsettiğiniz problemden verdiğim linklerde de bahsediliyordu ama bu aslında br problem olarak görülmemeli. Nasıl ki mesela sisteme harici bir hd taktık, işimizi gördük bitirdik ve remove vs. diyerek bağlantısını kopardık. Sonra bir dosya kopyalamayı unuttuğumuzu gördük tekrar diske erişmeye çalıştığımızda ne yapmamız gerekiyor? Çıkarıp takmamız.
Sizinki de aynı aslında ve bunun başka bir yolu yok.