diff --git a/BurnOutSharp/ExecutableType/Microsoft/Entries/ResourceDirectoryTableEntry.cs b/BurnOutSharp/ExecutableType/Microsoft/Entries/ResourceDirectoryTableEntry.cs
index d850f70f..b48383a3 100644
--- a/BurnOutSharp/ExecutableType/Microsoft/Entries/ResourceDirectoryTableEntry.cs
+++ b/BurnOutSharp/ExecutableType/Microsoft/Entries/ResourceDirectoryTableEntry.cs
@@ -62,7 +62,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
long lastPosition = stream.Position;
try
{
- int dataEntryAddress = (int)EVORE.ConvertVirtualAddress(rdte.DataEntryOffset, sections);
+ int dataEntryAddress = (int)ConvertVirtualAddress(rdte.DataEntryOffset, sections);
if (dataEntryAddress > 0)
{
stream.Seek(dataEntryAddress, SeekOrigin.Begin);
@@ -93,7 +93,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
{
try
{
- int dataEntryAddress = (int)EVORE.ConvertVirtualAddress(rdte.DataEntryOffset, sections);
+ int dataEntryAddress = (int)ConvertVirtualAddress(rdte.DataEntryOffset, sections);
if (dataEntryAddress > 0)
rdte.DataEntry = ResourceDataEntry.Deserialize(content, dataEntryAddress);
}
@@ -104,5 +104,29 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
return rdte;
}
+
+ ///
+ /// Convert a virtual address to a physical one
+ ///
+ /// Virtual address to convert
+ /// Array of sections to check against
+ /// Physical address, 0 on error
+ private static uint ConvertVirtualAddress(uint virtualAddress, SectionHeader[] sections)
+ {
+ // Loop through all of the sections
+ for (int i = 0; i < sections.Length; i++)
+ {
+ // If the section is invalid, just skip it
+ if (sections[i] == null)
+ continue;
+
+ // Attempt to derive the physical address from the current section
+ var section = sections[i];
+ if (virtualAddress >= section.VirtualAddress && virtualAddress <= section.VirtualAddress + section.VirtualSize)
+ return section.PointerToRawData + virtualAddress - section.VirtualAddress;
+ }
+
+ return 0;
+ }
}
}
\ No newline at end of file
diff --git a/BurnOutSharp/ProtectionType/ProtectDisc.cs b/BurnOutSharp/ProtectionType/ProtectDisc.cs
index 4770c97c..e95c888a 100644
--- a/BurnOutSharp/ProtectionType/ProtectDisc.cs
+++ b/BurnOutSharp/ProtectionType/ProtectDisc.cs
@@ -1,12 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Text;
using BurnOutSharp.ExecutableType.Microsoft;
using BurnOutSharp.Matching;
namespace BurnOutSharp.ProtectionType
{
- // TODO: Investigate the connection between this and VOB Protect CD/DVD
+ // This protection was called VOB ProtectCD / ProtectDVD in versions prior to 6
public class ProtectDISC : IContentCheck
{
///
@@ -40,6 +41,48 @@ namespace BurnOutSharp.ProtectionType
return match;
}
+ // Get the .data section, if it exists
+ var dataSection = sections.FirstOrDefault(s => Encoding.ASCII.GetString(s.Name).StartsWith(".data"));
+ if (dataSection != null)
+ {
+ int sectionAddr = (int)dataSection.PointerToRawData;
+ int sectionEnd = sectionAddr + (int)dataSection.VirtualSize;
+ var matchers = new List
+ {
+ // DCP-BOV + (char)0x00 + (char)0x00
+ new ContentMatchSet(
+ new ContentMatch(new byte?[] { 0x44, 0x43, 0x50, 0x2D, 0x42, 0x4F, 0x56, 0x00, 0x00 }, start: sectionAddr, end: sectionEnd),
+ GetVersion3till6, "VOB ProtectCD/DVD"),
+ };
+
+ string match = MatchUtil.GetFirstMatch(file, fileContent, matchers, includeDebug);
+ if (!string.IsNullOrWhiteSpace(match))
+ return match;
+ }
+
+ // Get the second to last section
+ var secondToLastSection = sections.Length > 1 ? sections[sections.Length - 2] : null;
+ if (secondToLastSection != null)
+ {
+ int sectionAddr = (int)secondToLastSection.PointerToRawData;
+ int sectionEnd = sectionAddr + (int)secondToLastSection.VirtualSize;
+ var matchers = new List
+ {
+ // VOB ProtectCD
+ new ContentMatchSet(
+ new ContentMatch(new byte?[]
+ {
+ 0x56, 0x4F, 0x42, 0x20, 0x50, 0x72, 0x6F, 0x74,
+ 0x65, 0x63, 0x74, 0x43, 0x44
+ }, start: sectionAddr, end: sectionEnd),
+ GetOldVersion, "VOB ProtectCD/DVD"),
+ };
+
+ string match = MatchUtil.GetFirstMatch(file, fileContent, matchers, includeDebug);
+ if (!string.IsNullOrWhiteSpace(match))
+ return match;
+ }
+
// Get the last section (example names: ACE5, akxpxgcv, and piofinqb)
var lastSection = sections.LastOrDefault();
if (lastSection != null)
@@ -52,6 +95,11 @@ namespace BurnOutSharp.ProtectionType
new ContentMatchSet(
new ContentMatch(new byte?[] { 0x48, 0xFA, 0x4D, 0x45, 0x54, 0x49, 0x4E, 0x46 }, start: sectionAddr, end: sectionEnd),
GetVersion76till10, "ProtectDISC"),
+
+ // DCP-BOV + (char)0x00 + (char)0x00
+ new ContentMatchSet(
+ new ContentMatch(new byte?[] { 0x44, 0x43, 0x50, 0x2D, 0x42, 0x4F, 0x56, 0x00, 0x00 }, start: sectionAddr, end: sectionEnd),
+ GetVersion3till6, "VOB ProtectCD/DVD"),
};
string match = MatchUtil.GetFirstMatch(file, fileContent, matchers, includeDebug);
@@ -59,9 +107,39 @@ namespace BurnOutSharp.ProtectionType
return match;
}
+ // Get the .vob.pcd section, if it exists
+ var vobpcdSection = sections.FirstOrDefault(s => Encoding.ASCII.GetString(s.Name).StartsWith(".vob.pcd"));
+ if (vobpcdSection != null)
+ return "VOB ProtectCD";
+
return null;
}
+ public static string GetOldVersion(string file, byte[] fileContent, List positions)
+ {
+ int position = positions[0] + 16; // Begin reading after "VOB ProtectCD"
+ char[] version = new ArraySegment(fileContent, position, 4).Select(b => (char)b).ToArray();
+ if (char.IsNumber(version[0]) && char.IsNumber(version[2]) && char.IsNumber(version[3]))
+ return $"{version[0]}.{version[2]}{version[3]}";
+
+ // Look for the legacy support version
+ position = positions[0] + "VOB ProtectCD with LEGACY SYSIPHOS Support V".Length;
+ version = new ArraySegment(fileContent, position, 7).Select(b => (char)b).ToArray();
+ if (char.IsNumber(version[0]) && char.IsNumber(version[2]) && char.IsNumber(version[4]))
+ return new string(version);
+
+ return "old";
+ }
+
+ public static string GetVersion3till6(string file, byte[] fileContent, List positions)
+ {
+ string version = GetVOBVersion(fileContent, positions[0]);
+ if (version.Length > 0)
+ return version;
+
+ return $"5.9-6.0 {GetVOBBuild(fileContent, positions[0])}";
+ }
+
public static string GetVersion6till8(string file, byte[] fileContent, List positions)
{
string version, strBuild = string.Empty;
@@ -196,5 +274,23 @@ namespace BurnOutSharp.ProtectionType
return string.Empty;
}
+
+ private static string GetVOBBuild(byte[] fileContent, int position)
+ {
+ if (!char.IsNumber((char)fileContent[position - 13]))
+ return string.Empty; //Build info removed
+
+ int build = BitConverter.ToInt16(fileContent, position - 4); // Check if this is supposed to be a 4-byte read
+ return $" (Build {build})";
+ }
+
+ // TODO: Ensure that this version finding works for all known versions
+ private static string GetVOBVersion(byte[] fileContent, int position)
+ {
+ byte version = fileContent[position - 2];
+ byte subVersion = (byte)((fileContent[position - 3] & 0xF0) >> 4);
+ byte subSubVersion = (byte)((fileContent[position - 4] & 0xF0) >> 4);
+ return $"{version}.{subVersion}.{subSubVersion}";
+ }
}
}
diff --git a/BurnOutSharp/ProtectionType/VOBProtectCDDVD.cs b/BurnOutSharp/ProtectionType/VOBProtectCDDVD.cs
deleted file mode 100644
index 2bbd5b08..00000000
--- a/BurnOutSharp/ProtectionType/VOBProtectCDDVD.cs
+++ /dev/null
@@ -1,238 +0,0 @@
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using System.Threading;
-using BurnOutSharp.Matching;
-using BurnOutSharp.Tools;
-
-namespace BurnOutSharp.ProtectionType
-{
- public class VOBProtectCDDVD : IContentCheck, IPathCheck
- {
- ///
- public List GetContentMatchSets()
- {
- return new List
- {
- // VOB ProtectCD
- new ContentMatchSet(new byte?[]
- {
- 0x56, 0x4F, 0x42, 0x20, 0x50, 0x72, 0x6F, 0x74,
- 0x65, 0x63, 0x74, 0x43, 0x44
- }, GetOldVersion, "VOB ProtectCD/DVD"),
-
- // DCP-BOV + (char)0x00 + (char)0x00
- new ContentMatchSet(new byte?[] { 0x44, 0x43, 0x50, 0x2D, 0x42, 0x4F, 0x56, 0x00, 0x00 }, GetVersion, "VOB ProtectCD/DVD"),
-
- // .vob.pcd
- new ContentMatchSet(new byte?[] { 0x2E, 0x76, 0x6F, 0x62, 0x2E, 0x70, 0x63, 0x64 }, "VOB ProtectCD"),
- };
- }
-
- ///
- public string CheckContents(string file, byte[] fileContent, bool includeDebug = false) => null;
-
- ///
- public ConcurrentQueue CheckDirectoryPath(string path, IEnumerable files)
- {
- var matchers = new List
- {
- new PathMatchSet(new PathMatch("VOB-PCD.KEY", useEndsWith: true), "VOB ProtectCD/DVD"),
- };
-
- return MatchUtil.GetAllMatches(files, matchers, any: true);
- }
-
- ///
- public string CheckFilePath(string path)
- {
- var matchers = new List
- {
- new PathMatchSet(new PathMatch("VOB-PCD.KEY", useEndsWith: true), "VOB ProtectCD/DVD"),
- };
-
- return MatchUtil.GetFirstMatch(path, matchers, any: true);
- }
-
- public static string GetOldVersion(string file, byte[] fileContent, List positions)
- {
- int position = positions[0]--; // TODO: Verify this subtract
- char[] version = new ArraySegment(fileContent, position + 16, 4).Select(b => (char)b).ToArray(); // Begin reading after "VOB ProtectCD"
- if (char.IsNumber(version[0]) && char.IsNumber(version[2]) && char.IsNumber(version[3]))
- return $"{version[0]}.{version[2]}{version[3]}";
-
- return "old";
- }
-
- public static string GetVersion(string file, byte[] fileContent, List positions)
- {
- string version = GetVersion(fileContent, --positions[0]); // TODO: Verify this subtract
- if (version.Length > 0)
- return version;
-
- version = SearchProtectDiscVersion(file, fileContent);
- if (version.Length > 0)
- {
- if (version.StartsWith("2"))
- version = $"6{version.Substring(1)}";
-
- return version;
- }
-
- return $"5.9-6.0 {GetBuild(fileContent, positions[0])}";
- }
-
- private static string GetBuild(byte[] fileContent, int position)
- {
- if (!char.IsNumber((char)fileContent[position - 13]))
- return string.Empty; //Build info removed
-
- int build = BitConverter.ToInt16(fileContent, position - 4); // Check if this is supposed to be a 4-byte read
- return $" (Build {build})";
- }
-
- private static string GetVersion(byte[] fileContent, int position)
- {
- if (fileContent[position - 2] == 5)
- {
- int index = position - 4;
- byte subsubVersion = (byte)((fileContent[index] & 0xF0) >> 4);
- index++;
- byte subVersion = (byte)((fileContent[index] & 0xF0) >> 4);
- return $"5.{subVersion}.{subsubVersion}";
- }
-
- return string.Empty;
- }
-
- // TODO: Analyze this method and figure out if this can be done without attempting execution
- private static string SearchProtectDiscVersion(string file, byte[] fileContent)
- {
- // If the file isn't executable, don't even bother
- if (!EVORE.IsPEExecutable(fileContent))
- return string.Empty;
-
- // Get some of the required paths
- string tempexe = EVORE.MakeTempFile(fileContent);
- string[] dependentDlls = EVORE.CopyDependentDlls(file, fileContent);
- string pdPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ProtectDisc");
-
- // Clean up any temp files before attempting to run
- Utilities.SafeTempDelete("a*.tmp");
- Utilities.SafeTempDelete("PCD*.sys");
- if (Directory.Exists(pdPath))
- Utilities.SafeDelete(Path.Combine(pdPath, "p*.dll"));
-
- // Try to safely start the temp executable
- Process exe = EVORE.StartSafe(tempexe);
- if (exe == null)
- return string.Empty;
-
- string version = "";
- Process[] processes = new Process[0];
- DateTime timestart = DateTime.Now;
- do
- {
- exe.Refresh();
- string[] files = null;
-
- // Check for ProtectDisc 8.2-x
- if (Directory.Exists(pdPath))
- files = Directory.GetFiles(pdPath, "p*.dll");
-
- if (files.Any())
- {
- string fileVersion = Utilities.GetFileVersion(files[0]);
- if (!string.IsNullOrWhiteSpace(fileVersion))
- {
- version = fileVersion;
-
- // ProtectDisc 9 uses a ProtectDisc-Core dll version 8.0.x
- if (version.StartsWith("8.0"))
- version = string.Empty;
-
- break;
- }
- }
-
- //check for ProtectDisc 7.1-8.1
- files = Directory.GetFiles(Path.GetTempPath(), "a*.tmp");
- if (files.Any())
- {
- string fileVersion = Utilities.GetFileVersion(files[0]);
- if (!string.IsNullOrWhiteSpace(fileVersion))
- {
- version = fileVersion;
- break;
- }
- }
-
- if (exe.HasExited)
- break;
-
- processes = Process.GetProcessesByName(exe.ProcessName);
- if (processes.Length == 2)
- {
- processes[0].Refresh();
- processes[1].Refresh();
- if (processes[1].WorkingSet64 > exe.WorkingSet64)
- exe = processes[1];
- else if (processes[0].WorkingSet64 > exe.WorkingSet64) //else if (processes[0].Modules.Count > exe.Modules.Count)
- exe = processes[0];
- }
- } while (processes.Length > 0 && DateTime.Now.Subtract(timestart).TotalSeconds < 20);
-
- Thread.Sleep(500);
- if (!exe.HasExited)
- {
- processes = Process.GetProcessesByName(exe.ProcessName);
- if (processes.Length == 2)
- {
- try
- {
- processes[0].Kill();
- }
- catch { }
- processes[0].Close();
- try
- {
- processes[1].Kill();
- }
- catch { }
- }
- else
- {
- exe.Refresh();
- try
- {
- exe.Kill();
- }
- catch { }
- }
- }
-
- exe.Close();
- Thread.Sleep(500);
-
- // Clean up any temp files after running
- Utilities.SafeDelete(tempexe);
- Utilities.SafeTempDelete("a*.tmp");
- Utilities.SafeTempDelete("PCD*.sys");
- if (Directory.Exists(pdPath))
- Utilities.SafeDelete(Path.Combine(pdPath, "p*.dll"));
-
- if (dependentDlls != null)
- {
- foreach (string dll in dependentDlls)
- {
- Utilities.SafeDelete(dll);
- }
- }
-
- return version;
- }
- }
-}
diff --git a/BurnOutSharp/Tools/EVORE.cs b/BurnOutSharp/Tools/EVORE.cs
deleted file mode 100644
index cb021eb3..00000000
--- a/BurnOutSharp/Tools/EVORE.cs
+++ /dev/null
@@ -1,227 +0,0 @@
-//this file is part of BurnOut
-//Copyright (C)2005-2010 Gernot Knippen
-//Ported code with augments Copyright (C)2018 Matt Nadareski
-//
-//This program is free software; you can redistribute it and/or
-//modify it under the terms of the GNU General Public License
-//as published by the Free Software Foundation; either
-//version 2 of the License, or (at your option) any later version.
-//
-//This program is distributed in the hope that it will be useful,
-//but WITHOUT ANY WARRANTY; without even the implied warranty of
-//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-//GNU General Public License for more details.
-//
-//You can get a copy of the GNU General Public License
-//by writing to the Free Software
-//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using BurnOutSharp.ExecutableType.Microsoft;
-using BurnOutSharp.ExecutableType.Microsoft.Headers;
-using BurnOutSharp.ExecutableType.Microsoft.Sections;
-using BurnOutSharp.ExecutableType.Microsoft.Tables;
-
-namespace BurnOutSharp.Tools
-{
- internal static class EVORE
- {
- ///
- /// Convert a virtual address to a physical one
- ///
- /// Virtual address to convert
- /// Array of sections to check against
- /// Physical address, 0 on error
- internal static uint ConvertVirtualAddress(uint virtualAddress, SectionHeader[] sections)
- {
- // Loop through all of the sections
- for (int i = 0; i < sections.Length; i++)
- {
- // If the section is invalid, just skip it
- if (sections[i] == null)
- continue;
-
- // Attempt to derive the physical address from the current section
- var section = sections[i];
- if (virtualAddress >= section.VirtualAddress && virtualAddress <= section.VirtualAddress + section.VirtualSize)
- return section.PointerToRawData + virtualAddress - section.VirtualAddress;
- }
-
- return 0;
- }
-
- ///
- /// Checks if the file contents represent a PE executable
- ///
- /// File contents to check
- /// True if the file is an EXE, false otherwise
- internal static bool IsPEExecutable(byte[] fileContent)
- {
- if (fileContent == null)
- return false;
-
- try
- {
- PortableExecutable pex = PortableExecutable.Deserialize(fileContent, 0);
- return !pex.ImageFileHeader.Characteristics.HasFlag(ImageObjectCharacteristics.IMAGE_FILE_DLL);
- }
- catch
- {
- return false;
- }
- }
-
- ///
- /// Writes the file contents to a temporary file, if possible
- ///
- /// File contents to write
- /// Optional extension for the temporary file, defaults to ".exe"
- /// Name of the new temporary file, null on error
- internal static string MakeTempFile(byte[] fileContent, string extension = ".exe")
- {
- // Ensure the extension is set
- if (string.IsNullOrWhiteSpace(extension))
- extension = ".exe";
- else if (!extension.StartsWith("."))
- extension = $".{extension}";
-
- // Get the temporary path to use
- string tempFileName = Guid.NewGuid().ToString();
- string tempPath = Path.Combine(Path.GetTempPath(), "tmp", $"{tempFileName}{extension}");
-
- // Create and fill the file, if possible
- try
- {
- Directory.CreateDirectory(Path.GetDirectoryName(tempPath));
- using (BinaryWriter bw = new BinaryWriter(File.OpenWrite(tempPath)))
- {
- bw.Write(fileContent);
- }
-
- return Path.GetFullPath(tempPath);
- }
- catch { }
-
- return null;
- }
-
- ///
- /// Copies all required DLLs for a given executable
- ///
- /// Temporary file path
- /// File contents to read
- /// Paths for all of the copied DLLs, null on error
- internal static string[] CopyDependentDlls(string file, byte[] fileContent)
- {
- if (fileContent == null)
- return null;
-
- // Process each of the DLLs that it finds
- try
- {
- unsafe
- {
- // Read all of the executable header information
- PortableExecutable pex = PortableExecutable.Deserialize(fileContent, 0);
-
- // Find the import directory entry
- DataDirectoryHeader idei = pex.OptionalHeader.DataDirectories[(byte)ImageDirectory.IMAGE_DIRECTORY_ENTRY_IMPORT];
-
- // Set the table index and size
- int tableIndex = (int)ConvertVirtualAddress(idei.VirtualAddress, pex.SectionTable);
- int tableSize = (int)idei.Size;
- if (tableIndex <= 0 || tableSize <= 0)
- return null;
-
- // Load the table from index
- ImportDataSection idata = ImportDataSection.Deserialize(fileContent, tableIndex, pex.OptionalHeader.Magic == OptionalHeaderType.PE32Plus, hintCount: 0);
- ImportDirectoryTable idt = idata.ImportDirectoryTable;
-
- // TODO: Use the known layout to determine the names in a more automated way instead of having to iterate
-
- // Retrieve the table data
- byte[] tableData = new byte[tableSize];
- Array.Copy(fileContent, tableIndex, tableData, 0, tableSize);
- int entryCount = tableSize / 4; // Each entry is a UInt32
-
- // TODO: Validate what this table actually looks like.
- // My concern about this is that it seems like each entry might be 16 bytes?
- // The original code does a += 12, reads the address, and then moves on.
- // That being said, the way that this works _does_ come up with a valid table,
- // at least something that looks like a valid table, since it shows up with
- // `ntoskrnl.exe` on the dot
- //
- // Unfortunately, for other programs, this comes up with nonsense data, so it's hard
- // to tell if the table is accurate or not.
-
- // Iterate through the table and get valid DLL names
- List dependentDlls = new List();
- for (int i = 0; i < entryCount; i++)
- {
- // Get and validate the virtual offset
- uint entryVirtualOffset = BitConverter.ToUInt32(tableData, i * 4);
- if (entryVirtualOffset == 0)
- continue;
-
- // Get the DLL name from the table and add it to the list if possible
- string entryDllName = new string(fileContent.Skip((int)entryVirtualOffset).TakeWhile(b => b > 0).Select(b => (char)b).ToArray());
-
- try
- {
- if (File.Exists(Path.Combine(Path.GetDirectoryName(file), entryDllName)))
- {
- FileInfo fiDLL = new FileInfo(Path.Combine(Path.GetDirectoryName(file), entryDllName));
- dependentDlls.Add(fiDLL.CopyTo(Path.Combine(Path.GetTempPath(), entryDllName), true).FullName);
- }
- }
- catch { }
- }
-
- return dependentDlls.ToArray();
- }
- }
- catch
- {
- return null;
- }
- }
-
- ///
- /// Attempt to run an executable
- ///
- /// Executable to attempt to run
- /// Process representing the running executable, null on error
- internal static Process StartSafe(string file)
- {
- if (file == null || !File.Exists(file))
- return null;
-
- // Create the process to start safely
- Process safeProcess = new Process
- {
- StartInfo = new ProcessStartInfo
- {
- FileName = file,
- WindowStyle = ProcessWindowStyle.Hidden,
- CreateNoWindow = true,
- ErrorDialog = false,
- }
- };
-
- // Try to start the process, returning the handle if we can
- try
- {
- safeProcess.Start();
- return safeProcess;
- }
- catch
- {
- return null;
- }
- }
- }
-}
diff --git a/BurnOutSharp/Tools/Utilities.cs b/BurnOutSharp/Tools/Utilities.cs
index 548e5f91..469d1acd 100644
--- a/BurnOutSharp/Tools/Utilities.cs
+++ b/BurnOutSharp/Tools/Utilities.cs
@@ -424,41 +424,5 @@ namespace BurnOutSharp.Tools
}
#endregion
-
- #region IO Helpers
-
- ///
- /// Safely attempt to delete a path
- ///
- /// Path to be deleted
- /// True to treat the path as a directory, false for a file
- public static void SafeDelete(string path, bool isDirectory = false)
- {
- // No valid path means we can't delete
- if (string.IsNullOrWhiteSpace(path))
- return;
-
- // Attempt to delete the path
- try
- {
- if (!isDirectory && File.Exists(path))
- File.Delete(path);
- else if (isDirectory && Directory.Exists(path))
- Directory.Delete(path, true);
- }
- catch
- {
- // Absorb any errors in deletion
- }
- }
-
- ///
- /// Safely attempt to delete a path in the temp directory
- ///
- /// Path in the temp directory to be deleted
- /// True to treat the path as a directory, false for a file
- public static void SafeTempDelete(string path, bool isDirectory = false) => SafeDelete(Path.Combine(Path.GetTempPath(), path), isDirectory);
-
- #endregion
}
}