开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜