|
Public Sub CopyDir(ByVal Src As String, ByVal Dst As String)
Dim Files() As String, Element As String
If Microsoft.VisualBasic.Right(Dst, Dst.Length - 1) <> Path.DirectorySeparatorChar Then
Dst &= Path.DirectorySeparatorChar
End If
If Not Directory.Exists(Dst) Then Directory.CreateDirectory(Dst)
Files = Directory.GetFileSystemEntries(Src)
For Each Element In Files
If Directory.Exists(Element) Then
CopyDir(Element, Dst & Path.GetFileName(Element))
Else
File.Copy(Element, Dst & Path.GetFileName(Element), True)
End If
Next Element
End Sub
Starlogic
|
|
|
|
|
You can change the line:
If Microsoft.VisualBasic.Right(Dst, Dst.Length - 1) <> Path.DirectorySeparatorChar Then<br />
to:
If Not dst.EndsWith(Path.DirectorySeparatorChar) Then
Even better is the fact that, the whole if ... end if statement is not need with the following revisions:
<br />
If Directory.Exists(Element) Then<br />
CopyDir(Element, Dst & Path.GetFileName(Element))<br />
Else<br />
File.Copy(Element, Dst & Path.GetFileName(Element), True)<br />
End If<br />
is Changed to:
<br />
If Directory.Exists(Element) Then<br />
CopyDir(Element, Path.Combine(Dst, Path.GetFileName(Element)))<br />
Else<br />
File.Copy(Element, Path.Combine(Dst, Path.GetFileName(Element)), True)<br />
End If<br />
The Path.Combine method will concatinate the Path.DirectorySeparatorChar onto the first argument if it is not already there!
So here is a slightly tweeked version of the whole thing:
<br />
Function CopyDir(ByVal SrcPath As String, ByVal DestPath As String)<br />
<br />
If Not Directory.Exists(DestPath) Then<br />
Directory.CreateDirectory(DestPath)<br />
End If<br />
<br />
Dim files() As String<br />
<br />
files = Directory.GetFileSystemEntries(SrcPath)<br />
For Each element As String In files<br />
'Sub directories <br />
If Directory.Exists(element) Then<br />
CopyDir(element, Path.Combine(DestPath, Path.GetFileName(element)))<br />
Else 'Files<br />
File.Copy(element, Path.Combine(DestPath, Path.GetFileName(element)), True)<br />
End If<br />
Next<br />
End Function<br />
Hope you have fun with this !
Kevin Orcutt
Software Engineer
SAEC/kinetic vision
www.saec-kv.com
korcutt@saec-kv.com
|
|
|
|
|
do u know how to determine drive types using C#. Just like what GetDriveTyes are doing in windows SDK.
|
|
|
|
|
you can use driveinfo instead
|
|
|
|
|
try this
DriveInfo[] drives = DriveInfo.GetDrives();
foreach (DriveInfo drive in drives)
{
Console.WriteLine("Drive: {0}", drive.Name);
Console.WriteLine("Type: {0}", drive.DriveType); // this is your target
}
Regards,
A.Ragab
|
|
|
|
|
First, thanks a lot for the article. I have a question about .NET framework. I really have no idea about the framework and if the question is so stupid you are free not to answer it
Well the question is can you use the Win API in a managed .NET program. If so, why don't you use the a simple shell function to copy the directory with all of its contents. Isn't it better? :?
Mustafa Demirhan
http://www.macroangel.com
Sonork ID 100.9935:zoltrix
<nobr>They say I'm lazy but it takes all my time
|
|
|
|
|
Hello,
Great question because I saw someone showing this solution in a newsgroup .
What about using a shell function to copy the directory ?
Advantages:
- Maybe the copy will be faster because you use pure native code.
Problems:
- Your code is not 100% .NET compliant.
- Your code is not portable to another framework version (like mono on Linux) because you rely on Windows commands.
- No exceptions will be raised in case of an error occurring during the shell copy.
- You start a new external process.
Convinced ?
R. LOPES
Just programmer.
|
|
|
|
|
Thanks for the answer.
GriffonRL wrote:
Great question because I saw someone showing this solution in a newsgroup .
Hehe. Believe me this is my own question. I did not see it in a newsgroup
I have been using my approach for years and never had a problem yet.
GriffonRL wrote:
- Your code is not 100% .NET compliant.
- Your code is not portable to another framework version (like mono on Linux) because you rely on Windows commands.
Yeah you are right. I never thought that because framework compatibility or OS independency is never an issue for me. I do not care about that :P
GriffonRL wrote:
- No exceptions will be raised in case of an error occurring during the shell copy.
Yes but you will get a return value which indicates if the operation is sucessfull or not. Isn't it good enough? Hmmm. Well in fact not. I admit that C# is a very very nice language and the one who uses C# should use it in C# way, not the old C way. So let me answer my question: NO. Using Exceptions is better.
Hey, but you can check the value and raise your own exception
GriffonRL wrote:
- You start a new external process.
I really didn't know that. Are you sure about that?
PS: One nice thing with using Shell functions is that you can put the files directly to the Recycle Bin (instead of deleting them).
Lastly, let me ask you another question: How is your experience with .NET till now? Is it really more productive than VC++? I love C#; but I do not like the .NET Framework it self and I hate the CLR (or whatever it is, the intermediate compiler thing - the code is not compiled into the native code).
I hope someday, Microsoft will come up with a native C# compiler with a new version of MFC (I dont want any language interoperability. All I want is to use a language like C# not C++ ).
Mustafa Demirhan
http://www.macroangel.com
Sonork ID 100.9935:zoltrix
<nobr>They say I'm lazy but it takes all my time
|
|
|
|
|
Hello,
Yes I agree that C# is a very nice language and we will soon get new important features like generics .
I have a long experience with Java and C++, and I found C# very easy to learn with that background.
I first played a little bit with ASP.NET 1 year ago but stopped for several months. I resumed my experiments a few months ago with the Visual Studio .NET release, and now we use .NET to build our business applications.
I really think this language is more productive than C++, or at least less harmful than C++. Writing bad C++ code is easier than writing bad C# code. Of course C# still miss some features but is is coming soon.
I have nothing against the .NET framework and it is full of helpful classes that speed up the development process a lot. I programmed a lot with Java and really enjoyed the Java APIs. The new .NET framework makes more sense than the system DLL we used to for Windows programming. MFC for example has a heavy heritage behind it.
The beauty of .NET if you develop only for Windows platforms, is that you can still write critical functions in a native C++ DLL and call them from your skeleton program written in C#/.NET.
Because the C# language has been submitted to the ECMA and specifications are available, anybody could write a C# compiler to native code. Or maybe someone will create a program to convert all CLR code into native code: some solutions exist for Java where .class files are converted into Windows .EXE.
So wait and see,
R. LOPES
Just programmer.
|
|
|
|
|
you mentioned that c# will be getting generics, what are those?
|
|
|
|
|
|
First off, it's a great article that points out another thing that's wrong with the FCL. Now...if you don't mind, I'd like to critique it a bit.
First off, there's no reason to return bool. A better way to do it would be to use straight Exceptions. To put it in Rama's words: "It's not the way of the Framework." The System.IO.File.Copy() method is marked as public static void Copy() , so what you should do is make this return void and stick to using Exceptions.
Another thing, when you say:
catch(Exception Ex)
{
Console.Error.WriteLine(Ex.Message);
Success=false;
}
That's wrong. Your code, as part of a class library, should never visually display information...and that includes writing to the console. You should let the consumer handle that. Jeffrey Richter points this out in his book Applied Microsoft .NET Framework Programming, the DataGrid displays a MessageBox when there is an error in setting the CurrentCell property. I know that as an app-writer, I would hate to have a component or utility that I was using display visual information to the user without my consent.
Oh, and you don't need a constructor in your class unless there are other methods that are not marked as static . So I would remove that because really, this class should never be instantiated.
That being said, it's a great implementation for something that should be in the Framework.
You will now find yourself in a wonderous, magical place, filled with talking gnomes, mythical squirrels, and, almost as an afterthought, your bookmarks
-Shog9 teaching Mel Feik how to bookmark
I don't know whether it's just the light but I swear the database server gives me dirty looks everytime I wander past.
-Chris Maunder
|
|
|
|
|
Hello,
Thank you for your nice post !
I totally agree with all your remarks .
I have to explain why I have this Console.Error.WriteLine(Ex.Message) stuff and a boolean just after.
That's because I catch the exceptions in the static function, the calling method never gets the info. So that's why I return a boolean.
But why I am catching the exception in the function ? Just because this function is coming from my framework and it is the way I wanted it. Actually, I redirect all Console.Error.WriteLine to a XML error file (see http://www.codeproject.com/csharp/XML_Error_Log.asp[^]) and it is important the message comes from the function. But you can tell me I can retrow the exception just after I logged it and you are right: it will be the best solution to be "in the way of the framework".
I think I will update the article, reduce the code size again and try/catch the exceptions in the usage example.
And yes, I can remove this nasty useless constructor even if it doesn't create any trouble . I use a template to build all my classes and I always have one.
Thank you again for your remarks. I will help me clean the code.
R. LOPES
Just programmer.
|
|
|
|
|
GriffonRL wrote:
That's because I catch the exceptions in the static function, the calling method never gets the info. So that's why I return a boolean.
You can still throw an Exception back up the call stack. All that you have to do is:
try
{
catch(Exception ex)
{throw ex;}
That'll throw the Exception back up the call stack to the caller of the function.
In fact...*Brilliant thought comes to David*
Why don't you do some extra work in the catch block...before you throw the exception back up the stack. One thing that I hate is when Windows starts copying a directory and then one file can't be moved, so I have a partial directory...So why don't you delete the destination files and folder if an error happened. That way it's all or nothing. I know a lot of other people who hate this too...so you may want to look into implementing that.
You will now find yourself in a wonderous, magical place, filled with talking gnomes, mythical squirrels, and, almost as an afterthought, your bookmarks
-Shog9 teaching Mel Feik how to bookmark
I don't know whether it's just the light but I swear the database server gives me dirty looks everytime I wander past.
-Chris Maunder
|
|
|
|
|
Wow, that would be really hard, because he has to keep the track of all copied files. And since he is using a recursive algorithm with static functions this may be really hard. Also, he should not delete the files that he has overwritten. Because of that, while keeping track of the files, he should also check if that file already exists or not. This list may become longer and doing all of these stuff is much harder than this simple and fast function
Mustafa Demirhan
http://www.macroangel.com
Sonork ID 100.9935:zoltrix
<nobr>They say I'm lazy but it takes all my time
|
|
|
|
|
Hello again,
Yes I agree about throwing the exception back after catching it. It is what I called "retrow" when I responded to your first post.
Sorry for the typo ...
Your second remark about partial copies is interesting, but I would like to keep this version simple. And what if you replace an existing file during the copy ? If you roolback the process how do you retrieve the original without keeping a version somewhere ? Implementing this rollback procedure sounds a little bit overkill to me.
Thanks for your feedback,
R. LOPES
Just programmer.
|
|
|
|
|
GriffonRL wrote:
Your second remark about partial copies is interesting
Yeah...I wasn't thinking about this being a "simple" procedure. It would be quite hard to do what I was suggesting. I don't think that it would be very easy to do the rollback of the partial copy. And you are right. You would have to keep a temp version of the originals...
You will now find yourself in a wonderous, magical place, filled with talking gnomes, mythical squirrels, and, almost as an afterthought, your bookmarks
-Shog9 teaching Mel Feik how to bookmark
I don't know whether it's just the light but I swear the database server gives me dirty looks everytime I wander past.
-Chris Maunder
|
|
|
|
|
I believe the right way to do this is:
catch (Exception ex)
{
throw;
}
When you do it with "throw ex;", you actually change the source information of the exception to the current line. However, with "throw;", its like it was never caught in the first place.
|
|
|
|
|
You're right.
I don't know whether it's just the light but I swear the database server gives me dirty looks everytime I wander past.
-Chris Maunder
Microsoft has reinvented the wheel, this time they made it round.
-Peterchen on VS.NET
|
|
|
|
|
I agree, great article!
Nice and simple and easy to use-
I just ran into this CLR pitfall today and was very happy to come across your solution. Thanks a bunch!
Peace-
|
|
|
|
|