Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Klatsch und Tratsch (https://www.delphipraxis.net/34-klatsch-und-tratsch/)
-   -   Tool für selektives AutoPlay? [Windows 7] (https://www.delphipraxis.net/162270-tool-fuer-selektives-autoplay-%5Bwindows-7%5D.html)

ehX 15. Aug 2011 12:59

Tool für selektives AutoPlay? [Windows 7]
 
Hallo zusammen,

ihr kennt ja sicher das AutoPlay-Feature von Windows: Man steckt z.B. einen USB-Stick rein und Windows öffnet dann das (oft wenig hilfreiche, überladene) Fenster, in dem man die Auswahl hat, was ausgeführt werden soll.
Mich hat dieses Feature immer genervt, da eh oft die falschen Optionen angeboten wurden, darum habe ich es abgeschaltet.

Das ist aber auch nicht gänzlich optimal...ich würde es. z.B. gerne haben, dass beim Einstecken meines verschlüsselten USB-Sticks automatisch die EXE gestartet wird, die zum Login in den Stick auffordert.
Diese EXE liegt aber in einer ReadOnly-Partition des Sticks, somit kann ich dort keine Autostart.ini oder dergleichen erstellen.
(Edit-Info: Es handelt sich um einen "Kingston DataTraveler 5000")

Lange Rede, kurzer Sinn:
Kennt jemand vielleicht ein Tool, bei dem man eine solche AutoPlay-Funktionalität selektiv einstellen kann?
Heisst, das Programm erkennt einen Stick und man kann für diesen Stick, wenn er das erste Mal gemountet wird, auswählen, was beim Einstecken automatisch gestartet wird.
Wenn man den Stick einmal konfiguriert hat, passiert das dann in Folge automatisch (Das zuvor ausgewählte Programm wird immer gestartet, sobald man diesen Stick reinsteckt).
Gibt es so etwas überhaupt?

Neutral General 15. Aug 2011 13:01

AW: Tool für selektives AutoPlay? [Windows 7]
 
Weiß nicht ob es sowas gibt, aber sollte auch nicht allzu schwer sein sich so ein Tool selbst zu schreiben :)

ehX 15. Aug 2011 13:14

AW: Tool für selektives AutoPlay? [Windows 7]
 
Gute Idee, allerdings gibt es da dann doch noch ein paar Hürden für mich...Erkennen, wann ein USB-Stick gemountet wird und dann eindeutig identifizieren....mal googlen :-D

Neutral General 15. Aug 2011 14:29

AW: Tool für selektives AutoPlay? [Windows 7]
 
MSDN-Library durchsuchenWM_DEVICECHANGE

MSDN-Library durchsuchenGetVolumeInformation

MSDN-Library durchsuchenRegisterDeviceNotification + MSDN-Library durchsuchenDEV_BROADCAST_VOLUME

Das sollte helfen ;)

Habe hier mal auf die schnelle einen sehr hässlichen, aber funktionierenden Code zusammengeschustert:

Delphi-Quellcode:
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    ListBox1: TListBox;
  private
    { Private-Deklarationen }
  public
    procedure WMDevChange(var Msg: TMessage); message WM_DEVICECHANGE;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

const
  DBT_DEVICEARRIVAL = $8000;
  DBT_DEVICEREMOVECOMPLETE = $8004;

{ TForm1 }

procedure TForm1.WMDevChange(var Msg: TMessage);
var DevName: Array[0..MAX_PATH] of Char;
    FileSys: Array[0..MAX_PATH] of Char;
    SN: DWORD;
    DevFlags, MaxLen: DWORD;
begin
  if Msg.WParam = DBT_DEVICEARRIVAL then
  begin
    GetVolumeInformation('G:\',@DevName[0],MAX_PATH+1,@SN,MaxLen,DevFlags,@FileSys[0],MAX_PATH+1);
    ListBox1.Items.Add('Laufwerk: G:');
    ListBox1.Items.Add('Bezeichnung: ' + String(DevName));
    ListBox1.Items.Add('Dateisystem: ' + String(FileSys));
    ListBox1.Items.Add('Serien-Nr.: ' + IntToStr(SN));
  end
  else
  if Msg.WParam = DBT_DEVICEREMOVECOMPLETE then
    ListBox1.Items.Clear;
end;

end.

jaenicke 15. Aug 2011 14:52

AW: Tool für selektives AutoPlay? [Windows 7]
 
Eine Alternative wäre einfach die integrierte Autoplayfunktion so anzupassen wie man es möchte statt diese abzuschalten...

Unter "Automatische Wiedergabe" finden sich in der Systemsteuerung bereits die wichtigsten Optionen.

Und wenn man eigene Einträge braucht, gibt es diverse Tools dafür:
http://www.snapfiles.com/get/AutoplayRepair.html

ehX 15. Aug 2011 15:24

AW: Tool für selektives AutoPlay? [Windows 7]
 
Danke euch vielmals!
Das hilft schonmal extrem weiter. :-)
Welche Lösung ich nun nehme, zeigt, ob ich das mit dem DeviceChange auch sauber implementiert kriege oder ob ich jaenicke's Lösung für ausreichend halte.
Danke aber nochmal, vor Allem auch für das Code-Schnippsel! :thumb:

ehX 15. Aug 2011 15:52

AW: Tool für selektives AutoPlay? [Windows 7]
 
Ok, ich habe mir mal schnell eine kleine Komponente zusammengeschustert, um ein Event zu erzeugen, wenn eine System Volume gemountet / ungemounted wird.

Wer's brauchen kann, hier der Code:

Delphi-Quellcode:
unit ehXDeviceChange;

{
  ehXDeviceChange
  ################

  Component for event notification when a system volume has been mounted or unmounted
  (e.g. removable drives or media)

  Author: blackFin
  Email: blackfin@elfenherz.de
  For: The "Delphi Praxis" community (http://www.delphipraxis.net/)
  Date of creation: 15.08.2011


  License:

  Do what you want with it, but there is one thing that always makes me happy:

  ##############################################################################
  If you modify the source and / or enhance this component,
  pleeeease, send your modified source code back to me via email.
  ##############################################################################

}

interface

uses
  Windows,Messages,SysUtils,Classes,Forms
;

type

  // Events
  TehXDeviceMountedEvent = procedure(ADrive: Char; ADriveName: string) of object ;
  TehXDeviceUnmountedEvent = procedure(ADrive: Char; ADriveName: string) of object ;

  // Class declaration of device change notifier
  TehXDeviceChangeNotifier = class(TComponent)
     private
       FDriveList : array of array[0..1] of string ;
       FMessageHook : boolean ;
       FVolumesMapped : boolean ;

       FOnDeviceMounted : TehXDeviceMountedEvent ;
       FOnDeviceUnmounted : TehXDeviceUnmountedEvent ;

       function FDoMessageHook(var Msg: TMessage): boolean ;
       procedure FOnWMDeviceChange(var Msg: TMessage);

       function FGetVolumeName(FDrive: Char): string;

     protected

     public
      constructor Create(AOwner: TComponent) ; override ;
      destructor Destroy() ; override ;

      procedure CreateVolumeMapping() ;
      function GetVolumeName(FDrive: char): string;

     published
       property OnDeviceMounted: TehXDeviceMountedEvent read FOnDeviceMounted write FOnDeviceMounted ;
       property OnDeviceUnmounted: TehXDeviceUnmountedEvent read FOnDeviceUnmounted write FOnDeviceUnmounted ;
  end;

  procedure Register;

implementation

const
  DRIVE_UNKNOWN = 0;
  DRIVE_NO_ROOT_DIR = 1;
  DRIVE_REMOVABLE = 2;
  DRIVE_FIXED = 3;
  DRIVE_REMOTE = 4;
  DRIVE_CDROM = 5;
  DRIVE_RAMDISK = 6;


// CONSTRUKTOR
constructor TehXDeviceChangeNotifier.Create(AOwner: TComponent) ;
begin
  inherited Create(AOwner) ;
  FVolumesMapped := false ;
  if not (csDesigning in ComponentState) then
  begin
    Application.HookMainWindow(FDoMessageHook);
    FMessageHook := True;
    self.CreateVolumeMapping() ;
  end;

end;

// DESTRUCTOR
destructor TehXDeviceChangeNotifier.Destroy() ;
begin
  SetLength(FDriveList,0) ;
  if FMessageHook then Application.UnhookMainWindow(FDoMessageHook);
  inherited Destroy() ;
end;

// message hook from main window
function TehXDeviceChangeNotifier.FDoMessageHook(var Msg: TMessage): boolean;
begin
  Result := False;
  case Msg.Msg of
     WM_DEVICECHANGE:
     begin
        FOnWMDeviceChange(Msg);
        Result := true ;
     end;
  end;
end;

// on device change
procedure TehXDeviceChangeNotifier.FOnWMDeviceChange(var Msg: TMessage);
  type
    PDevBroadcastHdr = ^TDevBroadcastHdr;
    TDevBroadcastHdr = packed record
      dbcd_size, dbcd_devicetype, dbcd_reserved: DWORD;
    end;
    PDevBroadcastVolume = ^TDevBroadcastVolume;

    TDevBroadcastVolume = packed record
      dbcv_size, dbcv_devicetype, dbcv_reserved, dbcv_unitmask: DWORD;
      dbcv_flags: Word;
    end;

  function GetDrive(pDBVol: PDevBroadcastVolume): string;
  var
    i: Byte;
    VolumeMask: DWORD;
  begin
    case (pDBVol^.dbcv_flags) of
      // removable MEDIA
      0:
        begin
           // todo: do something with this information
        end;

      // removable DRIVE
      1:
        begin
           // todo: do something with this information
        end;
    end;


    VolumeMask := pDBVol^.dbcv_unitmask;
    for i := 0 to 25 do
    begin
      if (VolumeMask and 1) = 1 then Result := Char(i + Ord('A')) + ': ';
       VolumeMask := VolumeMask shr 1;
    end;

  end;

var Drive,DriveName: String;
begin

  case Msg.wParam of

  // drive has been mounted
  $8000:
      if PDevBroadcastHdr(Msg.lParam)^.dbcd_devicetype = $0002 then
      begin
        Drive := GetDrive(PDevBroadcastVolume(Msg.lParam));
        DriveName := FGetVolumeName(Drive[1]) ;
        self.CreateVolumeMapping() ;
        if Assigned(FOnDeviceMounted) then FOnDeviceMounted(Drive[1],DriveName) ;
      end;

  // drive has been unmounted
  $8004:
      if PDevBroadcastHdr(Msg.lParam)^.dbcd_devicetype = $0002 then
      begin
         Drive := GetDrive(PDevBroadcastVolume(Msg.lParam));
         if Assigned(FOnDeviceUnmounted) then FOnDeviceUnmounted(Drive[1],self.GetVolumeName(Drive[1])) ;
         self.CreateVolumeMapping() ;
      end;
  end;
end;


// get the name of a volume (internally, from sytem)
function TehXDeviceChangeNotifier.FGetVolumeName(FDrive: Char): string;
var
 max, Flags: DWORD;
 Buf: array [0..MAX_PATH] of Char;
 SN: DWORD;
 FileSys: Array[0..MAX_PATH] of Char;
begin
  try
    GetVolumeInformation(PChar(string(FDrive + ':')), @Buf[0], sizeof(Buf), @SN, max, Flags, @FileSys, 0);
    Result := Buf;
  except
    result := '';
  end;
end;

// get the name of a volume (from volume mapping)
function TehXDeviceChangeNotifier.GetVolumeName(FDrive: char): string;
var
  i: Integer ;
begin
   if (not FVolumesMapped) then self.CreateVolumeMapping() ;

   Result := '' ;

   for i := 0 to High(FDriveList) do
   begin
      if FDriveList[i][0] = FDrive then
      begin
        Result := FDriveList[i][1] ;
        break ;
      end;
   end;
   
end;


// get all currently available volume names
procedure TehXDeviceChangeNotifier.CreateVolumeMapping() ;
var
  r: LongWord;
  Drives: array[0..128] of char;
  pDrive: PChar;
begin

  SetLength(FDriveList,0) ;

  r := GetLogicalDriveStrings(SizeOf(Drives), Drives);

  if r = 0 then Exit;

  if r > SizeOf(Drives) then
    raise Exception.Create(SysErrorMessage(ERROR_OUTOFMEMORY));

  pDrive := Drives;

  while pDrive^ <> #0 do
  begin
    case GetDriveType(pDrive) of
     DRIVE_FIXED,
     DRIVE_CDROM,
     DRIVE_REMOVABLE:
     begin
       // Anyone that uses still floppy drives? No, Tux SysAdmins, not you! :-)
       // Well, I've skipped reading the mapping on floppy drives A:\ and B:\ because reading the volume names of floppy drives is sooo slow :-(
       // Unfortunately, floppy drives have no own DriveType, they are listed as DRIVE_REMOVABLE, so extra handling of those is not clearly possible.
       // (comment out next line if you want to enable volume mapping on floppy dives A:\ and B:\, too)
       if ( (pDrive <> 'A:\') and (pDrive <> 'B:\') ) then
       begin
         SetLength(FDriveList,High(FDriveList)+2) ;
         FDriveList[High(FDriveList)][0] := string(pDrive[0]) ;
         FDriveList[High(FDriveList)][1] := self.FGetVolumeName(pDrive[0]) ;
       end;
     end;
    end;

    Inc(pDrive,4);
  end;

  FVolumesMapped := true ;

end;


// Register component in ehX Toolbar
procedure Register;
begin
  RegisterComponents('ehX', [TehXDeviceChangeNotifier]);
end;

end.

devidespe 15. Aug 2011 16:52

AW: Tool für selektives AutoPlay? [Windows 7]
 
@ehX: könnte man diese Komponente dahin gehend anpassen, dass die Autorun-Funktion von optischen Laufwerken (CD/DVD/BD) unterbunden wird? Erkannt wird der Gerätewechsel ja irgendwie, aber wie dann Autorun verhindern?

ehX 15. Aug 2011 17:54

AW: Tool für selektives AutoPlay? [Windows 7]
 
@devidespe:
Da AutoPlay eine globale Funktion des Betriebssystems ist, die nicht an ein Programm gebunden ist, kann das ein einzelnes Programm AFAIK nicht verhindern.
Die Komponente reagiert ja nur auf eine Device-Change Message des OS, kann sich aber nicht "rein-hooken".
Allerdings kann man AutoPlay ja in Windows generell abschalten und dann nur noch die Komponente verwenden.
Der Device-Change Event wird ja auch erzeugt, wenn AutoPlay in Windows deaktiviert ist.

devidespe 15. Aug 2011 18:16

AW: Tool für selektives AutoPlay? [Windows 7]
 
Autoplay in Windows abzuschalten, erfordert einen Neustart - den ich leider nicht durchführen kann. Es gibt hier im Forum verschiedene Lösungen, die allesamt auf QueryCancelAutoplay basieren, das funzt allerdings ab Windows 7 nicht mehr.

Die Alternative iQueryCancelAutoplay erfordert wiederum einen COM Server und ich habe mich da noch nicht drangewagt. Deswegen dachte ich, dass die Komponente evtl. helfen kann...


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:40 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz