Mark Brady
asked on
Return 'Filename' from windows explorer context menu
I have added an item to the windows context menu (right click on any file);
When clicked, my application opens so this is ok.
I need to know how to display the path and filename of the file that was right clicked on, so my application can deal with it.
Eg: I have added 'Your File Path is ' to the right click context menu from my application, This works fine.
When I click on the context menu item 'Your File Path is' it opens my application.
I want a procedure/ Function to do the following:
ShowMessage (YourFilePath);
Please can someone show me how to get the filepath [eg:] ('c:\test.txt') from the file that was clicked in windows and return it to my program ?
Now here is the longer version :
When right clicking on any file in windows explorer the context menu has a choice that is ''Your File Path is'. // I have achieved this.
When you click on it, my application is started // I have achieved this
Here is where I need help !
I need to know how my application will know WHICH file was clicked on ?
It should return the full filepath including filename so my application can work with it.
The registry key I have added for context menu is......
C:\Documents and Settings\Spider\Desktop\pr ogram test\maxenc.exe "%1"
What does the "%1" mean and how can I modify this to open the file that was clicked ?
Thanks in advance.
Elvin
When clicked, my application opens so this is ok.
I need to know how to display the path and filename of the file that was right clicked on, so my application can deal with it.
Eg: I have added 'Your File Path is ' to the right click context menu from my application, This works fine.
When I click on the context menu item 'Your File Path is' it opens my application.
I want a procedure/ Function to do the following:
ShowMessage (YourFilePath);
Please can someone show me how to get the filepath [eg:] ('c:\test.txt') from the file that was clicked in windows and return it to my program ?
Now here is the longer version :
When right clicking on any file in windows explorer the context menu has a choice that is ''Your File Path is'. // I have achieved this.
When you click on it, my application is started // I have achieved this
Here is where I need help !
I need to know how my application will know WHICH file was clicked on ?
It should return the full filepath including filename so my application can work with it.
The registry key I have added for context menu is......
C:\Documents and Settings\Spider\Desktop\pr
What does the "%1" mean and how can I modify this to open the file that was clicked ?
Thanks in advance.
Elvin
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Ciuly
I got it working by changing your line
// if paramcount>1 then
to
if paramcount>0 then
Now it works and returns the path and filename to the application. Was that a typo or is there something I should know about paramcount ?
Now that it is working, perhaps you could give advise on how to achieve this...
If a user right clicks on a file with a certain extention [eg] '.lok' then how to add to context another entry of say.... 'Unlock' So my application will know which procedure to carry out depending on the file extention that was loaded into the application.
Elvin
I got it working by changing your line
// if paramcount>1 then
to
if paramcount>0 then
Now it works and returns the path and filename to the application. Was that a typo or is there something I should know about paramcount ?
Now that it is working, perhaps you could give advise on how to achieve this...
If a user right clicks on a file with a certain extention [eg] '.lok' then how to add to context another entry of say.... 'Unlock' So my application will know which procedure to carry out depending on the file extention that was loaded into the application.
Elvin
>> Now it works and returns the path and filename to the application.
well, that's not what you wanted, is it? yuo wanted to have the filename passed as the parameter, which will normally reside in paramstr(1).
paramcount returns the number of parameters. if paramcount =0, it means there are no parameters. paramstr returns the values of the parameter, OR, if the index is 0, returns the application path/name.
since your applicaiton is not beeing executed with a parameter, why did you enter in the registry the %1? makes no sense.
I am guessing you are doing this all wrong. bulding a context menu handler requires knowledge of COM. I thought you already have it, given the way you presented your problem by everything "working". but if you don't even know what paramcount and paramstr are ... that means I'm in for a lot more pain than initially thought.
so, let's make this easier for both of us. here is a nice article with a context menu handler: http://www.delphi3000.com/articles/article_2926.asp?SK=
works for one selected file.
if you look for function TContextMenu.IShellExtInit _Initializ e you will see there how he gets the selected filename. if you need the extension, use extractfileext function.
if you will still encouter problems, post the entire project in a zip somewhere and post the link here. In this case, I think I'd rather see what you do and not assume anything :)
well, that's not what you wanted, is it? yuo wanted to have the filename passed as the parameter, which will normally reside in paramstr(1).
paramcount returns the number of parameters. if paramcount =0, it means there are no parameters. paramstr returns the values of the parameter, OR, if the index is 0, returns the application path/name.
since your applicaiton is not beeing executed with a parameter, why did you enter in the registry the %1? makes no sense.
I am guessing you are doing this all wrong. bulding a context menu handler requires knowledge of COM. I thought you already have it, given the way you presented your problem by everything "working". but if you don't even know what paramcount and paramstr are ... that means I'm in for a lot more pain than initially thought.
so, let's make this easier for both of us. here is a nice article with a context menu handler: http://www.delphi3000.com/articles/article_2926.asp?SK=
works for one selected file.
if you look for function TContextMenu.IShellExtInit
if you will still encouter problems, post the entire project in a zip somewhere and post the link here. In this case, I think I'd rather see what you do and not assume anything :)
ASKER
Sorry buddy what I meant to say was if I select a single file then run your example code, it was not returning the filename. I figured out that your line paramcount>1 was looking for more than 1 perameter when there was only 1 perameter. I changed it to >0 so it would recognise the file that was selected.
Am I confused ? Probabaly but it worked once I changed it.
// Here is the form data
object Form1: TForm1
Left = 0
Top = 0
VertScrollBar.Visible = False
BorderIcons = []
BorderStyle = bsNone
ClientHeight = 95
ClientWidth = 202
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
OnCreate = FormCreate
OnShow = FormShow
PixelsPerInch = 96
TextHeight = 13
object Label2: TLabel
Left = 379
Top = 464
Width = 3
Height = 13
end
object Label1: TLabel
Left = 8
Top = 8
Width = 4
Height = 16
Font.Charset = DEFAULT_CHARSET
Font.Color = clTeal
Font.Height = -13
Font.Name = 'Tahoma'
Font.Style = [fsBold]
ParentFont = False
end
end
// And the unit
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, registry;
const
DirExtensionKey = 'Directory\shell\encrypt';
FileExtensionKey = '*\shell\';
SubKey = '\command';
ContextName= 'Lock-Unlock File';
type
TForm1 = class(TForm)
Label2: TLabel;
Label1: TLabel;
procedure Lock(Sender: TObject);
procedure Unlock(Sender: TObject);
procedure AddEntryToExplMenu(Adding: boolean);
procedure FormCreate(Sender: TObject);
procedure GetFileName(Sender: TObject);
procedure FormShow(Sender: TObject);
private
{ Private declarations }
public
end;
var
Form1: TForm1;
FileSelected : TFilename;
implementation
{$R *.dfm}
procedure TForm1.GetFileName(Sender: TObject);
var
Filename, ext : string;
begin
if paramcount>0 then
Filename := (paramstr(1))
else
exit;
label1.Caption := (Filename);
ext := extractFileExt (Filename);
if ext = '.loc' then
Unlock(sender)
else
lock(Sender);
end;
function ReverseFileBytes(const Infile, OutFile: String): Boolean;
var
FileRead, FileWrite: TFileStream;
FileSize, i, x,z: Integer;
bt: Byte;
psw : string;
label pswcheck;
begin
Result := False;
pswcheck :
psw := inputbox ('Enter a password','Password','');
z := 32 - length(psw);
for i := 1 to z do
psw := psw + ' ';
FileRead := TFileStream.Create(InFile, fmOpenRead or fmShareDenyWrite);
try
FileWrite := TFileStream.Create(OutFile , fmCreate or fmOpenWrite or fmShareDenyWrite);
FileSize := FileRead.Size;
if FileSize < 1 then Exit;
FileWrite.Seek(0, soFromBeginning);
FileWrite.write(psw[1], 32);
for i := 1 to FileSize do
begin
FileRead.Seek(-i, soFromEnd);
FileRead.Read(bt, 1);
FileWrite.Write(bt,1);
end;
Result := True;
finally
FreeAndNil(FileRead);
FreeAndNil(FileWrite);
end;
end;
function UnlockFile(const Infile, OutFile: String): Boolean;
var
FileRead, FileWrite: TFileStream;
FileSize, i, x: Integer;
bt: Byte;
psw,password : string;
label NoCanDo;
begin
Result := False;
FileRead := TFileStream.Create(InFile, fmOpenRead or fmShareDenyWrite);
setlength(psw,32);
FileRead.Seek(0, soFromBeginning);
FileRead.read(psw[1], length(psw));
NoCanDo :
password := inputbox ('Enter the password','Password','');
if password = '' then
Goto NoCanDo;
if password <> (trim(psw)) then
begin
FileRead.Free;
exit;
end;
try
FileWrite := TFileStream.Create(OutFile , fmCreate or fmOpenWrite or fmShareDenyWrite);
FileSize := FileRead.Size;
if FileSize < 1 then Exit;
for i := 1 to FileSize - 32 do
begin
FileRead.Seek(-i, soFromEnd);
FileRead.Read(bt, 1);
FileWrite.Write(bt,1);
end;
Result := True;
finally
FreeAndNil(FileRead);
FreeAndNil(FileWrite);
end;
end;
PROCEDURE TForm1.AddEntryToExplMenu( Adding:boo lean);
var
reg: TRegistry;
begin
try
reg := TRegistry.Create;
except
Exit;
end;
if Adding then
with reg do
begin
RootKey := HKEY_CLASSES_ROOT;
OpenKey(FileExtensionKey, Adding);
WriteString('', ContextName);
CloseKey;
OpenKey(FileExtensionKey + ContextName+SubKey, Adding);
WriteString('', ParamStr(0) + ' "%1"');
CloseKey;
end
else
with reg do
begin
RootKey := HKEY_CLASSES_ROOT;
DeleteKey(FileExtensionKey + ContextName);
CloseKey;
end;
reg.Free;
END;
Procedure TForm1.Lock(Sender: TObject);
var
fname, ext, realname,s : string;
i,x : integer;
begin
fname := label1.caption;
if Fname = '' then
exit;
realname := ExtractFileName(fname);
if ReverseFileBytes(fname, Realname + '.loc') then
ShowMessage('The file has been Locked');
end;
Procedure TForm1.Unlock(Sender: TObject);
var
fname, ext, realname,s : string;
i,x : integer;
begin
fname := label1.caption;
if Fname = '' then
exit;
ext := ExtractFileExt(fname);
realname := ExtractFileName(fname);
x := pos('.loc',realname);
for I := 1 to x-1 do
begin
s := s + realname[i];
end;
if UnlockFile(fname, s) then
ShowMessage('The file has been Unlocked');
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
AddEntryToExplMenu(true);
GetFileName(sender);
end;
procedure TForm1.FormShow(Sender: TObject);
begin
close;
end;
end.
// This should be a console app but I haven't worked that out to do yet ?
Am I confused ? Probabaly but it worked once I changed it.
// Here is the form data
object Form1: TForm1
Left = 0
Top = 0
VertScrollBar.Visible = False
BorderIcons = []
BorderStyle = bsNone
ClientHeight = 95
ClientWidth = 202
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
OnCreate = FormCreate
OnShow = FormShow
PixelsPerInch = 96
TextHeight = 13
object Label2: TLabel
Left = 379
Top = 464
Width = 3
Height = 13
end
object Label1: TLabel
Left = 8
Top = 8
Width = 4
Height = 16
Font.Charset = DEFAULT_CHARSET
Font.Color = clTeal
Font.Height = -13
Font.Name = 'Tahoma'
Font.Style = [fsBold]
ParentFont = False
end
end
// And the unit
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, registry;
const
DirExtensionKey = 'Directory\shell\encrypt';
FileExtensionKey = '*\shell\';
SubKey = '\command';
ContextName= 'Lock-Unlock File';
type
TForm1 = class(TForm)
Label2: TLabel;
Label1: TLabel;
procedure Lock(Sender: TObject);
procedure Unlock(Sender: TObject);
procedure AddEntryToExplMenu(Adding:
procedure FormCreate(Sender: TObject);
procedure GetFileName(Sender: TObject);
procedure FormShow(Sender: TObject);
private
{ Private declarations }
public
end;
var
Form1: TForm1;
FileSelected : TFilename;
implementation
{$R *.dfm}
procedure TForm1.GetFileName(Sender:
var
Filename, ext : string;
begin
if paramcount>0 then
Filename := (paramstr(1))
else
exit;
label1.Caption := (Filename);
ext := extractFileExt (Filename);
if ext = '.loc' then
Unlock(sender)
else
lock(Sender);
end;
function ReverseFileBytes(const Infile, OutFile: String): Boolean;
var
FileRead, FileWrite: TFileStream;
FileSize, i, x,z: Integer;
bt: Byte;
psw : string;
label pswcheck;
begin
Result := False;
pswcheck :
psw := inputbox ('Enter a password','Password','');
z := 32 - length(psw);
for i := 1 to z do
psw := psw + ' ';
FileRead := TFileStream.Create(InFile,
try
FileWrite := TFileStream.Create(OutFile
FileSize := FileRead.Size;
if FileSize < 1 then Exit;
FileWrite.Seek(0, soFromBeginning);
FileWrite.write(psw[1], 32);
for i := 1 to FileSize do
begin
FileRead.Seek(-i, soFromEnd);
FileRead.Read(bt, 1);
FileWrite.Write(bt,1);
end;
Result := True;
finally
FreeAndNil(FileRead);
FreeAndNil(FileWrite);
end;
end;
function UnlockFile(const Infile, OutFile: String): Boolean;
var
FileRead, FileWrite: TFileStream;
FileSize, i, x: Integer;
bt: Byte;
psw,password : string;
label NoCanDo;
begin
Result := False;
FileRead := TFileStream.Create(InFile,
setlength(psw,32);
FileRead.Seek(0, soFromBeginning);
FileRead.read(psw[1], length(psw));
NoCanDo :
password := inputbox ('Enter the password','Password','');
if password = '' then
Goto NoCanDo;
if password <> (trim(psw)) then
begin
FileRead.Free;
exit;
end;
try
FileWrite := TFileStream.Create(OutFile
FileSize := FileRead.Size;
if FileSize < 1 then Exit;
for i := 1 to FileSize - 32 do
begin
FileRead.Seek(-i, soFromEnd);
FileRead.Read(bt, 1);
FileWrite.Write(bt,1);
end;
Result := True;
finally
FreeAndNil(FileRead);
FreeAndNil(FileWrite);
end;
end;
PROCEDURE TForm1.AddEntryToExplMenu(
var
reg: TRegistry;
begin
try
reg := TRegistry.Create;
except
Exit;
end;
if Adding then
with reg do
begin
RootKey := HKEY_CLASSES_ROOT;
OpenKey(FileExtensionKey, Adding);
WriteString('', ContextName);
CloseKey;
OpenKey(FileExtensionKey + ContextName+SubKey, Adding);
WriteString('', ParamStr(0) + ' "%1"');
CloseKey;
end
else
with reg do
begin
RootKey := HKEY_CLASSES_ROOT;
DeleteKey(FileExtensionKey
CloseKey;
end;
reg.Free;
END;
Procedure TForm1.Lock(Sender: TObject);
var
fname, ext, realname,s : string;
i,x : integer;
begin
fname := label1.caption;
if Fname = '' then
exit;
realname := ExtractFileName(fname);
if ReverseFileBytes(fname, Realname + '.loc') then
ShowMessage('The file has been Locked');
end;
Procedure TForm1.Unlock(Sender: TObject);
var
fname, ext, realname,s : string;
i,x : integer;
begin
fname := label1.caption;
if Fname = '' then
exit;
ext := ExtractFileExt(fname);
realname := ExtractFileName(fname);
x := pos('.loc',realname);
for I := 1 to x-1 do
begin
s := s + realname[i];
end;
if UnlockFile(fname, s) then
ShowMessage('The file has been Unlocked');
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
AddEntryToExplMenu(true);
GetFileName(sender);
end;
procedure TForm1.FormShow(Sender: TObject);
begin
close;
end;
end.
// This should be a console app but I haven't worked that out to do yet ?
yep. that was my mistake explaining. it's >=1, you're right. then I read "Now it works and returns the path and filename to the application. " and thought you meant
"Now it works and returns the path and filename of the application". guess I wasn't woken up fully :D
then we go to the next stage:
"If a user right clicks on a file with a certain extention [eg] '.lok' then how to add to context another entry of say.... 'Unlock' So my application will know which procedure to carry out depending on the file extention that was loaded into the application."
in order to be able to achieve this, you must write a COM class which will be a context menu handler. just in teh link I gave you on delphi3000.zom. there is no way around it. basically, when the context menu is created, explorer will call some methods in your com class which will tell it IF to create any menues, and what menues to create depending on the selected object (file, directory, etc)
so you need to make it a COM object, which basically means that you will not be able to make it a console application.
it won't be any kind of aplication, it will be a dll. refer to that article for more info.
"Now it works and returns the path and filename of the application". guess I wasn't woken up fully :D
then we go to the next stage:
"If a user right clicks on a file with a certain extention [eg] '.lok' then how to add to context another entry of say.... 'Unlock' So my application will know which procedure to carry out depending on the file extention that was loaded into the application."
in order to be able to achieve this, you must write a COM class which will be a context menu handler. just in teh link I gave you on delphi3000.zom. there is no way around it. basically, when the context menu is created, explorer will call some methods in your com class which will tell it IF to create any menues, and what menues to create depending on the selected object (file, directory, etc)
so you need to make it a COM object, which basically means that you will not be able to make it a console application.
it won't be any kind of aplication, it will be a dll. refer to that article for more info.
ASKER
Thanks Ciuly
I'm going to accept your first answer (even though there was a typo) as I now have this working to my satisfaction. I read the info in your link but considering it is a large process just to add one more command to the context menu, I have rewritten my app code so it looks for the file extention and processes the file according to what the extention is. Only one entry in the context menu 'Lock-Unlock'
When that is clicked it runs my app and either locks or unlocks the file that was selected.
I was prefering to have this as a console app as I have nothing on the form and the form is never displayed but for now I will deal with closing the app on formshow.
I will rerad more on console app;ications and modify my code to suit later.
Thanks for your help buddy....
Elvin
I'm going to accept your first answer (even though there was a typo) as I now have this working to my satisfaction. I read the info in your link but considering it is a large process just to add one more command to the context menu, I have rewritten my app code so it looks for the file extention and processes the file according to what the extention is. Only one entry in the context menu 'Lock-Unlock'
When that is clicked it runs my app and either locks or unlocks the file that was selected.
I was prefering to have this as a console app as I have nothing on the form and the form is never displayed but for now I will deal with closing the app on formshow.
I will rerad more on console app;ications and modify my code to suit later.
Thanks for your help buddy....
Elvin
ASKER
I can work with what you gave me even though there was a typo I worked it out. Thanks for the answer Ciuly
for a small mistake, a typo, you give me a B grade? very nice. well, if you think that an A grade is given only for a perfect, flawless answer, then I think, no, I KNOW, that you are now the 12th person on my blacklist: which means that I will no longer answer your questions.
have a nice one.
PS: no need to answer, I unsubscribed from this question.
have a nice one.
PS: no need to answer, I unsubscribed from this question.
ASKER
I tried that code in my application. Where should I execute it ? OnFormCreate ? I just tried it as a separate procedure and selected a file in Windows Explorer, then swapped to my application and ran the procedure but it always has a paramcount <1 so it's not recognising that a file has been selected in windows.
Can you maybe show me a small example ?
Thanks
Elvin