Functions/GenXdev.FileSystem/Move-ToRecycleBin.cs
// ################################################################################
// Part of PowerShell module : GenXdev.FileSystem // Original cmdlet filename : Move-ToRecycleBin.cs // Original author : René Vaessen / GenXdev // Version : 1.302.2025 // ################################################################################ // Copyright (c) René Vaessen / GenXdev // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ################################################################################ using System; using System.IO; using System.Management.Automation; using System.Runtime.InteropServices; namespace GenXdev.FileSystem { /// <summary> /// <para type="synopsis"> /// Moves files and directories to the Windows Recycle Bin safely. /// </para> /// /// <para type="description"> /// Safely moves files or directories to the recycle bin using the Windows Shell API, /// even if they are currently in use. The function uses the Shell.Application COM /// object to perform the operation, ensuring proper recycling behavior and undo /// capability. /// </para> /// /// <para type="description"> /// PARAMETERS /// </para> /// /// <para type="description"> /// -Path <string[]><br/> /// One or more paths to files or directories that should be moved to the recycle /// bin. Accepts pipeline input and wildcards. The paths must exist and be /// accessible.<br/> /// - <b>Aliases</b>: FullName<br/> /// - <b>Position</b>: 0<br/> /// - <b>Default</b>: None<br/> /// </para> /// /// <example> /// <para>Move a single file to the recycle bin</para> /// <para>Detailed explanation of the example.</para> /// <code> /// Move-ToRecycleBin -Path "C:\temp\old-report.txt" /// </code> /// </example> /// /// <example> /// <para>Move multiple files using pipeline and alias</para> /// <para>Detailed explanation of the example.</para> /// <code> /// "file1.txt","file2.txt" | recycle /// </code> /// </example> /// </summary> [Cmdlet(VerbsCommon.Move, "ToRecycleBin")] [OutputType(typeof(bool))] public class MoveToRecycleBinCommand : PSGenXdevCmdlet { /// <summary> /// One or more paths to files or directories that should be moved to the recycle /// bin. Accepts pipeline input and wildcards. The paths must exist and be /// accessible. /// </summary> [Parameter( Mandatory = true, Position = 0, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true, HelpMessage = "Specify the path(s) to move to the recycle bin")] [ValidateNotNullOrEmpty] [Alias("FullName")] public string[] Path { get; set; } private bool success = true; private dynamic shellObj; /// <summary> /// Begin processing - initialize shell automation object for recycle bin operations /// </summary> protected override void BeginProcessing() { // initialize shell automation object for recycle bin operations shellObj = null; try { shellObj = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application")); WriteVerbose("Created Shell.Application COM object for recycle operations"); } catch (Exception ex) { WriteError(new ErrorRecord(ex, "ComObjectCreationFailed", ErrorCategory.ResourceUnavailable, null)); success = false; } } /// <summary> /// Process record - main cmdlet logic for processing each path /// </summary> protected override void ProcessRecord() { if (shellObj == null) { return; } foreach (string itemPath in Path) { // convert relative or shorthand paths to full filesystem paths string fullPath = ExpandPath(itemPath); WriteVerbose($"Processing path: {fullPath}"); try { // check if the target path actually exists before attempting to recycle if (File.Exists(fullPath) || Directory.Exists(fullPath)) { // confirm the recycle operation with the user if (ShouldProcess(fullPath, "Move to Recycle Bin")) { // split the path into directory and filename for shell operation string dirName = System.IO.Path.GetDirectoryName(fullPath); string fileName = System.IO.Path.GetFileName(fullPath); // get shell folder object for the directory containing the item dynamic folderObj = shellObj.Namespace(dirName); dynamic fileObj = folderObj.ParseName(fileName); // perform the recycle operation using shell verbs fileObj.InvokeVerb("delete"); WriteVerbose($"Successfully moved to recycle bin: {fullPath}"); } } else { WriteWarning($"Path not found: {fullPath}"); success = false; } } catch (Exception ex) { WriteError(new ErrorRecord(ex, "RecycleOperationFailed", ErrorCategory.InvalidOperation, fullPath)); success = false; } } } /// <summary> /// End processing - cleanup the COM object and return success status /// </summary> protected override void EndProcessing() { // cleanup the COM object to prevent resource leaks if (shellObj != null) { try { Marshal.ReleaseComObject(shellObj); WriteVerbose("Released Shell.Application COM object"); } catch (Exception ex) { WriteWarning($"Failed to release COM object: {ex.Message}"); } } WriteObject(success); } } } |