Skip to content

added truncate file option to context menu - .net 8 #334

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions src/LogExpert.UI/Controls/LogWindow/LogWindowPublic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using LogExpert.Core.EventArguments;
using LogExpert.Dialogs;
using LogExpert.UI.Entities;
using LogExpert.UI.Extensions;

namespace LogExpert.UI.Controls.LogWindow;

Expand Down Expand Up @@ -581,6 +582,28 @@ public void FollowTailChanged (bool isChecked, bool byTrigger)
SendGuiStateUpdate();
}

public void TryToTruncate ()
{
try
{
if (LockFinder.CheckIfFileIsLocked(Title))
{
var name = LockFinder.FindLockedProcessName(Title);
StatusLineText($"Truncate failed: file is locked by {name}");
}
else
{
File.WriteAllText(Title, "");
}
}
catch (Exception ex)
{
_logger.Warn($"Unexpected issue truncating file: {ex.Message}");
StatusLineText("Unexpected issue truncating file");
throw;
}
}

public void GotoLine (int line)
{
if (line >= 0)
Expand Down
2 changes: 1 addition & 1 deletion src/LogExpert.UI/Controls/LogWindow/TimeSpreadigControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ internal partial class TimeSpreadingControl : UserControl

private Bitmap _bitmap = new(1, 1);
private int _displayHeight = 1;
private readonly int _edgeOffset = (int)Win32.GetSystemMetricsForDpi(Win32.SM_CYVSCROLL);
private readonly int _edgeOffset = (int)NativeMethods.GetSystemMetricsForDpi(NativeMethods.SM_CYVSCROLL);
private int _lastMouseY;
private readonly object _monitor = new();
private int _rectHeight = 1;
Expand Down
4 changes: 2 additions & 2 deletions src/LogExpert.UI/Dialogs/ChooseIconDlg.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using LogExpert.UI.Extensions;
using LogExpert.UI.Extensions;
using System.Runtime.Versioning;

namespace LogExpert.UI.Dialogs;
Expand Down Expand Up @@ -38,7 +38,7 @@ private void FillIconList()
{
iconListView.Items.Clear();

Icon[,] icons = Win32.ExtractIcons(FileName);
Icon[,] icons = NativeMethods.ExtractIcons(FileName);

if (icons == null)
{
Expand Down
2 changes: 1 addition & 1 deletion src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ public LogTabWindow (string[] fileNames, int instanceNumber, bool showInstanceNu
public void ChangeTheme (Control.ControlCollection container)
{
ColorMode.LoadColorMode(ConfigManager.Settings.Preferences.DarkMode);
Win32.UseImmersiveDarkMode(Handle, ColorMode.DarkModeEnabled);
NativeMethods.UseImmersiveDarkMode(Handle, ColorMode.DarkModeEnabled);

#region ApplyColorToAllControls
foreach (Control component in container)
Expand Down
12 changes: 11 additions & 1 deletion src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindow.designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -847,7 +847,11 @@ private void OnFindInExplorerToolStripMenuItemClick (object sender, EventArgs e)
explorer.Start();
}

[SupportedOSPlatform("windows")]
private void TruncateFileToolStripMenuItem_Click (object sender, EventArgs e)
{
CurrentLogWindow?.TryToTruncate();
}

private void OnExportBookmarksToolStripMenuItemClick (object sender, EventArgs e)
{
CurrentLogWindow?.ExportBookmarkList();
Expand Down
6 changes: 3 additions & 3 deletions src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindowPrivate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -774,7 +774,7 @@ private Icon CreateLedIcon (int level, bool dirty, int tailState, int syncMode)
// a managed copy of icon. then the unmanaged win32 handle is destroyed
var iconHandle = bmp.GetHicon();
var icon = Icon.FromHandle(iconHandle).Clone() as Icon;
Win32.DestroyIcon(iconHandle);
NativeMethods.DestroyIcon(iconHandle);

gfx.Dispose();
bmp.Dispose();
Expand Down Expand Up @@ -1033,7 +1033,7 @@ private void SetTabIcons (Preferences preferences)
[SupportedOSPlatform("windows")]
private void SetToolIcon (ToolEntry entry, ToolStripItem item)
{
Icon icon = Win32.LoadIconFromExe(entry.IconFile, entry.IconIndex);
Icon icon = NativeMethods.LoadIconFromExe(entry.IconFile, entry.IconIndex);
if (icon != null)
{
item.Image = icon.ToBitmap();
Expand All @@ -1046,7 +1046,7 @@ private void SetToolIcon (ToolEntry entry, ToolStripItem item)
item.DisplayStyle = ToolStripItemDisplayStyle.Image;
}

Win32.DestroyIcon(icon.Handle);
NativeMethods.DestroyIcon(icon.Handle);
icon.Dispose();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ public void SelectTab (ILogWindow logWindow)
[SupportedOSPlatform("windows")]
public void SetForeground ()
{
Win32.SetForegroundWindow(Handle);
NativeMethods.SetForegroundWindow(Handle);
if (WindowState == FormWindowState.Minimized)
{
if (_wasMaximized)
Expand Down
4 changes: 2 additions & 2 deletions src/LogExpert.UI/Dialogs/LogTabWindow/SettingsDialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -558,12 +558,12 @@ private void DisplayCurrentIcon ()
{
if (_selectedTool != null)
{
Icon icon = Win32.LoadIconFromExe(_selectedTool.IconFile, _selectedTool.IconIndex);
Icon icon = NativeMethods.LoadIconFromExe(_selectedTool.IconFile, _selectedTool.IconIndex);
if (icon != null)
{
Image image = icon.ToBitmap();
buttonIcon.Image = image;
Win32.DestroyIcon(icon.Handle);
NativeMethods.DestroyIcon(icon.Handle);
icon.Dispose();
}
else
Expand Down
129 changes: 129 additions & 0 deletions src/LogExpert.UI/Extensions/LockFinder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;

// Expanded with some helpers from: https://code.msdn.microsoft.com/windowsapps/How-to-know-the-process-704839f4/
// Uses Windows Restart Manager.
// A more involved and cross platform solution to this problem is here: https://github.com/cklutz/LockCheck


namespace LogExpert.UI.Extensions;

internal class LockFinder
{

/// <summary>
/// Method <c>FindLockedProcessName</c> Retrieve the first process name
/// that is locking the file at the specified path
/// </summary>
/// <param name="path">The path of a file with a write lock held by a
/// process</param>
/// <resturns>The name of the first process found with a lock</resturns>
/// <exception cref="Exception">
/// Thrown when the file path is not locked
/// </exception>
static public string FindLockedProcessName (string path)
{
var list = FindLockProcesses(path);
if (list.Count == 0)
{
throw new Exception(
"No processes are locking the path specified");
}
return list[0].ProcessName;
}

/// <summary>
/// Method <c>CheckIfFileIsLocked</c> Check if the file specified has a
/// write lock held by a process
/// </summary>
/// <param name="path">The path of a file being checked if a write lock
/// held by a process</param>
/// <returns>true when one or more processes with lock</returns>
static public bool CheckIfFileIsLocked (string path)
{
var list = FindLockProcesses(path);
if (list.Count > 0)
{ return true; }
return false;
}

/// <summary>
/// Used to find processes holding a lock on the file. This would cause
/// other usage, such as file truncation or write opretions to throw
/// IOException if an exclusive lock is attempted.
/// </summary>
/// <param name="path">Path being checked</param>
/// <returns>List of processes holding file lock to path</returns>
/// <exception cref="Exception"></exception>
static public List<Process> FindLockProcesses (string path)
{
var key = Guid.NewGuid().ToString();
var processes = new List<Process>();

var res = NativeMethods.RmStartSession(out var handle, 0, key);
if (res != 0)
{
throw new Exception("Could not begin restart session. " +
"Unable to determine file locker.");
}

try
{
uint pnProcInfo = 0;
uint lpdwRebootReasons = NativeMethods.RmRebootReasonNone;
string[] resources = [path];

res = NativeMethods.RmRegisterResources(handle, (uint)resources.Length,
resources, 0, null, 0, null);
if (res != 0)
{
throw new Exception("Could not register resource.");
}
res = NativeMethods.RmGetList(handle, out var pnProcInfoNeeded, ref pnProcInfo, null,
ref lpdwRebootReasons);
const int ERROR_MORE_DATA = 234;
if (res == ERROR_MORE_DATA)
{
var processInfo =
new NativeMethods.RM_PROCESS_INFO[pnProcInfoNeeded];
pnProcInfo = pnProcInfoNeeded;
// Get the list.
res = NativeMethods.RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, processInfo, ref lpdwRebootReasons);
if (res == 0)
{
processes = new List<Process>((int)pnProcInfo);
for (var i = 0; i < pnProcInfo; i++)
{
try
{
processes.Add(Process.GetProcessById(processInfo[i].
Process.dwProcessId));
}
catch (ArgumentException) { }
}
}
else
{
throw new Exception("Could not list processes locking resource");
}
}
else if (res != 0)
{
throw new Exception("Could not list processes locking resource." +
"Failed to get size of result.");
}
}
catch (Exception exception)
{
Trace.WriteLine(exception.Message);
}
finally
{
Trace.WriteLine($"RmEndSession: {NativeMethods.RmEndSession(handle)}");
}

return processes;
}
}
Loading
Loading