使用 C#,如何在 Windows Vista,7,2008 中复制符号链接

发布于 2024-09-30 11:34:14 字数 149 浏览 0 评论 0原文

使用 C#,如何在 Windows Vista,7,2008 中复制符号链接。

当我使用 File.Copy 复制符号链接时,它的目标会被复制。

我希望模仿使用带有 /B 选项的 xcopy 时的行为。

使用 .NET 3.5 可以吗?

Using c#, how 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

余生再见 2024-10-07 11:34:15

您可以使用 pinvoke 并调用 CopyFileEx。请注意您要查找的COPY_FILE_COPY_SYMLINK

You could make use of pinvoke and call CopyFileEx. Note the COPY_FILE_COPY_SYMLINK which is what you are looking for.

策马西风 2024-10-07 11:34:15

我认识到这是一个相当古老的线程,但我刚刚完成了一些支持此功能的 C 代码工作(是的,确实)。发帖是因为我查遍了这方面的资料,而且不容易找到。

遗憾的是,CopyFileExCOPY_FILE_SYMLINK 并不能解决问题。这只是在目标目录中创建一个具有正确名称的 0 大小文件,但没有符号链接。另一篇旧文章包含您可以尝试实现的解决方案: 如何复制目录符号链接作为目标的链接?

我确实认为 CopyFileEx 的问题是一个错误,在 Windows 10 中仍然存在。

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.

雨轻弹 2024-10-07 11:34:14

您可以使用 Win32 CopyFileEx 函数来执行此操作。这需要一些努力,但这里是整个 CopyFileEx 帮助程序类(C# 3.0 和 .NET 3.5 Client Profile 兼容并经过测试!)。您还可以将其重复用于您拥有的任何其他 CopyFileEx 任务:

  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);
  }

以下是一些示例代码,展示了如何使用它来复制符号链接(而不是它引用的文件):

  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);   
  }  

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);   
  }  
一场春暖 2024-10-07 11:34:14

.NET 框架中没有用于链接(硬链接、软链接或符号链接)的 API。

您必须调用 mklink.exe 使用 Process.Start 并创建所需的链接,
或者您可以寻找能够执行此类操作的第三方库。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文