Wie Medium aus Laufwerk auswerfen (Eject)

05/06/2009 - 16:51 von Christian Stelte | Report spam
Hallo!

Ich überarbeite gerade ein àlteres, spezielles Kopierprogramm welches in
Delphi geschrieben wurde. Dieses besitzt unter anderem die Funktion nach
erfolgreichem Backup das Medium auszuwerfen. Dazu nutzt das alte Programm
'mciSendString'. Diese Lösung findet man ja auch für C#:

using System.Runtime.InteropServices;
[DllImport("winmm.dll")] static extern Int32 mciSendString(string Befehl,
string buffer, int bufferSize, IntPtr hwndCallback);

private void SchubladeÖffnen() { mciSendString("set CDAudio door open",
null, 127, (IntPtr)0); }
private void SchubladeSchließen() { mciSendString("set CDAudio door closed",
null, 127, (IntPtr)0); }

Das Problem an der Sache ist, das es mit CD/DVD und dem REV funktioniert,
aber z.B. mit dem RDX Quickstor nicht.
Mit dem Rev geht es wahrscheinlich da es sich als UDF-Brenner anmeldet,
soweit ich das überblicke. Das RDX ist aber eine Art Wechselfestplatte. In
den Medien scheinen 2,5" HDDs zu sein, zumindest sehen sie von hinten so
aus.

Da es aus dem Explorer heraus funktioniert (Kontextmenü -> Auswerfen) muss
es ja noch eine andere Art geben, ein Laufwerk auszuwerfen.

Habt Ihr eine Idee wohin meine Suche gehen muss?

MfG
Chris
 

Lesen sie die antworten

#1 Frank Dzaebel
05/06/2009 - 21:21 | Warnen spam
Hallo Christian,

Ich überarbeite gerade ein àlteres, spezielles Kopierprogramm welches
in Delphi geschrieben wurde. Dieses besitzt unter anderem die
Funktion nach erfolgreichem Backup das Medium auszuwerfen. Dazu nutzt
das alte Programm 'mciSendString'.



Das ist aber mehr oder weniger unsauber.
Offiziell muss man AFAIK die Treiber ansprechen.

[How To Ejecting Removable Media in Windows NT/Windows 2000/Windows XP]
http://support.microsoft.com/kb/165721/en-us

Folgendes ist auf Vista getestet (aber sonst ungeprüft) :

//=// Form1.cs:
// ...
private void button1_Click(object sender, EventArgs e)
{
Drive.Eject("D:");
}
// ...


//==// Drive.cs:
using System;
using System.Runtime.InteropServices;
using System.Threading;

public class Drive
{
const int INVALID_HANDLE_VALUE = -1;
const int GENERIC_READ = unchecked((int)0x80000000);
const int GENERIC_WRITE = unchecked((int)0x40000000);
const int FILE_SHARE_READ = unchecked((int)0x00000001);
const int FILE_SHARE_WRITE = unchecked((int)0x00000002);
const int OPEN_EXISTING = unchecked((int)3);

const int FSCTL_LOCK_VOLUME = unchecked((int)0x00090018);
const int FSCTL_DISMOUNT_VOLUME = unchecked((int)0x00090020);

const int IOCTL_STORAGE_EJECT_MEDIA = unchecked((int)0x002D4808);
const int IOCTL_STORAGE_MEDIA_REMOVAL = unchecked((int)0x002D4804);


[DllImport("kernel32.dll", EntryPoint = "CreateFileW",
private static extern IntPtr CreateFile(
string lpFileName, int dwDesiredAccess,
int dwShareMode, IntPtr lpSecurityAttributes,
int dwCreationDisposition,
int dwFlagsAndAttributes, IntPtr hTemplateFile);

[DllImport("kernel32.dll", ExactSpelling = true,
SetLastError = true)]
private static extern bool CloseHandle(IntPtr handle);

[DllImport("kernel32.dll", ExactSpelling = true,
SetLastError = true)]
private static extern bool DeviceIoControl(
IntPtr hDevice, int dwIoControlCode,
byte[] lpInBuffer, int nInBufferSize,
byte[] lpOutBuffer, int nOutBufferSize,
out int lpBytesReturned, IntPtr lpOverlapped);

public static bool Eject(string driveName)
{
bool ok = false;
bool KarteKannEntnommenWerden = false;
// Schritt 1: Volume öffnen
IntPtr h = CreateFile(@"\\.\" + driveName, GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
if (h.ToInt32() == -1) return false;

while (true)
{
// Schritt 2: Volume sperren
for (int i = 0; i < 10; i++)
{
int nout = 0;
ok = DeviceIoControl(h, FSCTL_LOCK_VOLUME,
null, 0, null, 0, out nout, IntPtr.Zero);
if (ok) break;
Thread.Sleep(500);
}
if (!ok) break;


// Schritt 3: Volume dismounten
int xout = 0;
ok = DeviceIoControl(h, FSCTL_DISMOUNT_VOLUME,
null, 0, null, 0, out xout, IntPtr.Zero);
if (!ok) break;

KarteKannEntnommenWerden = true;


// Schritt 4: Prevent Removal Of Volume
byte[] flg = new byte[1];
flg[0] = 0; // 0 = false
int yout = 0;
ok = DeviceIoControl(h,
IOCTL_STORAGE_MEDIA_REMOVAL, flg, 1,
null, 0, out yout, IntPtr.Zero);
if (!ok)
break;


// Schritt 5: Eject Media
ok = DeviceIoControl(h,
IOCTL_STORAGE_EJECT_MEDIA,
null, 0, null, 0, out xout, IntPtr.Zero);
break;
}


// Schritt 6: Close Handle
ok = CloseHandle(h);
return KarteKannEntnommenWerden;
}
}

//http://groups.google.com/group/micr...5fb39b99f5


ciao Frank
Dipl.Inf. Frank Dzaebel [MCP/MVP C#]
http://Dzaebel.NET

Ähnliche fragen