حذف الملف إلى سلة المحذوفات على نظام التشغيل Windows x64 في C#

StackOverflow https://stackoverflow.com/questions/2342628

  •  23-09-2019
  •  | 
  •  

سؤال

لقد حصلت على هذا الفصل الذي يبدو أنه يعمل بشكل جيد على أنظمة غير 64 بت.

using System;
using System.Runtime.InteropServices;

namespace DeleteToRecycleBin
{
/// <summary>
/// Send files directly to the recycle bin.
/// </summary>
public class RecybleBin
{

    /// <summary>
    /// Possible flags for the SHFileOperation method.
    /// </summary>
    [Flags]
    public enum FileOperationFlags: ushort 
    {
        /// <summary>
        /// Do not show a dialog during the process
        /// </summary>
        FOF_SILENT =                0x0004,
        /// <summary>
        /// Do not ask the user to confirm selection
        /// </summary>
        FOF_NOCONFIRMATION =        0x0010,
        /// <summary>
        /// Delete the file to the recycle bin.  (Required flag to send a file to the bin
        /// </summary>
        FOF_ALLOWUNDO =             0x0040,
        /// <summary>
        /// Do not show the names of the files or folders that are being recycled.
        /// </summary>
        FOF_SIMPLEPROGRESS =        0x0100,
        /// <summary>
        /// Surpress errors, if any occur during the process.
        /// </summary>
        FOF_NOERRORUI =             0x0400,
        /// <summary>
        /// Warn if files are too big to fit in the recycle bin and will need
        /// to be deleted completely.
        /// </summary>
        FOF_WANTNUKEWARNING =       0x4000,
    }

    /// <summary>
    /// File Operation Function Type for SHFileOperation
    /// </summary>
    public enum FileOperationType: uint
    {
        /// <summary>
        /// Move the objects
        /// </summary>
        FO_MOVE =                   0x0001,
        /// <summary>
        /// Copy the objects
        /// </summary>
        FO_COPY =                   0x0002,
        /// <summary>
        /// Delete (or recycle) the objects
        /// </summary>
        FO_DELETE =                 0x0003,
        /// <summary>
        /// Rename the object(s)
        /// </summary>
        FO_RENAME =                 0x0004,
    }



    /// <summary>
    /// SHFILEOPSTRUCT for SHFileOperation from COM
    /// </summary>
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 1)]
    private struct SHFILEOPSTRUCT
    {

        public IntPtr hwnd;
        [MarshalAs(UnmanagedType.U4)]
        public FileOperationType wFunc;
        public string pFrom;
        public string pTo;
        public FileOperationFlags fFlags;
        [MarshalAs(UnmanagedType.Bool)]
        public readonly bool fAnyOperationsAborted;
        public readonly IntPtr hNameMappings;
        public readonly string lpszProgressTitle;
    }

    [DllImport("shell32.dll", CharSet = CharSet.Auto)]
    private static extern int SHFileOperation(ref SHFILEOPSTRUCT FileOp);

    /// <summary>
    /// Send file to recycle bin
    /// </summary>
    /// <param name="path">Location of directory or file to recycle</param>
    /// <param name="flags">FileOperationFlags to add in addition to FOF_ALLOWUNDO</param>
    public static bool Send(string path, FileOperationFlags flags)
    {
        try
        {
            SHFILEOPSTRUCT fs = new SHFILEOPSTRUCT
                                    {
                                        wFunc = FileOperationType.FO_DELETE,
                                        pFrom = path + '\0' + '\0',
                                        fFlags = FileOperationFlags.FOF_ALLOWUNDO | flags
                                    };

            // important to double-terminate the string.
            SHFileOperation(ref fs);
            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }

    /// <summary>
    /// Send file to recycle bin.  Display dialog, display warning if files are too big to fit (FOF_WANTNUKEWARNING)
    /// </summary>
    /// <param name="path">Location of directory or file to recycle</param>
    public static bool Send(string path) {
        return Send(path, FileOperationFlags.FOF_NOCONFIRMATION | FileOperationFlags.FOF_WANTNUKEWARNING);
    }

    /// <summary>
    /// Send file silently to recycle bin.  Surpress dialog, surpress errors, delete if too large.
    /// </summary>
    /// <param name="path">Location of directory or file to recycle</param>
    public static bool SendSilent(string path)
    {
        return Send(path, FileOperationFlags.FOF_NOCONFIRMATION | FileOperationFlags.FOF_NOERRORUI | FileOperationFlags.FOF_SILENT);

    }
}

}

هل هناك طريقة لإصلاحها حتى تعمل بشكل جيد على x64 أيضًا؟لقد حاولت تغيير ushort إلى ulong وبعض التعديلات الأخرى لكنه لا يعمل.

أعلم أن هناك حلولًا أخرى تتطلب الرجوع إلى Microsoft.VisualBasic ولكني أفضل طريقة p/invocation.

الإجابة الصحيحة هي:

ضمن x64، يجب الإعلان عن SHFILEOPSTRUCT بدون المعلمة Pack = 1، وإلا فسوف تفشل.يعد هذا أمرًا صعبًا للغاية إذا كنت تريد أن تكون التعليمات البرمجية الخاصة بك مستقلة عن النظام الأساسي، حيث يتعين عليك الإعلان عن بنيتين منفصلتين، واحدة بها حزمة = 1، وواحدة بدونها.يجب عليك بعد ذلك الإعلان عن استدعاءين مختلفين لـ SHFileOperation، واحد لكل من الهياكل.ثم عليك أن تقرر أي واحد تريد الاتصال به اعتمادًا على ما إذا كنت تعمل على 32 أو 64 بت.

هل كانت مفيدة؟

المحلول

هل نظرت إلى استدعاء موقع؟لديه تعريف مختلف قليلاً لنوع FILEOPSTRUCT، مما يفرض Unicode لشيء واحد.أتساءل عما إذا كان charset = auto يربك الأمور... مثل أنه افتراضيًا على ANSI على 32 بت، ولكن Unicode على 64 بت وحدث خطأ ما في مكان ما في المنتصف.

يحرر؛كما أن النهج المرجعي لـ Visual Basic هو أسلوب بسيط...أعلم أن الناس ينفرون منه لسبب ما، لكن مكتبات الارتباط الحيوي (DLL) ذات الصلة لا تزال جزءًا من إطار العمل الأساسي، لذلك لن تقوم بإضافة أي تبعيات جديدة.

نصائح أخرى

غريب كما يبدو ، .net لديه بالفعل وظائف لحذفها إلى سلة إعادة التدوير ... لكنها في Microsoft.VisualBasic مساحة الاسم. خاصة، Microsoft.VisualBasic.FileIO.

using Microsoft.VisualBasic.FileIO;

// class declaration, method start here

// Send file to recycle bin without dialog
FileSystem.DeleteFile("pathToFile", UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin);

// Send file to recycle bin without dialog
FileSystem.DeleteFile("pathToFile", UIOption.AllDialogs, RecycleOption.SendToRecycleBin);

// Directories are the same, but with DeleteDirectory instead
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top