Using c#, how do I copy a symbolic link in Windows Vista,7,2008
Using c#, how开发者_C百科 do I copy a symbolic link in Windows Vista,7,2008.
When I use File.Copy to copy a symlink, its target gets copied.
I wish to mimic the behavior one gets when you use xcopy with the /B option.
Is this possible using .NET 3.5?
You can use the Win32 CopyFileEx
function to do this. It took a bit of effort, but here is the whole CopyFileEx
helper class (C# 3.0 and .NET 3.5 Client Profile compatible and tested!). You can also reuse it for any other CopyFileEx
tasks that you have:
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
public static class CopyHelper
{
[Flags]
public enum CopyFileFlags : uint
{
COPY_FILE_FAIL_IF_EXISTS = 0x00000001,
COPY_FILE_RESTARTABLE = 0x00000002,
COPY_FILE_OPEN_SOURCE_FOR_WRITE = 0x00000004,
COPY_FILE_ALLOW_DECRYPTED_DESTINATION = 0x00000008,
COPY_FILE_COPY_SYMLINK = 0x00000800 //NT 6.0+
}
public enum CopyProgressResult : uint
{
PROGRESS_CONTINUE = 0,
PROGRESS_CANCEL = 1,
PROGRESS_STOP = 2,
PROGRESS_QUIET = 3
}
public enum CopyProgressCallbackReason : uint
{
CALLBACK_CHUNK_FINISHED = 0x00000000,
CALLBACK_STREAM_SWITCH = 0x00000001
}
public delegate CopyProgressResult CopyProgressRoutine(
long TotalFileSize,
long TotalBytesTransferred,
long StreamSize,
long StreamBytesTransferred,
uint dwStreamNumber,
CopyProgressCallbackReason dwCallbackReason,
IntPtr hSourceFile,
IntPtr hDestinationFile,
IntPtr lpData);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CopyFileEx(string lpExistingFileName,
string lpNewFileName, CopyProgressRoutine lpProgressRoutine,
IntPtr lpData, ref bool pbCancel, CopyFileFlags dwCopyFlags);
}
Here is some sample code that shows how to use it to copy a symbolic link (and not the file it refers to):
string srcLink = @"c:\l.txt"; // Sample source soft link
string destFile = @"d:\l.txt"; // Sample destination soft link
bool bCancel = false;
bool bSuccess = CopyHelper.CopyFileEx(srcLink, destFile,
null, IntPtr.Zero, ref bCancel,
CopyHelper.CopyFileFlags.COPY_FILE_COPY_SYMLINK);
if (!bSuccess)
{
int error = Marshal.GetLastWin32Error();
throw new Win32Exception(error);
}
There is no API for links (neither hardlinks, softlinks or symbolic links) in the .NET framework.
You must either call mklink.exe
with Process.Start
and create the link you want,
or you have a look for a third party library which is able to do such things.
You could make use of pinvoke and call CopyFileEx. Note the COPY_FILE_COPY_SYMLINK
which is what you are looking for.
I recognize this is a fairly old thread, but I've just finished some work in C code (yes, really) that supports this. Posting because I searched all over for this information, and it was not easy to find.
Sadly CopyFileEx
with COPY_FILE_SYMLINK
does not do the trick. That simply creates a 0-size file in the target directory with the correct name, but no symbolic link. Another old article contains a solution you could try to implement: How to copy directory symbolic link as a link to the target?.
I do think the problem with CopyFileEx
is a bug, one that still exists in Windows 10.
精彩评论