• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 318
  • Last Modified:

Copy files and create folders from CD-ROM to PC

Hello All -

I need to copy the contents of a CD-ROM to a pre-selected path. The path (edSelected) gets picked when
the user clicks Btn2 and navigates to the folder (browse folder), and then I'll append the folder 'app'
to that path.

For example:

They select:

C:\Program Files

When they click the button, the folder 'app' gets added (C:\Program Files\app) and the contents of the
CD-ROM gets copied.

The code below works, but I have two issues:

A) The pathing issue places an extra '\' when they select the root to be the path. C:\ - becomes C:\\app

B) I can't get the value - StrECopy to read the CD-ROM drive letter so I can copy. Trying to use ExtractFileDir(Application.ExeName), but that fails.

I can get the folders and files to copy from one folder on the PC to another on the PC, but not from the CD-ROM to PC.


procedure CopyFiles(const FromFolder: string; const ToFolder: string);
var
  Fo      : TSHFileOpStruct;
  buffer  : array[0..4096] of char;
  p       : pchar;
begin
  FillChar(Buffer, sizeof(Buffer), #0);
  p := @buffer;
  StrECopy(p, PChar(FromFolder)); //this is folder that you want to copy
  FillChar(Fo, sizeof(Fo), #0);
  Fo.Wnd    := Application.Handle;
  Fo.wFunc  := FO_COPY;
  Fo.pFrom  := @Buffer;
  Fo.pTo    := PChar(ToFolder); //this is where the folder will go
  Fo.fFlags := 0;
  if ((SHFileOperation(Fo) <> 0) or (Fo.fAnyOperationsAborted <> false)) then
    ShowMessage('File copy process cancelled')
end;

procedure TForm1.Btn1Click(Sender: TObject);
begin
Close;
end;

// problem here: If you pick the root of the drive, you get two '\\'
// example: pick C: drive and you get C:\\App
//pick a normal folder, and it works

procedure TForm1.Btn2Click(Sender: TObject);
var
s: string;
begin
 if SelectDirectory('Select Directory','',S) then
     edSelected.Caption := s + '\app';
end;

//need StrECopy to default to the CD-ROM. On it an eniter group of folders and files
//need to copied

procedure TForm1.Btn3Click(Sender: TObject);
var
Fo      : TSHFileOpStruct;
buffer  : array[0..4096] of char;
p       : pchar;
begin
FillChar(Buffer, sizeof(Buffer), #0);
p := @buffer;
StrECopy(p, 'C:\MyDir\*.*');
FillChar(Fo, sizeof(Fo), #0);
Fo.Wnd    := Handle;
Fo.wFunc  := FO_COPY;
Fo.pFrom  := @Buffer;
Fo.pTo    := pchar(edSelected.caption);
 if ((SHFileOperation(Fo) <> 0) or (Fo.fAnyOperationsAborted <> false)) then
   ShowMessage('Cancelled')
end;


Since this is a double questions, I've double up on the points.

RB
0
routerboy309
Asked:
routerboy309
  • 10
  • 8
1 Solution
 
CynnaCommented:
routerboy309,


> A) The pathing issue places an extra '\' when they select the root to be the path. C:\ - becomes C:\\app

This is quite normal. Simply change your code:

  procedure TForm1.Btn2Click(Sender: TObject);
  var
  s: string;
  begin
    if SelectDirectory('Select Directory','',S) then
       edSelected.Caption := s + '\app';
  end;


to this:


  procedure TForm1.Button8Click(Sender: TObject);
  var s: string;
  begin
    if SelectDirectory('Select Directory','',S) then begin
       if s[Length(s)]<>'\' then s:=s+'\';
       edSelected.Caption := s + 'app';
    end;  
  end



B) I can't get the value - StrECopy to read the CD-ROM drive letter so I can copy. Trying to use ExtractFileDir(Application.ExeName), but that fails.

Hmmm... I don't quite understand you here.
I'll assume you want to extract drive letter of the CD-ROM.
If this is true, this function will get you first available CD drive letter in system:


function GrabCDLetter: String;
// search for first available CD drive letter in system
var i: Integer;
    DriveLetters: String;
begin
  DriveLetters:='DEFGHIJK';
  for i:=1 to Length(DriveLetters) do begin
      Result:=DriveLetters[i]+':\';
      if GetDriveType(PChar(Result))=DRIVE_CDROM then Exit;
  end;
end;


If this isn't what you need, please give simplified example (I have this: ...., but I need this: .....) to explain B) futher.

0
 
CynnaCommented:
oops,

change
 
  procedure TForm1.Button8Click(Sender: TObject);

to

  procedure TForm1.Btn2Click(Sender: TObject);
0
 
robert_marquardtCommented:
One hint for copying from CD-ROM. All files on a CD-ROM are read only and may stay read only when copied. You may need to change the file attributes.
0
Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
routerboy309Author Commented:
Cynna -

Thanks for the iinfo. I'm testing it now.

robert_marquardt -

You bring up a good point. 3 of 6 files will need to be changed.


RB
0
 
routerboy309Author Commented:
Cynna -

A) Is solved. :)

B) I have this:

StrECopy(p, 'C:\MyDir\*.*');
StrECopy = the copy folder - but right now its hard coded. I need the application to know where its at, so StrECopy can gets its value and then appending a folder to that.

For example:

My CD-ROM is F. So StrECopy reads the value and adds the folder APP to it for a result of

StrECopy(p, 'F:\App\*.*');

In short, when the user clicks the button, the folder App gets created and its contents of F:\App gets moved to the Hard drive location (the part you fix 'A' of this question already).

I tried using ExtractFilePath(Application.EXEName)+'\app\*.*' but this falied:

StrECopy(p, ExtractFilePath(Application.EXEName)+'\app\*.*);


Does this help?

RB





0
 
routerboy309Author Commented:
I may have found the solution.

StrECopy(p,pchar(ExtractFilePath(Application.EXEName)+'\app\*.*'));

Cynna -

Can you check my code? Looking for options towards 'read only' changing attribute situation, too.

RB
0
 
CynnaCommented:
routerboy309,


I'm sorry, but I'm still not sure exactly what you need...

Before I go on, maybe this will help you:

>I tried using ExtractFilePath(Application.EXEName)+'\app\*.*' but this falied:

> StrECopy(p, ExtractFilePath(Application.EXEName)+'\app\*.*);

It failed because ExtractFilePath() always returns trailing '\':
So simply change:

     StrECopy(p, ExtractFilePath(Application.EXEName)+'\app\*.*);

to:

     StrECopy(p, PChar(ExtractFilePath(Application.EXEName)+'app\*.*));

That will copy from your application path+'app' to target folder.


If that doesn't help, I'll try guessing, and you tell me if I'm right, OK?


Guess #1
---------------

   You need to let user decide FROM where files should be
   copied (choose source folder). Right now, everything is
   copied from 'C:\MyDir', and user only chooses target
   folder, he can't choose source folder.
   
   If this is all you need, then change line:
     
          StrECopy(p, 'C:\MyDir\*.*');

   ... to following lines:
 
          // Allow user to choose source folder:
          if SelectDirectory('Choose source folder:','',s) then
             if s[Length(s)]<>'\' then s:=s+'\';
          else // Cancelled
             Exit;
          // s now contains selected source folder:
          StrECopy(p, s+'*.*');

   ... and, of course, add string variable s:

          procedure TForm1.Btn3Click(Sender: TObject);
          var
             s: String; // <--- new var added
             Fo      : TSHFileOpStruct;
          (.... rest of your code .....)


Guess #2
---------------

   You want '\app' to be automatically appended to source  folder.
   For example, if user chooses 'F:\', you want source
   folder to become 'F:\app'.
   
   If this is true, then do everything explained in
   Guess #1, except change line:

             StrECopy(p, s+'*.*');

   to:

             StrECopy(p, s+'app\*.*');





If all of these guesses aren't correct, you'll have
to explain it a bit more clearer again. In that case,
please be more specific.

Clearly state:

"BAD: This code: ....
      does this ...."

"GOOD: I want code that does this:
       ....."
0
 
CynnaCommented:
Sorry,

Forgot to add cast PChar() to StrECopy(p, ...) statements:
Wherever you have StrECopy(p,...), change it to StrECopy(p, PChar(...));

For example:

  StrECopy(p, s+'*.*');

change to:

  StrECopy(p, PChar(s+'*.*'));

0
 
CynnaCommented:
> Looking for options towards 'read only' changing attribute situation, too

Copy/Paste:
------------------

procedure ClearReadOnlyAttrib(const Filename: string );
var
  Attributes: word;
begin
  Attributes := FileGetAttr( Filename );
  FileSetAttr( Filename, (Attributes and not faReadOnly));
end;

0
 
routerboy309Author Commented:
Your due dilegence is certainly worth me giving you the points. :)


"You need to let user decide FROM where files should be
  copied (choose source folder)."

No. The User doesn't get the option to change where the files are to be copied FROM. Only gets to change where to PUT the files. So I Guess #2 is closest.

StrECopy is set based on where the CD-ROM was inserted with appending the value of 'APP' for the folder (and its contents).

I want the code to read the drive where the CD-ROM was inserted, append the path of that value with APP, and then when the user clicks the btn, the entire contents of the folder is transferred to the PC.

I think you have plenty of GOOD examples for me to test with. Plus, I like the fact you provided the code sample for the read only issue, hense, I've changed the point value. If my explaination is still unclear, please let me know.

0
 
CynnaCommented:
>I want the code to read the drive where the CD-ROM was inserted,

Did you solve this problem? How do you know in which CD drive the
CD has been inserted?
Previously you mentioned you have CD drive F:\ - if this is the case,
why bother finding out the letter of the CD drive with CD in question?
This makes sense only if you have multiple CD drives in your target system,
(for example, CD-ROM and CD-RW could be E: and F:), and you don't know
which one contains the CD.
If you want to automatically find the drive letter of the drive that
contains desired CD, you should know the CD title.
Its a bit more complicated then what you needed so far.



>... append the path of that value with APP, and then when the user clicks the btn,
>the entire contents of the folder is transferred to the PC.

This is very easy.
CopyFiles() does everything you need, so I'm puzzled, why did you use
Btn3Click() code at all?

It can be done much more easily. Assuming you know CD drive letter
(let's say F:),  then just use your CopyFiles() function this way:


procedure TForm1.Btn2Click(Sender: TObject);
var DriveLetter, TargetDir: String;
begin
  DriveLetter:='F:\';
  if SelectDirectory('Select target folder','', TargetDir) then begin
     // Be sure selected dir ends with '\':
     if TargetDir[Length(TargetDir)]<>'\' then TargetDir:=TargetDir+'\';
     // We want to copy files to subfolder APP of selected dir
     TargetDir:=TargetDir+'APP';
     // Finally copy all items from F:\APP:
     CopyFiles(DriveLetter+'APP', TargetDir);
  end;
end;



Just copy/paste this code, and be sure you leave CopyFiles() function.
0
 
routerboy309Author Commented:
I only used the F letter as a reference to the question. While I have mulitple CD-ROM drives, I sure many don't. So based on using the code:

(ExtractFilePath(Application.EXEName)+'\app\*.*'));

adds the Drive letter to the path, right?

I just applied the answer to the read-only issue and it worked perfectly.

RB

0
 
CynnaCommented:

1. ExtractFilePath(Application.EXEName)+'\app\*.*'
   
   should be (read my previous post, or go to Help about ExtractFilePath):

   ExtractFilePath(Application.EXEName)+'app\*.*'


2. > adds the Drive letter to the path, right?

Well, not quite. It extracts path of your application and and '\app\*.*' to it... :)

For example, if your app is called Project1, and is saved
in 'C:\Program Files\Delphi5\Projects\testing'

Application.ExeName='C:\Program Files\Delphi5\Projects\testing\Project1.exe'

ExtractFilePath(Application.EXEName)='C:\Program Files\Delphi5\Projects\testing\'

ExtractFilePath(Application.EXEName)+'\app\*.*'='C:\Program Files\Delphi5\Projects\testing\\app\*.*'
0
 
routerboy309Author Commented:
Excallant! I think you just solved another issue I had. I was using Application.ExeName (and appending to it) to find a Word doc so my app would open it. But I should be using ExtractFilePath.

Also, something else just bit me in as$. My copy file routine fails on Win98... I get an error - Cannot copy File File System Error (1026). So I guess its back to the drawing board...:(

procedure TForm1.btncopyClick(Sender: TObject);
var
Fo      : TSHFileOpStruct;
buffer  : array[0..4096] of char;
p       : pchar;
begin
 FillChar(Buffer, sizeof(Buffer), #0);
 p := @buffer;
 StrECopy(p,pchar(ExtractFilePath(Application.EXEName)+'\app\*.*'));
 FillChar(Fo, sizeof(Fo), #0);
 Fo.Wnd    := Handle;
 Fo.wFunc  := FO_COPY;
 Fo.pFrom  := @Buffer;
 Fo.pTo    := pchar(edSelected.caption);
    if ((SHFileOperation(Fo) <> 0) or (Fo.fAnyOperationsAborted <> false)) then
    ShowMessage('Cancelled');
     ClearReadOnlyAttrib(edSelected.caption + '\settings.txt');
end;
0
 
CynnaCommented:
Are you shure you have
  ExtractFilePath(Application.EXEName)+'\app\
folder?
If you do, what is it (copy/paste it here)?

0
 
routerboy309Author Commented:
Ah---You're right again. Too many '\'. Once I changed it, everythign worked right.

Thanks again!

RB
0
 
CynnaCommented:
No problem, hope it turns out OK...

Cy.
0
 
routerboy309Author Commented:
It did. :) Many thanks.

I'm about to post another issue surrounding the ExtractFilePath(Application.EXEName) function and two OpenDialog components (They fail to find the proper path, sharing one path for both).

It seems you have plenty of experience and I'd like you to get the points. Since I'm not sure how the 'expert side' works, is there a way to post and hope you get the chance to answer?

RB
0
 
CynnaCommented:
routerboy309,

Sorry I didn't get your last comment. When you post comment on answered question, I don't get any mail notification, so I really don't know when you posted something here.

Thank you for your trust in me, but you should give everybody a chance to give you your answer. But still, if you'd like your question to be targeted at me, probably the best way would be asking the question titled 'For Cynna: files followup' or something; that will soon get my attention ;) ....

And please remember, I tipically look only at the questions I get notified on by mail (except the new ones, of course).
Thanks!

0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 10
  • 8
Tackle projects and never again get stuck behind a technical roadblock.
Join Now