【问题标题】:VB FileSystem.Copy - how to get new name of renamed fileVB FileSystem.Copy - 如何获得重命名文件的新名称
【发布时间】:2012-09-11 23:50:49
【问题描述】:

我正在使用此功能将文件复制到程序目录中:

new Computer().FileSystem.CopyFile(source,
                                   destination,
                                   UIOption.AllDialogs, 
                                   UICancelOption.ThrowException);

如果存在同名文件,则向用户显示常规窗口对话框,要求用新名称替换、取消或复制。

是否可以返回该文件的新名称?

【问题讨论】:

  • 为什么不确认文件不存在?
  • 它们可能是两个不同的同名文件。我可以做所有的检查并询问有关重命名或覆盖自己的问题,但这违背了使用此功能的目的
  • @mobiletim 我认为无论是使用此函数还是 Windows API 函数(如 SHCopyFile)或其他相关 API,都无法获得您想要的东西,因为它们(至少我知道的那些,只返回一个错误代码或一个布尔值,表明复制操作是否成功),您可能需要询问用户并注意重命名和覆盖您自己。
  • 底层 Windows API 函数 (SHFileOperation) 能够通过 SHFILEOPSTRUCT.hNameMappings 成员返回此信息。你需要的 pinvoke 是坚韧不拔的。

标签: c# .net vb.net filenames


【解决方案1】:

我找到了这个code,它可以满足您的需求,但我的解释是在 C# 中...

public class Win32ApiUtils
{
    [StructLayout(LayoutKind.Sequential, Pack = 2, CharSet = CharSet.Unicode)]
    public struct SHFILEOPSTRUCT
    {
        public IntPtr hwnd;
        public FO_Func WFunc;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string PFrom;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string pTO;
        public ushort fFlags;
        public bool FAnyOperationsAborted;
        public IntPtr HNameMappings;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string LpszProgressTitle;

    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    private struct SHNAMEMAPPING
    {
        [MarshalAs(UnmanagedType.LPWStr)]
        public string PszOldPath;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string PszNewPath;
        public int CchOldPath;
        public int CchNewPath;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct HANDLETOMAPPINGS
    {
        public uint UNumberOfMappings;
        public IntPtr LpSHNameMapping;
    }

    [DllImport("Shell32.dll", CharSet = CharSet.Unicode)]
    private static extern int SHFileOperation(ref SHFILEOPSTRUCT LpFileOp);

    [DllImport("Shell32.dll")]
    private static extern void SHFreeNameMappings(SHNAMEMAPPING IntPtr);

    public static int CopyFiles()
    {
        // set up our file operation structure
        SHFILEOPSTRUCT sh;
        sh.hwnd = IntPtr.Zero;
        sh.WFunc = FO_Func.FO_COPY;

        sh.PFrom = @"C:\temp\f1\a.txt" + Constants.vbNullChar + @"C:\temp\f1\b.txt" + Constants.vbNullChar +
                   Constants.vbNullChar;

        sh.fFlags = (ushort)FILEOP_FLAGS_ENUM.FOF_ALLOWUNDO
                    | (ushort)FILEOP_FLAGS_ENUM.FOF_MULTIDESTFILES
                    | (ushort)FILEOP_FLAGS_ENUM.FOF_WANTMAPPINGHANDLE;

        sh.FAnyOperationsAborted = false;
        sh.HNameMappings = IntPtr.Zero;
        sh.LpszProgressTitle = null;

        sh.pTO = @"C:\temp\a.txt" + Constants.vbNullChar + @"C:\temp\b.txt" + Constants.vbNullChar +
                 Constants.vbNullChar;

        int ret = SHFileOperation(ref sh);

        if (sh.HNameMappings != IntPtr.Zero)
        {
            // Copy from Sh.HNameMappings to HANDLETOMAPPINGS 
            HANDLETOMAPPINGS mappings =
                (HANDLETOMAPPINGS)Marshal.PtrToStructure(sh.HNameMappings, typeof(HANDLETOMAPPINGS));

            // initialize the pointer for reading at the position of the mappings.LpSHNameMapping 
            IntPtr ptr = mappings.LpSHNameMapping;

            for (int I = 0; I < (int)mappings.UNumberOfMappings; I++)
            {
                // read from the pointer
                // copying to SHNAMEMAPPING
                SHNAMEMAPPING mapping = (SHNAMEMAPPING)Marshal.PtrToStructure(ptr, typeof(SHNAMEMAPPING));

                // create file info from mapping
                // something we can get at
                FileInfo fileNew = new FileInfo(mapping.PszNewPath);

                Console.WriteLine("new file name: {0}", fileNew.Name);

                // advance by the size of the structure to the next SHNAMEMAPPING
                ptr = new IntPtr(ptr.ToInt32() + Marshal.SizeOf(typeof(SHNAMEMAPPING)));
            }
        }

        return ret;
    }

    [Flags]
    private enum FILEOP_FLAGS_ENUM : ushort
    {
        FOF_MULTIDESTFILES = 0x0001,
        FOF_CONFIRMMOUSE = 0x0002,
        FOF_SILENT = 0x0004, // don't create progress/report
        FOF_RENAMEONCOLLISION = 0x0008,
        FOF_NOCONFIRMATION = 0x0010, // Don't prompt the user.
        FOF_WANTMAPPINGHANDLE = 0x0020, // Fill in SHFILEOPSTRUCT.hNameMappings
        // Must be freed using SHFreeNameMappings
        FOF_ALLOWUNDO = 0x0040,
        FOF_FILESONLY = 0x0080, // on *.*, do only files
        FOF_SIMPLEPROGRESS = 0x0100, // means don't show names of files
        FOF_NOCONFIRMMKDIR = 0x0200, // don't confirm making any needed dirs
        FOF_NOERRORUI = 0x0400, // don't put up error UI
        FOF_NOCOPYSECURITYATTRIBS = 0x0800, // dont copy NT file Security Attributes
        FOF_NORECURSION = 0x1000, // don't recurse into directories.
        FOF_NO_CONNECTED_ELEMENTS = 0x2000, // don't operate on connected elements.
        FOF_WANTNUKEWARNING = 0x4000,
        // during delete operation, warn if nuking instead of recycling (partially overrides FOF_NOCONFIRMATION)
        FOF_NORECURSEREPARSE = 0x8000, // treat reparse points as objects, not containers
    }

    public enum FO_Func : uint
    {
        FO_MOVE = 0x0001,
        FO_COPY = 0x0002,
        FO_DELETE = 0x0003,
        FO_RENAME = 0x0004,
    }


}

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-23
    • 2012-08-01
    • 2021-11-02
    • 2014-06-01
    • 2020-10-21
    • 2016-05-09
    相关资源
    最近更新 更多