Get all directories and catch permissions exception and continue - c#

public void newestFile(string path)
{
try
{
foreach (var item in dir.GetDirectories("*.*", SearchOption.AllDirectories))
{
var file = item.GetFiles().OrderByDescending(f => f.LastWriteTime).First();
}
}
catch (Exception ex)
{
}
}
I want to get the newest file from each directory from specific path and continue after catch the permission exception, currently my code stuck in catch and not continue.

Unfortunately Microsoft's implementation of GetDirectories() is extremely poor, and doesn't handle IO exceptions relating to access rights.
If you want to just skip over directories that you don't have access to (such as the special Recycle Bin folder, for example), then you have to write your own wrapper for the Windows API functions FindFirstFile() and FindNextFile().
Here's a complete example. If you run it, you'll see that it lists all the accessible directories on your C: drive.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using Microsoft.Win32.SafeHandles;
namespace Demo
{
public class Program
{
private void run()
{
string root = "C:\\";
foreach (var folder in FolderEnumerator.EnumerateFoldersRecursively(root))
Console.WriteLine(folder);
}
private static void Main()
{
new Program().run();
}
}
public static class FolderEnumerator
{
public static IEnumerable<string> EnumerateFoldersRecursively(string root)
{
foreach (var folder in EnumerateFolders(root))
{
yield return folder;
foreach (var subfolder in EnumerateFoldersRecursively(folder))
yield return subfolder;
}
}
public static IEnumerable<string> EnumerateFolders(string root)
{
WIN32_FIND_DATA findData;
string spec = Path.Combine(root, "*");
using (SafeFindHandle findHandle = FindFirstFile(spec, out findData))
{
if (!findHandle.IsInvalid)
{
do
{
if ((findData.cFileName != ".") && (findData.cFileName != "..")) // Ignore special "." and ".." folders.
{
if ((findData.dwFileAttributes & FileAttributes.Directory) != 0)
{
yield return Path.Combine(root, findData.cFileName);
}
}
}
while (FindNextFile(findHandle, out findData));
}
}
}
internal sealed class SafeFindHandle: SafeHandleZeroOrMinusOneIsInvalid
{
[SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
public SafeFindHandle(): base(true)
{
}
protected override bool ReleaseHandle()
{
if (!IsInvalid && !IsClosed)
{
return FindClose(this);
}
return (IsInvalid || IsClosed);
}
protected override void Dispose(bool disposing)
{
if (!IsInvalid && !IsClosed)
{
FindClose(this);
}
base.Dispose(disposing);
}
}
[StructLayout(LayoutKind.Sequential)]
internal struct FILETIME
{
public uint dwLowDateTime;
public uint dwHighDateTime;
public long ToLong()
{
return dwLowDateTime + ((long)dwHighDateTime) << 32;
}
};
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
internal struct WIN32_FIND_DATA
{
public FileAttributes dwFileAttributes;
public FILETIME ftCreationTime;
public FILETIME ftLastAccessTime;
public FILETIME ftLastWriteTime;
public int nFileSizeHigh;
public int nFileSizeLow;
public int dwReserved0;
public int dwReserved1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAX_PATH)]
public string cFileName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAX_ALTERNATE)]
public string cAlternate;
}
[DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
private static extern SafeFindHandle FindFirstFile(string lpFileName, out WIN32_FIND_DATA lpFindFileData);
[DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool FindNextFile(SafeHandle hFindFile, out WIN32_FIND_DATA lpFindFileData);
[DllImport("kernel32.dll", SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool FindClose(SafeHandle hFindFile);
private const int MAX_PATH = 260;
private const int MAX_ALTERNATE = 14;
}
}
Note: This code uses FindFirstFile() and FindNextFile() which iterate through all folders AND files. The code above is just ignoring the files and only returning the folders.
It would be more efficient to use FindFirstFileEx() and specify a flag to return only directories. I leave that change as the proverbial exercise for the reader. ;)

public string[] newestFile(string path){
IEnumerable<string> files = new string[]{};
foreach (var item in dir.GetDirectories(Path.Combine(path,"*.*"), SearchOption.AllDirectories))
{
try {
files = files.Concat(item.GetFiles().OrderByDescending(f => f.LastWriteTime).First());
}
catch {}
}
return files.ToArray();
}

Related

AccessViolationException when calling vkEnumeratePhysicalDevices via pInvoke from c#

I have the keen idea to write a wrapper for Vulkan in c#.
Unfortunately the second call of the Vulkan API already fails unexplainably.
The code below is taken from Sascha Willems' Vulkan examples and converted into c# code:
Vk.ApplicationInfo applicationInfo = new Vk.ApplicationInfo();
applicationInfo.sType = Vk.StructureType.STRUCTURE_TYPE_APPLICATION_INFO;
applicationInfo.pApplicationName = "Example";
applicationInfo.pEngineName = "Example";
applicationInfo.apiVersion = (uint)Math.Pow(2, 22) + 2;
string[] enabledExtensions = new string[] { "VK_KHR_surface", "VK_KHR_win32_surface" };
Vk.InstanceCreateInfo instanceCreateInfo = new Vk.InstanceCreateInfo();
instanceCreateInfo.sType = Vk.StructureType.STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instanceCreateInfo.pNext = null;
instanceCreateInfo.pApplicationInfo = applicationInfo;
instanceCreateInfo.enabledExtensionCount = (uint)enabledExtensions.Count();
instanceCreateInfo.ppEnabledExtensionNames = enabledExtensions;
Vk.Instance theInstance = new Vk.Instance();
Vk.Result vr = Vk.vkCreateInstance(instanceCreateInfo, IntPtr.Zero, theInstance);
// vr = SUCCESS
uint gpuCount = 0;
vr = Vk.vkEnumeratePhysicalDevices(theInstance, ref gpuCount, IntPtr.Zero);
//Fails with System.AccessViolationException
with
public static class Vk
{
public enum Result
{
SUCCESS = 0,
...
};
public enum StructureType
{
...
}
static Vk()
{
List<string> path = new List<string>() { #"C:\VulkanSDK\1.0.3.1\Source\lib32\" };
AddEnvironmentPaths(path);
}
static void AddEnvironmentPaths(IEnumerable<string> paths)
{
var path = new[] { Environment.GetEnvironmentVariable("PATH") ?? string.Empty };
string newPath = string.Join(Path.PathSeparator.ToString(), path.Concat(paths));
Environment.SetEnvironmentVariable("PATH", newPath);
}
[DllImport("vulkan-1.dll")]
public static extern Result vkCreateInstance(InstanceCreateInfo instanceCreateInfo, IntPtr pAllocator, Instance instance);
[StructLayout(LayoutKind.Sequential)]
public class InstanceCreateInfo
{
public StructureType sType;
public object pNext;
public uint flags;
public ApplicationInfo pApplicationInfo;
public uint enabledLayerCount;
public string[] ppEnabledLayerNames;
public uint enabledExtensionCount;
public string[] ppEnabledExtensionNames;
}
[StructLayout(LayoutKind.Sequential)]
public class ApplicationInfo
{
public StructureType sType;
public object pNext;
public string pApplicationName;
public uint applicationVersion;
public string pEngineName;
public uint engineVersion;
public uint apiVersion;
}
[StructLayout(LayoutKind.Sequential)]
public class Instance
{
}
[DllImport("vulkan-1.dll")]
public static extern Result vkEnumeratePhysicalDevices(Instance instance, ref uint pPhysicalDeviceCount, PhysicalDevice pPhysicalDevices);
[DllImport("vulkan-1.dll")]
public static extern Result vkEnumeratePhysicalDevices(Instance instance, ref uint pPhysicalDeviceCount, IntPtr pPhysicalDevices);
public class PhysicalDevice
{
}
}
My Suspicion is that Vk.Instance should be something else than just an empty class. VkInstance is in the official vulkan.h defined as typedef struct VkInstance_T* VkInstance. My understanding of this line is unfortunately very limited. I already tried exchanging the type Vk.Instance with IntPtr and object but without success.
Theses are important segments from vulkan.h
#define VK_DEFINE_HANDLE(object) typedef struct object##_T* object;
VK_DEFINE_HANDLE(VkInstance)
VK_DEFINE_HANDLE(VkPhysicalDevice)
VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(
const VkInstanceCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkInstance* pInstance);
VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDevices(
VkInstance instance,
uint32_t* pPhysicalDeviceCount,
VkPhysicalDevice* pPhysicalDevices);
Zastai answered my question.
It had to be
[DllImport("vulkan-1.dll")]
public static extern Result vkCreateInstance(InstanceCreateInfo instanceCreateInfo, IntPtr pAllocator, out IntPtr instance);
because it were indeed pointers to pointers.
IntPtr instance;
Vk.Result vr = Vk.vkCreateInstance(instanceCreateInfo, IntPtr.Zero, out instance);
uint gpuCount = 0;
vr = Vk.vkEnumeratePhysicalDevices(instance, ref gpuCount, IntPtr.Zero);
Thanks a lot!

Get total amount of memory from WinXP and above

There are already many answers about this topic, but is there a single way to get the the total amount of memory on a windows system from XP and above including Windows Server 2003?
What I have found:
Win32_LogicalMemoryConfiguration (Deprecated)
Win32_ComputerSystem (Minimum supported client: Vista)
Microsoft.VisualBasic.Devices.ComputerInfo (no XP support according to platforms)
thx
Add reference to Microsoft.VisualBasic and
var info = new Microsoft.VisualBasic.Devices.ComputerInfo();
Debug.WriteLine(info.TotalPhysicalMemory);
Debug.WriteLine(info.AvailablePhysicalMemory);
Debug.WriteLine(info.TotalVirtualMemory);
Debug.WriteLine(info.AvailableVirtualMemory);
edit : How can I get the total physical memory in C#?
or
You can make use of GlobalMemoryStatusEx : Example Here
private void DisplayMemory()
{
// Consumer of the NativeMethods class shown below
long tm = System.GC.GetTotalMemory(true);
NativeMethods oMemoryInfo = new NativeMethods();
this.lblMemoryLoadNumber.Text = oMemoryInfo.MemoryLoad.ToString();
this.lblIsMemoryTight.Text = oMemoryInfo.isMemoryTight().ToString();
if (oMemoryInfo.isMemoryTight())
this.lblIsMemoryTight.Text.Font.Bold = true;
else
this.lblIsMemoryTight.Text.Font.Bold = false;
}
Native class wrapper.
[CLSCompliant(false)]
public class NativeMethods {
private MEMORYSTATUSEX msex;
private uint _MemoryLoad;
const int MEMORY_TIGHT_CONST = 80;
public bool isMemoryTight()
{
if (_MemoryLoad > MEMORY_TIGHT_CONST )
return true;
else
return false;
}
public uint MemoryLoad
{
get { return _MemoryLoad; }
internal set { _MemoryLoad = value; }
}
public NativeMethods() {
msex = new MEMORYSTATUSEX();
if (GlobalMemoryStatusEx(msex)) {
_MemoryLoad = msex.dwMemoryLoad;
//etc.. Repeat for other structure members
}
else
// Use a more appropriate Exception Type. 'Exception' should almost never be thrown
throw new Exception("Unable to initalize the GlobalMemoryStatusEx API");
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
private class MEMORYSTATUSEX
{
public uint dwLength;
public uint dwMemoryLoad;
public ulong ullTotalPhys;
public ulong ullAvailPhys;
public ulong ullTotalPageFile;
public ulong ullAvailPageFile;
public ulong ullTotalVirtual;
public ulong ullAvailVirtual;
public ulong ullAvailExtendedVirtual;
public MEMORYSTATUSEX()
{
this.dwLength = (uint) Marshal.SizeOf(typeof( MEMORYSTATUSEX ));
}
}
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool GlobalMemoryStatusEx( [In, Out] MEMORYSTATUSEX lpBuffer);
}

Preventing GC from taking my delegate in C#

I'm referring back to a post i made a long time ago as i've only just got back to working with this WRG305API.dll.
With referral to: calling C++ functions containing callbacks in C#
Ive been trying to write an app that interfaces with this DLL and thanks to the guys that helped me back then. I've been able to get it working for a short period of time.
Ive been stopped by this annoying issue which is stated as:
A callback was made on a garbage collected delegate of type 'WinFFT!WinFFT.winradioIO.winRadioIOWrapper+CallbackFunc::Invoke'. This may cause application crashes ...
Here is the wrapper code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace WinFFT.winradioIO
{
class winRadioIOWrapper
{
private const string APIDLL_PATH = "WRG305API.dll";
public delegate void CallbackFunc(IntPtr p);
public CallbackFunc mycallback;
[StructLayout(LayoutKind.Sequential)]
public struct Features
{
public uint feature;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct RadioInfo
{
public uint length;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 9)]
public string serialNumber;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 9)]
public string productName;
public UInt64 minFrequency;
public UInt64 maxFrequency;
public Features feature;
}
[DllImport(APIDLL_PATH)]
public static extern int OpenRadioDevice(int deviceNumber);
[DllImport(APIDLL_PATH)]
public static extern bool CloseRadioDevice(int radioHandle);
[DllImport(APIDLL_PATH)]
public static extern int GetRadioList(ref RadioInfo info, int bufferSize, ref int infoSize);
[DllImport(APIDLL_PATH)]
public static extern bool IsDeviceConnected(int radioHandle);
[DllImport(APIDLL_PATH)]
public static extern bool GetInfo(int radioHandle, ref RadioInfo info);
[DllImport(APIDLL_PATH)]
public static extern int GetFrequency(int radioHandle);
[DllImport(APIDLL_PATH)]
public static extern bool SetFrequency(int radioHandle, int frequency);
[DllImport(APIDLL_PATH)]
private static extern bool CodecStart(int hRadio, CallbackFunc func, IntPtr CallbackTarget);
[DllImport(APIDLL_PATH)]
private static extern uint CodecRead(int hRadio, byte[] Buf, uint Size);
[DllImport(APIDLL_PATH)]
private static extern bool CodecStop(int hRadio);
public static bool startIFStream(int radioHandle)
{
bool bStarted = CodecStart(radioHandle, MyCallbackFunc, IntPtr.Zero);
return bStarted;
}
// Note: this method will be called from a different thread!
private static void MyCallbackFunc(IntPtr pData)
{
// Sophisticated work goes here...
}
public static void readIFStreamBlock(int radioHandle, byte[] streamDumpLocation, uint blockSize)
{
CodecRead(radioHandle, streamDumpLocation, blockSize);
}
public static bool stopIFStream(int radioHandle)
{
bool bStoped = CodecStop(radioHandle);
return bStoped;
}
}
}
Here is my Application interfacing class layer which provides the friendly methods to use the dll interface:
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
namespace WinFFT.winradioIO
{
class radioInterface
{
enum DeviceStatus { Disconnected, Connected, Unknown };
private static DeviceStatus deviceStatus = DeviceStatus.Unknown;
public static string radioName, serialNumber;
public static int minimumFreq, maximumFreq;
static int radioHandle;
static radioInterface()
{
InitializeDeviceConnection();
}
public static void duffMethod(IntPtr ptr)
{
}
private static void InitializeDeviceConnection()
{
winRadioIOWrapper.CloseRadioDevice(radioHandle);
deviceStatus = DeviceStatus.Disconnected;
// Get Radio Info
winRadioIOWrapper.RadioInfo radioInfo = new winRadioIOWrapper.RadioInfo();
int aStructSize = Marshal.SizeOf(radioInfo), anInfoSize = 0;
radioInfo.length = (uint)aStructSize;
if (winRadioIOWrapper.GetRadioList(ref radioInfo, aStructSize, ref anInfoSize) == 1)
{
radioName = radioInfo.productName;
serialNumber = radioInfo.serialNumber;
minimumFreq = (int)radioInfo.minFrequency;
maximumFreq = (int)radioInfo.maxFrequency;
}
// Open device
radioHandle = winRadioIOWrapper.OpenRadioDevice(0);
CheckDeviceConnection();
}
private static void CheckDeviceConnection()
{
bool anIsDeviceConnected = winRadioIOWrapper.IsDeviceConnected(radioHandle);
if (deviceStatus == DeviceStatus.Unknown ||
deviceStatus == DeviceStatus.Disconnected && anIsDeviceConnected ||
deviceStatus == DeviceStatus.Connected && !anIsDeviceConnected)
{
if (anIsDeviceConnected)
{
deviceStatus = DeviceStatus.Connected;
winRadioIOWrapper.startIFStream(radioHandle);
}
else
{
winRadioIOWrapper.CloseRadioDevice(radioHandle);
deviceStatus = DeviceStatus.Disconnected;
}
}
}
public static void ReadIFStream(ref byte[] bufferLocation)
{
winRadioIOWrapper.readIFStreamBlock(radioHandle, bufferLocation, (uint)bufferLocation.Length);
}
public static void SetFreq(int valueInHz)
{
winRadioIOWrapper.SetFrequency(radioHandle, valueInHz);
}
public static void ShutDownRadio()
{
winRadioIOWrapper.CloseRadioDevice(radioHandle);
}
}
}
I Understand why AVIDeveloper chose the path, its is brilliant for continuously streaming out the data from the WinRadio Reciever (which is what the DLL is for), but the function CodecRead in the DLL allows one to copy a specified number of bytes from the radio's buffer. This is the path I went as I want to control how regularly I take the data and hence why I left the delegate function alone. But with this as it is at the moment, I am loosing the delegate in the wrapper to the GC and I am really stumped on how to prevent this.
Thanks in Advance guys.
Store the delegate as a field.
private static CallbackFunc _callback = new CallbackFunc(MyCallbackFunc);
public static bool startIFStream(int radioHandle)
{
bool bStarted = CodecStart(radioHandle, _callback, IntPtr.Zero);
return bStarted;
}

How can I get the PID of the parent process of my application

My winform application is launched by another application (the parent), I need determine the pid of the application which launch my application using C#.
WMI is the easier way to do this in C#. The Win32_Process class has the ParentProcessId property. Here's an example:
using System;
using System.Management; // <=== Add Reference required!!
using System.Diagnostics;
class Program {
public static void Main() {
var myId = Process.GetCurrentProcess().Id;
var query = string.Format("SELECT ParentProcessId FROM Win32_Process WHERE ProcessId = {0}", myId);
var search = new ManagementObjectSearcher("root\\CIMV2", query);
var results = search.Get().GetEnumerator();
results.MoveNext();
var queryObj = results.Current;
var parentId = (uint)queryObj["ParentProcessId"];
var parent = Process.GetProcessById((int)parentId);
Console.WriteLine("I was started by {0}", parent.ProcessName);
Console.ReadLine();
}
}
Output when run from Visual Studio:
I was started by devenv
Using Brian R. Bondy's answer as a guide, as well as what is on PInvoke.net, and some Reflector output, I have produced this, for use in LinqPad MyExtensions:
using Microsoft.Win32.SafeHandles;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
static class ProcessExtensions
{
public static int ParentProcessId(this Process process)
{
return ParentProcessId(process.Id);
}
public static int ParentProcessId(int Id)
{
PROCESSENTRY32 pe32 = new PROCESSENTRY32{};
pe32.dwSize = (uint)Marshal.SizeOf(typeof(PROCESSENTRY32));
using(var hSnapshot = CreateToolhelp32Snapshot(SnapshotFlags.Process, (uint)Id))
{
if(hSnapshot.IsInvalid)
throw new Win32Exception();
if(!Process32First(hSnapshot, ref pe32))
{
int errno = Marshal.GetLastWin32Error();
if(errno == ERROR_NO_MORE_FILES)
return -1;
throw new Win32Exception(errno);
}
do {
if(pe32.th32ProcessID == (uint)Id)
return (int)pe32.th32ParentProcessID;
} while(Process32Next(hSnapshot, ref pe32));
}
return -1;
}
private const int ERROR_NO_MORE_FILES = 0x12;
[DllImport("kernel32.dll", SetLastError=true)]
private static extern SafeSnapshotHandle CreateToolhelp32Snapshot(SnapshotFlags flags, uint id);
[DllImport("kernel32.dll", SetLastError=true)]
private static extern bool Process32First(SafeSnapshotHandle hSnapshot, ref PROCESSENTRY32 lppe);
[DllImport("kernel32.dll", SetLastError=true)]
private static extern bool Process32Next(SafeSnapshotHandle hSnapshot, ref PROCESSENTRY32 lppe);
[Flags]
private enum SnapshotFlags : uint
{
HeapList = 0x00000001,
Process = 0x00000002,
Thread = 0x00000004,
Module = 0x00000008,
Module32 = 0x00000010,
All = (HeapList | Process | Thread | Module),
Inherit = 0x80000000,
NoHeaps = 0x40000000
}
[StructLayout(LayoutKind.Sequential)]
private struct PROCESSENTRY32
{
public uint dwSize;
public uint cntUsage;
public uint th32ProcessID;
public IntPtr th32DefaultHeapID;
public uint th32ModuleID;
public uint cntThreads;
public uint th32ParentProcessID;
public int pcPriClassBase;
public uint dwFlags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=260)] public string szExeFile;
};
[SuppressUnmanagedCodeSecurity, HostProtection(SecurityAction.LinkDemand, MayLeakOnAbort=true)]
internal sealed class SafeSnapshotHandle : SafeHandleMinusOneIsInvalid
{
internal SafeSnapshotHandle() : base(true)
{
}
[SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode=true)]
internal SafeSnapshotHandle(IntPtr handle) : base(true)
{
base.SetHandle(handle);
}
protected override bool ReleaseHandle()
{
return CloseHandle(base.handle);
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true, ExactSpelling=true)]
private static extern bool CloseHandle(IntPtr handle);
}
}
If you have control over the parent application, you could modify the parent to pass its PID to the child when it launches the process.
Check the th32ParentProcessID member of a CreateToolhelp32Snapshot enumeration.
For an example of how to do this see my post here.
Since you are using C# though you'll need to use DllImports. In the linked post there are MSDN pages for each for the functions you need. At the bottom of each MSDN page they have the code for DllImport for C#.
There is also an easier way using managed code only but it doesn't work if you have the more than one process name started by different applications.

How can I opt the user to delete all files in a folder (but no subdirectories)?

I've got a folder path. The folder contains a lot of files as well as some subfolders. I'd like to let the user delete the files (but not the folders) using the standard windows dialog.
I'm currently using this code, which deletes the whole folder.
Microsoft.VisualBasic.FileIO.FileSystem.DeleteDirectory (
path,
UIOption.AllDialogs,
RecycleOption.SendToRecycleBin,
UICancelOption.DoNothing);
I'm aware I could enumerate all files and prompt the user for each file, but that's not practical at all.
Why not just write a function for this specific task?
public static void DeleteFilesInFolder()
{
using(var dlg = new FolderBrowserDialog())
{
if(dlg.ShowDialog() == DialogResult.OK)
{
var folderPath = dlg.SelectedPath;
var dir = new DirectoryInfo(folderPath);
var files =dir.GetFiles();
foreach (var f in files)
{
try
{
f.Delete();
}
catch (Exception ex) {
//handle this error
}
}
}
}
}
ah ok, just a suggestion..
then have a look at this:
http://www.blackwasp.co.uk/RecycleBin2.aspx
[StructLayout(LayoutKind.Sequential)]
public struct SHFILEOPSTRUCT
{
public IntPtr hwnd;
public uint wFunc;
public string pFrom;
public string pTo;
public ushort fFlags;
public int fAnyOperationsAborted;
public IntPtr hNameMappings;
[MarshalAs(UnmanagedType.LPWStr)]
public string lpszProgressTitle;
}
private const int FO_DELETE = 0x0003;
private const int FOF_SILENT = 0x0004;
private const int FOF_ALLOWUNDO = 0x0040;
private const int FOF_NOCONFIRMATION = 0x0010;
private const int FOF_WANTNUKEWARNING = 0x4000;
[DllImport("Shell32.dll")]
static extern int SHFileOperation([In] ref SHFILEOPSTRUCT lpFileOp);
used like this to delete all files matching the *.* pattern in a folder:
SHFILEOPSTRUCT operation = new SHFILEOPSTRUCT();
operation.wFunc = FO_DELETE;
operation.pFrom = #"c:\Recycle\*.*" + "\0\0";
operation.fFlags = FOF_ALLOWUNDO;
int result = SHFileOperation(ref operation);
Visual Basic uses the SHFileOperation() API function to display the dialog. I think you can call it yourself and customize it the way you want by specifying the FOF_FILESONLY flag for the SHFILEOPSTRUCT.fFlags member. The P/Invoke is gritty, visit pinvoke.net for the declarations.

Categories