diff --git a/Assets/Scripts/ViewModels/NativeMethods.cs b/Assets/Scripts/ViewModels/NativeMethods.cs new file mode 100644 index 0000000..5bf2ce4 --- /dev/null +++ b/Assets/Scripts/ViewModels/NativeMethods.cs @@ -0,0 +1,86 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; + +namespace StlVault.ViewModels +{ + [SuppressMessage("ReSharper", "FieldCanBeMadeReadOnly.Local")] + [SuppressMessage("ReSharper", "BuiltInTypeReferenceStyle")] + [SuppressMessage("ReSharper", "MemberCanBePrivate.Local")] + [SuppressMessage("ReSharper", "InconsistentNaming")] + [SuppressMessage("ReSharper", "IdentifierTypo")] + internal static class NativeMethods + { + public static void BrowseTo(string filePath) + { + const uint normalPriorityClass = 0x0020; + + var application = Environment.GetEnvironmentVariable("windir") + @"\explorer.exe"; + var commandLine = $"/e, /select, \"{filePath}\""; + var sInfo = new STARTUPINFO(); + var pSec = new SECURITY_ATTRIBUTES(); + var tSec = new SECURITY_ATTRIBUTES(); + pSec.nLength = Marshal.SizeOf(pSec); + tSec.nLength = Marshal.SizeOf(tSec); + + //Open Explorer at location + CreateProcess(application, commandLine, + ref pSec, ref tSec, false, normalPriorityClass, + IntPtr.Zero, null, ref sInfo, out _); + } + + [DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)] + static extern bool CreateProcess( + string lpApplicationName, + string lpCommandLine, + ref SECURITY_ATTRIBUTES lpProcessAttributes, + ref SECURITY_ATTRIBUTES lpThreadAttributes, + bool bInheritHandles, + uint dwCreationFlags, + IntPtr lpEnvironment, + string lpCurrentDirectory, + [In] ref STARTUPINFO lpStartupInfo, + out PROCESS_INFORMATION lpProcessInformation); + + // This also works with CharSet.Ansi as long as the calling function uses the same character set. + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + private struct STARTUPINFO + { + public Int32 cb; + public string lpReserved; + public string lpDesktop; + public string lpTitle; + public Int32 dwX; + public Int32 dwY; + public Int32 dwXSize; + public Int32 dwYSize; + public Int32 dwXCountChars; + public Int32 dwYCountChars; + public Int32 dwFillAttribute; + public Int32 dwFlags; + public Int16 wShowWindow; + public Int16 cbReserved2; + public IntPtr lpReserved2; + public IntPtr hStdInput; + public IntPtr hStdOutput; + public IntPtr hStdError; + } + + [StructLayout(LayoutKind.Sequential)] + private struct PROCESS_INFORMATION + { + public IntPtr hProcess; + public IntPtr hThread; + public int dwProcessId; + public int dwThreadId; + } + + [StructLayout(LayoutKind.Sequential)] + private struct SECURITY_ATTRIBUTES + { + public int nLength; + public unsafe byte* lpSecurityDescriptor; + public int bInheritHandle; + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/ViewModels/NativeMethods.cs.meta b/Assets/Scripts/ViewModels/NativeMethods.cs.meta new file mode 100644 index 0000000..51e2c8b --- /dev/null +++ b/Assets/Scripts/ViewModels/NativeMethods.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a6efff53ae1b49878c63966565d52303 +timeCreated: 1586500630 \ No newline at end of file diff --git a/Assets/Scripts/ViewModels/UserFeedbackModel.cs b/Assets/Scripts/ViewModels/UserFeedbackModel.cs index 145773e..b32ffc0 100644 --- a/Assets/Scripts/ViewModels/UserFeedbackModel.cs +++ b/Assets/Scripts/ViewModels/UserFeedbackModel.cs @@ -81,19 +81,29 @@ private void CreateArchive() private static void ShowInExplorer(string zipPath) { - Process.Start(new ProcessStartInfo - { - FileName = "explorer", - Arguments = $"/e, /select, \"{zipPath}\"" - }); + NativeMethods.BrowseTo(zipPath); } private static void Add(ZipArchive archive, string folder, string fileName) { - var filePath = Path.Combine(folder, fileName); - if (!File.Exists(filePath)) return; + var sourceFilePath = Path.Combine(folder, fileName); + if (!File.Exists(sourceFilePath)) return; - archive.CreateEntryFromFile(filePath, fileName); + using (var stream = File.Open(sourceFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + { + var zipArchiveEntry = archive.CreateEntry(fileName); + var dateTime = File.GetLastWriteTime(sourceFilePath); + if (dateTime.Year < 1980 || dateTime.Year > 2107) + { + dateTime = new DateTime(1980, 1, 1, 0, 0, 0); + } + + zipArchiveEntry.LastWriteTime = dateTime; + using (var targetStream = zipArchiveEntry.Open()) + { + stream.CopyTo(targetStream); + } + } } protected override void OnAccept()