Solved

Copy files and create folders from CD-ROM to PC

Posted on 2002-06-28
19
269 Views
Last Modified: 2010-04-04
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
Comment
Question by:routerboy309
  • 10
  • 8
19 Comments
 
LVL 7

Expert Comment

by:Cynna
ID: 7118244
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
 
LVL 7

Expert Comment

by:Cynna
ID: 7118248
oops,

change
 
  procedure TForm1.Button8Click(Sender: TObject);

to

  procedure TForm1.Btn2Click(Sender: TObject);
0
 
LVL 11

Expert Comment

by:robert_marquardt
ID: 7118299
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
Migrating Your Company's PCs

To keep pace with competitors, businesses must keep employees productive, and that means providing them with the latest technology. This document provides the tips and tricks you need to help you migrate an outdated PC fleet to new desktops, laptops, and tablets.

 

Author Comment

by:routerboy309
ID: 7118357
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
 

Author Comment

by:routerboy309
ID: 7118393
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
 

Author Comment

by:routerboy309
ID: 7118519
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
 
LVL 7

Accepted Solution

by:
Cynna earned 125 total points
ID: 7118552
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
 
LVL 7

Expert Comment

by:Cynna
ID: 7118562
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
 
LVL 7

Expert Comment

by:Cynna
ID: 7118571
> 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
 

Author Comment

by:routerboy309
ID: 7118617
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
 
LVL 7

Expert Comment

by:Cynna
ID: 7118829
>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
 

Author Comment

by:routerboy309
ID: 7119164
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
 
LVL 7

Expert Comment

by:Cynna
ID: 7120444

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
 

Author Comment

by:routerboy309
ID: 7120477
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
 
LVL 7

Expert Comment

by:Cynna
ID: 7121526
Are you shure you have
  ExtractFilePath(Application.EXEName)+'\app\
folder?
If you do, what is it (copy/paste it here)?

0
 

Author Comment

by:routerboy309
ID: 7121623
Ah---You're right again. Too many '\'. Once I changed it, everythign worked right.

Thanks again!

RB
0
 
LVL 7

Expert Comment

by:Cynna
ID: 7121658
No problem, hope it turns out OK...

Cy.
0
 

Author Comment

by:routerboy309
ID: 7123515
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
 
LVL 7

Expert Comment

by:Cynna
ID: 7134923
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

Featured Post

Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
This video shows how to use Hyena, from SystemTools Software, to bulk import 100 user accounts from an external text file. View in 1080p for best video quality.

832 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question