Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Changes to command line - many fixes:

Fixed - problem with commandline - if drive letter called as lower case ExtractFilePath - would pass the letter as lower case
Fixed - EmumWindows - problem - explorer windows are now closed successfully again
Fixed - Ejecting mountpoint from command line - case mattered - even when doing /REMOVETHIS - now looks up the correctly cased mountpoint name
Fixed - quotes around params when restarting in mobile mode
Fixed - /REMOVELETTER not restarting in mobile mode when attempting to eject self

Changes to tree and form - enabled multiline - experimental
  • Loading branch information...
commit b9b0bdf0a0876ba24f76c4fbdd624c7b9446411a 1 parent fa50080
@bgbennyboy authored
View
21 USBDiskEject.dpr
@@ -32,6 +32,7 @@ uses
dialogs,
extctrls,
windows,
+ JclStrings,
formMain in 'formMain.pas' {Mainfrm},
uDriveEjector in 'uDriveEjector.pas',
uDiskEjectConst in 'uDiskEjectConst.pas',
@@ -45,7 +46,7 @@ uses
uCardReaderManager in 'uCardReaderManager.pas';
var
- strTempMountPoint: string;
+ strTempMountPoint, strNewMountPoint: string;
Ejector: TDriveEjector;
EjectErrorCode: integer;
CardEject: boolean;
@@ -80,7 +81,7 @@ begin
{Check if trying to eject drive that program is running from
and check if mobile is false - in case somehow temp folder is on the drive
you're trying to eject}
- if (IsAppRunningFromThisLocation(options.CommandLine_Param_RemoveLetter) ) and
+ if (IsAppRunningFromThisLocation( ConvertDriveLetterToMountPoint(options.CommandLine_Param_RemoveLetter)) ) and
(options.InMobileMode = false) then
begin
StartInMobileMode('/NOSAVE ' + '/REMOVELETTER ' + options.CommandLine_Param_RemoveLetter);
@@ -160,8 +161,8 @@ begin
you're trying to eject}
if ( IsAppRunningFromThisLocation( options.CommandLine_Param_RemoveMountPoint ) ) and
(options.InMobileMode = false) then
- begin
- StartInMobileMode('/NOSAVE ' + '/REMOVEMOUNTPOINT ' + options.CommandLine_Param_RemoveMountPoint);
+ begin //Add quotes back - if param has spaces then param is truncated without the quotes
+ StartInMobileMode('/NOSAVE ' + '/REMOVEMOUNTPOINT ' + StrQuote(options.CommandLine_Param_RemoveMountPoint, '"') );
exit;
end;
@@ -185,7 +186,9 @@ begin
Communicator := TCommunicationManager.Create(MyTrayIcon);
try
- if Ejector.RemoveDrive(options.CommandLine_Param_RemoveMountPoint, EjectErrorCode, options.UseWindowsNotifications, CardEject, options.CloseRunningApps_Ask, options.CloseRunningApps_Force) then
+ //Mountpoints are case sensitive when ejecting so - try and get proper cased mountpoint
+ strNewMountPoint := GetCaseSensitiveMountPointName(options.CommandLine_Param_RemoveMountPoint, Ejector);
+ if Ejector.RemoveDrive(strNewMountPoint, EjectErrorCode, options.UseWindowsNotifications, CardEject, options.CloseRunningApps_Ask, options.CloseRunningApps_Force) then
begin //Eject succeeded
if options.UseWindowsNotifications = false then //If true then windows shows its own message
begin
@@ -243,8 +246,8 @@ begin
you're trying to eject}
if ( IsAppRunningFromThisLocation( strTempMountPoint ) ) and
(options.InMobileMode = false) and (strTempMountPoint <> '')then
- begin
- StartInMobileMode('/NOSAVE ' + '/REMOVEMOUNTPOINT ' + strTempMountPoint);
+ begin //Add quotes if param has spaces then param is truncated without the quotes
+ StartInMobileMode('/NOSAVE ' + '/REMOVEMOUNTPOINT ' + StrQuote(strTempMountPoint, '"'));
exit;
end
else
@@ -330,8 +333,8 @@ begin
you're trying to eject}
if ( IsAppRunningFromThisLocation( strTempMountPoint ) ) and
(options.InMobileMode = false) and (strTempMountPoint <> '')then
- begin
- StartInMobileMode('/NOSAVE ' + '/REMOVEMOUNTPOINT ' + strTempMountPoint);
+ begin //Add quotes - if param has spaces then param is truncated without the quotes
+ StartInMobileMode('/NOSAVE ' + '/REMOVEMOUNTPOINT ' + StrQuote(strTempMountPoint, '"'));
exit;
end
else
View
BIN  USBDiskEject.res
Binary file not shown
View
4 USB_Disk_Eject.cfg
@@ -18,10 +18,10 @@ WindowWidth=345
WindowLeftPos=200
WindowTopPos=200
SnapTo=1
-HideCardReadersWithNoMedia=1
+HideCardReadersWithNoMedia=0
CardPollingInterval=5000
ShowCardReaders=1
-ShowPartitionsAsOne=1
+ShowPartitionsAsOne=0
MaxWidth=0
[Hotkeys]
View
6 formMain.dfm
@@ -73,10 +73,12 @@ object Mainfrm: TMainfrm
TreeOptions.SelectionOptions = [toFullRowSelect, toRightClickSelect]
TreeOptions.StringOptions = [toSaveCaptions, toShowStaticText, toAutoAcceptEditChange]
OnDblClick = TreeDblClick
+ OnDrawText = TreeDrawText
OnGetText = TreeGetText
OnPaintText = TreePaintText
OnGetImageIndex = TreeGetImageIndex
OnGetNodeDataSize = TreeGetNodeDataSize
+ OnInitNode = TreeInitNode
OnKeyPress = TreeKeyPress
OnMouseDown = TreeMouseDown
Columns = <
@@ -140,7 +142,7 @@ object Mainfrm: TMainfrm
Left = 16
Top = 112
Bitmap = {
- 494C01010700D0012C0130003000FFFFFFFF2110FFFFFFFFFFFFFFFF424D3600
+ 494C01010700D0013C0130003000FFFFFFFF2110FFFFFFFFFFFFFFFF424D3600
0000000000003600000028000000C00000006000000001002000000000000020
0100000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
@@ -2529,7 +2531,7 @@ object Mainfrm: TMainfrm
Left = 80
Top = 112
Bitmap = {
- 494C0101090038021C0210001000FFFFFFFF2110FFFFFFFFFFFFFFFF424D3600
+ 494C0101090038022C0210001000FFFFFFFF2110FFFFFFFFFFFFFFFF424D3600
0000000000003600000028000000400000003000000001002000000000000030
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
View
97 formMain.pas
@@ -78,6 +78,11 @@
Option to hide all card readers
Option to show drives with multiple partitions as one entry - with different icon to indicate this
Option to set max width of form - useful eg if mountpoint in a deeply nested folder
+ Fixed - problem with commandline - if drive letter called as lower case ExtractFilePath - would pass the letter as lower case
+ Fixed - EmumWindows - problem - explorer windows are now closed successfully again
+ Fixed - Ejecting mountpoint from command line - case mattered - even when doing /REMOVETHIS - now looks up the correctly cased mountpoint name
+ Fixed - quotes around params when restarting in mobile mode
+ Fixed - /REMOVELETTER not restarting in mobile mode when attempting to eject self
TODO Before Release:
Update credits in readme and about form
@@ -87,8 +92,10 @@
Need to fix in start in mobile mode - need switch for eject card or card reader device
OTHER:
+ ********* Fix multiline on form - static text now not showing******************
Cant tab to the move label on main form
Windows 2000 support is broken
+ Potential problem - EmumWindowsAndClose (and close apps running from) - only closes windows for that drive - not for other partitions - may need to do it for siblings too
Optional/Possibilities/Non-critical:
See mindmap for full list
@@ -159,6 +166,11 @@ TMainfrm = class(TForm)
procedure TreeMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure JvAppInstances1Rejected(Sender: TObject);
+ procedure TreeInitNode(Sender: TBaseVirtualTree; ParentNode,
+ Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
+ procedure TreeDrawText(Sender: TBaseVirtualTree; TargetCanvas: TCanvas;
+ Node: PVirtualNode; Column: TColumnIndex; const Text: string;
+ const CellRect: TRect; var DefaultDraw: Boolean);
private
DrivePopups: array of TMenuItem;
Procedure MinimizeClick(Sender:TObject);
@@ -487,7 +499,7 @@ procedure TMainfrm.GUIRemoveDrive(MountPoint: String; RemoveCard: boolean);
//Check if trying to eject drive that its running from
if IsAppRunningFromThisLocation( MountPoint ) then
begin
- StartInMobileMode('/NOSAVE ' + '/REMOVEMOUNTPOINT ' + StrDoubleQuote(MountPoint));
+ StartInMobileMode('/NOSAVE ' + '/REMOVEMOUNTPOINT ' + StrQuote(MountPoint, '"'));
CloseProgram;
Exit;
end;
@@ -704,6 +716,70 @@ procedure TMainfrm.TreeDblClick(Sender: TObject);
GUIRemoveDrive(MountPoint, RemoveCard);
end;
+procedure TMainfrm.TreeDrawText(Sender: TBaseVirtualTree; TargetCanvas: TCanvas;
+ Node: PVirtualNode; Column: TColumnIndex; const Text: string;
+ const CellRect: TRect; var DefaultDraw: Boolean);
+{var
+ DrawFormat : Cardinal;
+ R : TRect;
+ s : WideString; }
+ {NodeWidth, EllipsisWidth : Integer; }
+ {Size: TSize;
+begin
+ if Column in [0] then
+ begin
+ DefaultDraw := False;
+ R := CellRect;
+ GetTextExtentPoint32W(TargetCanvas.Handle, PWideChar(Text), Length(Text), Size);
+ //NodeWidth := Size.cx + 2 * Tree.TextMargin;
+ GetTextExtentPoint32W(TargetCanvas.Handle, '...', 3, Size);
+ {EllipsisWidth := Size.cx;
+ if ((NodeWidth - 2 * Tree.TextMargin) > R.Right - R.Left) then
+ s := EllipseString(TargetCanvas.Handle, Text, R.Right - R.Left, EllipsisWidth)
+ else s := Text;}
+ {S := Text;
+
+ DrawFormat := DT_NOPREFIX or DT_VCENTER;// or DT_SINGLELINE;
+ Windows.DrawTextW(TargetCanvas.Handle, PWideChar(s), Length(s), R, DrawFormat);
+ end; }
+
+{var
+ R: TRect;
+begin
+ R := CellRect;
+ R.Top := 0;
+ R.Bottom := 0;
+ Windows.DrawText(TargetCanvas.Handle, PChar(String(Text)), Length(Text), R, DT_CALCRECT);
+
+ R.Top := ((CellRect.Bottom - CellRect.Top) - R.Bottom) div 2;
+ if R.Top < 0 then R.Top := 0;
+ Inc(R.Top, CellRect.Top);
+ R.Bottom := CellRect.Bottom;
+
+ Windows.DrawText(TargetCanvas.Handle, PChar(String(Text)), Length(Text), R, DT_END_ELLIPSIS or DT_NOPREFIX or DT_WORDBREAK or
+ DT_EDITCONTROL); }
+
+var
+ DrawRect: TRect;
+ DrawFlags: Cardinal;
+ DrawParams: TDrawTextParams;
+begin
+ defaultdraw:=false; //BUT multiline stops static text being drawn by this and the default vt method
+
+ DrawRect := CellRect;
+ DrawFlags := DT_END_ELLIPSIS or DT_NOPREFIX or DT_WORDBREAK or
+ DT_EDITCONTROL;
+ DrawText(TargetCanvas.Handle, PChar(Text), -1, DrawRect, DrawFlags or DT_CALCRECT);
+ DrawRect.Right := CellRect.Right;
+ if DrawRect.Bottom < CellRect.Bottom then
+ OffsetRect(DrawRect, 0, (CellRect.Bottom - DrawRect.Bottom) div 2)
+ else
+ DrawRect.Bottom := CellRect.Bottom;
+ ZeroMemory(@DrawParams, SizeOf(DrawParams));
+ DrawParams.cbSize := SizeOf(DrawParams);
+ DrawTextEx(TargetCanvas.Handle, PChar(Text), -1, DrawRect, DrawFlags, @DrawParams);
+end;
+
procedure TMainfrm.DrivePopupMenuHandler(Sender: TObject);
var
MountPoint: string;
@@ -922,11 +998,26 @@ procedure TMainfrm.TreeGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
end
else
case texttype of
- ttNormal: CellText:='(' + Ejector.RemovableDrives[Node.Index].DriveMountPoint + ') ' + Ejector.RemovableDrives[Node.Index].VendorId + ' ' + Ejector.RemovableDrives[Node.Index].ProductID;
- ttStatic: CellText:= Ejector.RemovableDrives[Node.Index].VolumeLabel;
+ ttNormal:
+ if Options.ShowPartitionsAsOne and Ejector.RemovableDrives[Node.Index].HasSiblings then //Just show name not mountpoint
+ CellText:=Ejector.RemovableDrives[Node.Index].VendorId + ' ' + Ejector.RemovableDrives[Node.Index].ProductID
+ else
+ CellText:='(' + Ejector.RemovableDrives[Node.Index].DriveMountPoint + ') ' + #13#10 + Ejector.RemovableDrives[Node.Index].VendorId + ' ' + Ejector.RemovableDrives[Node.Index].ProductID;
+
+ ttStatic:
+ if Options.ShowPartitionsAsOne and Ejector.RemovableDrives[Node.Index].HasSiblings then //Dont show the label
+ CellText := ''
+ else
+ CellText:= Ejector.RemovableDrives[Node.Index].VolumeLabel;
end;
end;
+procedure TMainfrm.TreeInitNode(Sender: TBaseVirtualTree; ParentNode,
+ Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
+begin
+ Include(InitialStates, ivsMultiline);
+end;
+
procedure TMainfrm.TreeKeyPress(Sender: TObject; var Key: Char);
begin
if key = #13 then
View
13 uDiskEjectOptions.pas
@@ -32,7 +32,9 @@
interface
uses
Classes, Sysutils, forms, inifiles, JCLFileUtils, JCLSysInfo, JCLStrings,
- uDiskEjectConst, uCustomHotKeyManager, uCardReaderManager;
+ uDiskEjectConst, uCustomHotKeyManager, uCardReaderManager,
+
+ dialogs;
type
TOptions = class (TComponent)
@@ -481,10 +483,17 @@ function TOptions.GetCommandLine_Param_RemoveMountPoint: string;
if (intTemp <> -1) and (ParamCount >= intTemp + 1) then
begin
tempParam:=ParamStr(intTemp + 1); //Paramstr automatically parses out speech marks
- result:=IncludeTrailingPathDelimiter(tempParam) ;
+ tempParam:=Trim(TempParam); //Remove trailing spaces
+
+ if length(tempParam) = 1 then //Its a drive letter on its own
+ result:=IncludeTrailingPathDelimiter(tempParam + ':')
+ else
+ result:=IncludeTrailingPathDelimiter(tempParam);
end
else
result:='';
+
+ //Showmessage('command line param ' + result);
end;
function TOptions.GetCommandLine_Param_RemoveName: string;
View
33 uDiskEjectUtils.pas
@@ -26,7 +26,7 @@
interface
uses Classes, sysutils, windows, forms, jclsysinfo, jclfileutils, jclshell,
- JCLRegistry, dialogs, ShellAPI, JwaWindows,
+ JCLRegistry, dialogs, ShellAPI, JwaWindows, JCLStrings,
uDiskEjectConst, uDriveEjector, uCardReaderManager;
type
@@ -50,6 +50,7 @@ function BalloonTipsEnabled: boolean;
function IsWindowsVistaorLater : Boolean;
function FindMountPoint(Directory: string): string;
function IsAppRunningFromThisLocation(MountPoint: string): boolean;
+function GetCaseSensitiveMountPointName(MountPoint: string; Ejector: TDriveEjector): string;
implementation
@@ -419,6 +420,15 @@ function FindMountPoint(Directory: string): string;
CurrPath := ExtractFilePath( ExcludeTrailingPathDelimiter( CurrPath ) );
end;
+ {Fix - always capitalise the drive letter. If started from command line with lower case drive then ExtractFilePath gives the drive as lower case
+ see http://quick.mixnmojo.com/usb-disk-eject-1-2-beta-4-last-beta-before-release-hopefully#comments for more info}
+ if result <> '' then
+ begin
+ result[1] := Uppercase(Result)[1];
+
+ //Add quotes in case path has spaces - these get stripped out later anyway
+ result := StrQuote(result, '"');
+ end;
end;
function IsAppRunningFromThisLocation(MountPoint: string): boolean;
@@ -469,4 +479,25 @@ function IsAppRunningFromThisLocation(MountPoint: string): boolean;
end;
+{Looks up mountpoint in Ejector.Driveslist and returns the proper case sensitive mountpoint
+ If it doesnt exist - just return the original string - simpler to error out later rather than now}
+function GetCaseSensitiveMountPointName(MountPoint: string; Ejector: TDriveEjector): string;
+var
+ i: integer;
+begin
+ result := MountPoint; //If it doesnt exist - just return the original string - simpler to error out later rather than now
+ if Ejector = nil then exit;
+ if Ejector.DrivesCount = 0 then exit;
+
+ for I := 0 to Ejector.DrivesCount - 1 do
+ begin
+ if AnsiCompareText(MountPoint, Ejector.RemovableDrives[i].DriveMountPoint) = 0 then
+ begin
+ result := Ejector.RemovableDrives[i].DriveMountPoint;
+ break;
+ end;
+ end;
+end;
+
+
end.
View
22 uDriveEjector.pas
@@ -44,6 +44,7 @@ interface
CardMediaPresent: boolean;
BusType: integer;
ParentDevInst: integer;
+ SiblingIndexes: array of integer;
end;
TDriveEjector = class
@@ -570,6 +571,7 @@ function TDriveEjector.RemoveDrive(MountPoint: string;
begin
//First try and close explorer windows
EnumWindows(@EnumWindowsAndCloseFunc, LParam(MountPoint));
+
//Then try and close any programs that might be running from the drive
if CloseRunningApps then
CloseAppsRunningFrom(MountPoint, ForceRunningAppsClosure);
@@ -628,17 +630,31 @@ procedure TDriveEjector.CheckForCardReaders;
procedure TDriveEjector.CheckForSiblings;
var
- i: integer;
+ i, j: integer;
begin
- for I := 0 to DrivesCount - 1 do
+ {for I := 0 to DrivesCount - 1 do
begin
if GetNoDevicesWithSameParentInst(RemovableDrives[i].ParentDevInst) > 0 then
if GetNoDevicesWithSameProductID(RemovableDrives[i].ProductId) > 0 then //Hard drive partitions
RemovableDrives[i].HasSiblings := true
else
RemovableDrives[i].HasSiblings := false;
- end;
+ end;}
+ for I := 0 to DrivesCount - 1 do
+ for J := 0 to DrivesCount - 1 do
+ begin
+ if I = J then continue; //Same drive
+ if RemovableDrives[i].ParentDevInst = RemovableDrives[j].ParentDevInst then
+ if RemovableDrives[i].ProductId = RemovableDrives[j].ProductId then
+ begin
+ RemovableDrives[i].HasSiblings := true;
+ SetLength(RemovableDrives[i].SiblingIndexes, length(RemovableDrives[i].SiblingIndexes) + 1);
+ RemovableDrives[i].SiblingIndexes[High(RemovableDrives[i].SiblingIndexes)] := j;
+ end
+ else
+ RemovableDrives[i].HasSiblings := false;
+ end;
end;
function TDriveEjector.CheckIfDriveHasMedia(MountPoint: string): boolean;
View
10 uProcessAndWindowUtils.pas
@@ -178,8 +178,10 @@ function EnumChildWindowsAndCloseFunc(Handle: THandle;
var
WindowText : array[0.. MAX_PATH - 1] of Char;
FoundPos: integer;
+ Res: cardinal;
begin
- PostMessage(Handle, WM_GETTEXT, sizeof(WindowText), integer(@WindowText[0]));
+ //PostMessage(Handle, WM_GETTEXT, sizeof(WindowText), integer(@WindowText[0]));
+ SendMessageTimeout(Handle, WM_GETTEXT, SizeOf(WindowText), Cardinal(@WindowText[0]), SMTO_ABORTIFHUNG or SMTO_NORMAL, 500, Res);
FoundPos:= pos(DriveString, WindowText);
if FoundPos > 0 then
@@ -197,13 +199,15 @@ function EnumWindowsAndCloseFunc(Handle: THandle;
WindowName, WindowText: array[0..MAX_PATH] of Char;
FoundPos: integer;
DriveString: string;
+ Res: cardinal;
begin
//Build the search string
DriveString:= ExcludeTrailingPathDelimiter ( MountPoint );
//Get the window caption
- PostMessage(Handle, WM_GETTEXT, SizeOf(WindowName), integer(@WindowName[0]));
-
+ //PostMessage(Handle, WM_GETTEXT, SizeOf(WindowName), cardinal(@WindowName[0]));
+ {SendMessage sometimes never returned, PostMessage just didnt work a lot of the time, so SendMessageTimeout is the alternative}
+ SendMessageTimeout(Handle, WM_GETTEXT, SizeOf(WindowName), Cardinal(@WindowName[0]), SMTO_ABORTIFHUNG or SMTO_NORMAL, 500, Res);
//Look for CabinetWClass in all windows
WindowHandle := FindWindow('CabinetWClass', WindowName);
if WindowHandle > 0 then //Found an explorer window
Please sign in to comment.
Something went wrong with that request. Please try again.