调用windows复制对话框复制文件

命令行调用windows复制对话框复制文件,C#版可能有些Bug报错, 请测试使用!

一:结果演示

1). 复制演示

在这里插入图片描述

2). 提示覆盖

在这里插入图片描述

3). 不提示覆盖

在这里插入图片描述

二. C#源代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Runtime.InteropServices;

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

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 2)]
        struct SHFILEOPSTRUCT
        {
            public IntPtr hwnd;
            public FO_Func wFunc;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string pFrom;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string pTo;
            public ushort fFlags;
            [MarshalAs(UnmanagedType.Bool)]
            public bool fAnyOperationsAborted;
            public IntPtr hNameMappings;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string lpszProgressTitle;

        }


        [DllImport("shell32.dll", CharSet = CharSet.Unicode)]
        static extern int SHFileOperation([In, Out] ref SHFILEOPSTRUCT lpFileOp);

        static string usage = "调用Windows自带的复制文件对话框来复制文件。\n" +
                        "\n CopyX [/Y] source destination\n\n" +
                        "\t/Y         \t不提示直接覆盖目标文件。\n" +
                        "\tsource     \t指定要复制的文件。\n" +
                        "\tdestination\t为新文件指定目录和/或文件名。";


        static int Main(string[] args)
        {
            bool bOverWrite = false;
            string srcPath = null, dstPath = null;
            foreach (string arg in args)
            {
                if (arg == "/y" || arg == "/Y")
                {
                    bOverWrite = true;
                }
                else if (srcPath == null)
                {
                    srcPath = arg;
                }
                else if (dstPath == null)
                {
                    dstPath = arg;
                }
            }

            if (args.Contains("/?") || srcPath == null || dstPath == null)
            {
                Console.WriteLine(usage);
                return -1;
            }

            if ((!File.Exists(srcPath)) && (!Directory.Exists(srcPath)))
            {
                Console.WriteLine("复制失败, 源文件不存在!");
                return -1;
            }


            SHFILEOPSTRUCT lpFileOp = new SHFILEOPSTRUCT();
            lpFileOp.hwnd = IntPtr.Zero;
            lpFileOp.wFunc = FO_Func.FO_COPY;
            lpFileOp.pFrom = srcPath + '\0';
            lpFileOp.pTo = dstPath + '\0';
            /*
            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
            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
            */
            lpFileOp.fFlags = bOverWrite ? (ushort)(0x0010 | 0x0200) : (ushort)0x0100;
            lpFileOp.hNameMappings = IntPtr.Zero;
            lpFileOp.fAnyOperationsAborted = false;

            int ret = SHFileOperation(ref lpFileOp);
            switch (ret)
            {
                case 0x00: return 0;  // 拷贝成功
                case 0x71: Console.WriteLine("The source and destination files are the same file."); break;
                case 0x72: Console.WriteLine("Multiple file paths were specified in the source buffer, but only one destination file path."); break;
                case 0x73: Console.WriteLine("Rename operation was specified but the destination path is a different directory. Use the move operation instead."); break;
                case 0x74: Console.WriteLine("The source is a root directory, which cannot be moved or renamed."); break;
                case 0x75: Console.WriteLine("The operation was canceled by the user, or silently canceled if the appropriate flags were supplied to SHFileOperation."); break;
                case 0x76: Console.WriteLine("The destination is a subtree of the source."); break;
                case 0x78: Console.WriteLine("Security settings denied access to the source."); break;
                case 0x79: Console.WriteLine("The source or destination path exceeded or would exceed MAX_PATH."); break;
                case 0x7A: Console.WriteLine("The operation involved multiple destination paths, which can fail in the case of a move operation."); break;
                case 0x7C: Console.WriteLine("The path in the source or destination or both was invalid."); break;
                case 0x7D: Console.WriteLine("The source and destination have the same parent folder."); break;
                case 0x7E: Console.WriteLine("The destination path is an existing file."); break;
                case 0x80: Console.WriteLine("The destination path is an existing folder."); break;
                case 0x81: Console.WriteLine("The name of the file exceeds MAX_PATH."); break;
                case 0x82: Console.WriteLine("The destination is a read-only CD-ROM, possibly unformatted."); break;
                case 0x83: Console.WriteLine("The destination is a read-only DVD, possibly unformatted."); break;
                case 0x84: Console.WriteLine("The destination is a writable CD-ROM, possibly unformatted."); break;
                case 0x85: Console.WriteLine("The file involved in the operation is too large for the destination media or file system."); break;
                case 0x86: Console.WriteLine("The source is a read-only CD-ROM, possibly unformatted."); break;
                case 0x87: Console.WriteLine("The source is a read-only DVD, possibly unformatted."); break;
                case 0x88: Console.WriteLine("The source is a writable CD-ROM, possibly unformatted."); break;
                case 0xB7: Console.WriteLine("MAX_PATH was exceeded during the operation."); break;
                case 0x402: Console.WriteLine("An unknown error occurred. This is typically due to an invalid path in the source or destination. This error does not occur on Windows Vista and later."); break;
                default: Console.WriteLine("复制失败, 未知错误代码【" + ret + "】,参考: https://docs.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shfileoperationa"); break;
            }
            return ret;
        }
    }
}

三. AutoIt 源代码

#NoTrayIcon

#pragma compile(FileDescription, '简单调用Windows自带复制对话框复制文件或文件夹')
#pragma compile(FileVersion, 1.0.0.0)
#pragma compile(ProductName, Leo)
#pragma compile(ProductVersion, 1.0.0.0)
#pragma compile(LegalCopyright, Copyright ©  2020)
#pragma compile(x64, false)
#pragma compile(UPX, true)
#pragma compile(Compression, 9)
#pragma compile(Console, true)

#include <APIShellExConstants.au3>
#include <WinAPIFiles.au3>
#include <WinAPIShellEx.au3>

Global $bOverWrite = False, $bHelp = False
Global $srcPath = '', $dstPath = ''


For $i = 1 To $CmdLine[0]
    If $CmdLine[$i] = '/y' Then
        $bOverWrite = True
    ElseIf $CmdLine[$i] = '/?' Then
        $bHelp = True
    ElseIf $srcPath = '' Then
        $srcPath = $CmdLine[$i]
    ElseIf $dstPath = '' Then
        $dstPath = $CmdLine[$i]
    EndIf
Next


If $bHelp Or $srcPath = '' Or $dstPath = '' Then
    ConsoleWrite("调用Windows自带的复制文件对话框来复制文件。" & @CRLF & @CRLF & _
                 "CopyX [/Y] source destination" & @CRLF & @CRLF & @TAB & _
                 "/Y             不提示直接覆盖目标文件。" & @CRLF & @TAB & _
                 "source         指定要复制的文件。" & @CRLF & @TAB & _
                 "destination    为新文件指定目录和/或文件名。" & @CRLF)
    Exit -1
EndIf

If FileExists($srcPath) <> 1 Then
    ConsoleWriteError('复制失败, 源文件不存在!')
    Exit -1
EndIf

If $bOverWrite Then
     _WinAPI_ShellFileOperation($srcPath, $dstPath, $FO_COPY, BitOR($FOF_NOCONFIRMATION, $FOF_NOCONFIRMMKDIR))
     Global $ret = @extended
Else
     _WinAPI_ShellFileOperation($srcPath, $dstPath, $FO_COPY, $FOF_SIMPLEPROGRESS)
     Global $ret = @extended
EndIf


If $ret <> 0 Then
    ConsoleWriteError("复制失败,错误代码: " & $ret & " 参考: https://www.autoitscript.com/autoit3/docs/libfunctions/_WinAPI_ShellFileOperation.htm")
    Exit $ret
Else
    Exit 0
EndIf

四. 文件说明及下载

C#版编译为DoNet4.5,Win7需安装4.5框架
AutoIt版默认支持Win7 ~ Win10 比较稳定
可自行编译

https://download.csdn.net/download/LeoForBest/12565079

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值