Solved

Copy files and create folders from CD-ROM to PC

Posted on 2002-06-28
19
263 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
Comment Utility
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
Comment Utility
oops,

change
 
  procedure TForm1.Button8Click(Sender: TObject);

to

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

Expert Comment

by:robert_marquardt
Comment Utility
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
 

Author Comment

by:routerboy309
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
> 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
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 

Author Comment

by:routerboy309
Comment Utility
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
Comment Utility
>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
Comment Utility
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
Comment Utility

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
Comment Utility
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
Comment Utility
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
Comment Utility
Ah---You're right again. Too many '\'. Once I changed it, everythign worked right.

Thanks again!

RB
0
 
LVL 7

Expert Comment

by:Cynna
Comment Utility
No problem, hope it turns out OK...

Cy.
0
 

Author Comment

by:routerboy309
Comment Utility
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
Comment Utility
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

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

762 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now