using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
namespace EverythingLikeApp
{
public partial class MainForm : Form
{
// Everything API 常量
private const int EVERYTHING_OK = 0;
private const int EVERYTHING_ERROR_MEMORY = 1;
private const int EVERYTHING_ERROR_IPC = 2;
private const int EVERYTHING_ERROR_REGISTERCLASSEX = 3;
private const int EVERYTHING_ERROR_CREATEWINDOW = 4;
private const int EVERYTHING_ERROR_QUERY = 5;
// Everything API 导入
[DllImport(@"C:\Program Files\Everything\Everything64.dll", CharSet = CharSet.Unicode)]
private static extern int Everything_SetSearch(string lpSearchString);
[DllImport(@"C:\Program Files\Everything\Everything64.dll")]
private static extern bool Everything_Query(bool bWait);
[DllImport(@"C:\Program Files\Everything\Everything64.dll")]
private static extern int Everything_GetNumResults();
[DllImport(@"C:\Program Files\Everything\Everything64.dll", CharSet = CharSet.Unicode)]
private static extern void Everything_GetResultFullPathName(int nIndex, StringBuilder lpString, int nMaxCount);
[DllImport(@"C:\Program Files\Everything\Everything64.dll")]
private static extern int Everything_GetLastError();
[DllImport(@"C:\Program Files\Everything\Everything64.dll", CharSet = CharSet.Unicode)]
public static extern void Everything_GetResultFullPathNameW(int nIndex, StringBuilder lpString, int nMaxCount);
private ContextMenuStrip listViewContextMenu;
// 添加缓存机制
private ConcurrentDictionary<string, ListViewItem[]> searchCache = new ConcurrentDictionary<string, ListViewItem[]>();
private CancellationTokenSource searchTokenSource;
// 在类成员变量区域添加
private const int BUFFER_SIZE = 260; // Windows MAX_PATH 标准值
public MainForm()
{
InitializeComponent();
InitializeContextMenu();
SetupListView();
CheckEverythingService();
}
private void InitializeContextMenu()
{
listViewContextMenu = new ContextMenuStrip();
// 添加菜单项
var openItem = new ToolStripMenuItem("打开");
openItem.Click += (s, e) => OpenSelectedItem();
var renameItem = new ToolStripMenuItem("重命名");
renameItem.Click += (s, e) => RenameSelectedItem();
var openPathItem = new ToolStripMenuItem("打开所在文件夹");
openPathItem.Click += (s, e) => OpenContainingFolder();
var copyPathItem = new ToolStripMenuItem("复制路径");
copyPathItem.Click += (s, e) => CopyItemPath();
var propertiesItem = new ToolStripMenuItem("属性");
propertiesItem.Click += (s, e) => ShowProperties();
listViewContextMenu.Items.AddRange(new ToolStripItem[] {
openItem, renameItem, openPathItem,
new ToolStripSeparator(),
copyPathItem,
new ToolStripSeparator(),
propertiesItem
});
}
private void SetupListView()
{
listView1.View = View.Details;
listView1.FullRowSelect = true;
listView1.Columns.Add("名称", 300);
listView1.Columns.Add("路径", 500);
listView1.Columns.Add("大小", 100);
listView1.Columns.Add("修改日期", 150);
listView1.MouseDoubleClick += (s, e) => OpenSelectedItem();
listView1.KeyDown += (s, e) =>
{
if (e.KeyCode == Keys.Enter) OpenSelectedItem();
};
listView1.ContextMenuStrip = listViewContextMenu;
}
private void CheckEverythingService()
{
try
{
if (Everything_GetLastError() != EVERYTHING_OK)
{
MessageBox.Show("Everything服务未运行,请先启动Everything", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
catch (DllNotFoundException)
{
MessageBox.Show("找不到Everything64.dll,请确保Everything已安装", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
// 修改后的并行搜索代码
private async void SearchButton_Click(object sender, EventArgs e)
{
string searchText = searchTextBox.Text.Trim();
if (string.IsNullOrEmpty(searchText)) return;
searchTokenSource?.Cancel();
searchTokenSource = new CancellationTokenSource();
var token = searchTokenSource.Token;
// 显示加载状态
UpdateStatus("搜索中...");
try
{
var results = await Task.Run(() =>
{
token.ThrowIfCancellationRequested();
// 设置搜索参数
Everything_SetSearch(searchText);
if (!Everything_Query(true)) return Array.Empty<ListViewItem>();
int resultCount = Everything_GetNumResults();
var items = new ListViewItem[resultCount];
// 使用线程安全的并行处理
Parallel.For(0, resultCount, i =>
{
token.ThrowIfCancellationRequested();
// 每个线程使用独立的StringBuilder
var localBuilder = new StringBuilder(BUFFER_SIZE);
Everything_GetResultFullPathName(i, localBuilder, localBuilder.Capacity);
string fullPath = localBuilder.ToString();
items[i] = CreateListViewItem(fullPath);
});
return items;
}, token);
if (!token.IsCancellationRequested)
{
DisplayResults(results);
}
}
catch (OperationCanceledException)
{
UpdateStatus("搜索已取消");
}
catch (Exception ex)
{
MessageBox.Show($"搜索出错: {ex.Message}", "错误");
}
}
// 创建ListViewItem的辅助方法
private ListViewItem CreateListViewItem(string fullPath)
{
var item = new ListViewItem(Path.GetFileName(fullPath));
item.SubItems.Add(fullPath);
try
{
var fileInfo = new FileInfo(fullPath);
item.SubItems.Add(FormatSize(fileInfo.Length));
item.SubItems.Add(fileInfo.LastWriteTime.ToString("yyyy-MM-dd HH:mm"));
item.Tag = fullPath;
}
catch
{
item.SubItems.Add("");
item.SubItems.Add("");
}
return item;
}
// 状态更新方法
private void UpdateStatus(string message)
{
if (InvokeRequired)
{
Invoke(new Action(() => UpdateStatus(message)));
return;
}
toolStripStatusLabel1.Text = message;
}
// 优化后的文件大小格式化
private string FormatSize(long bytes)
{
if (bytes < 1024) return $"{bytes} B";
if (bytes < 1048576) return $"{bytes / 1024f:0.##} KB";
if (bytes < 1073741824) return $"{bytes / 1048576f:0.##} MB";
return $"{bytes / 1073741824f:0.##} GB";
}
// 高效显示结果的方法
private void DisplayResults(ListViewItem[] items)
{
if (this.InvokeRequired)
{
this.Invoke(new Action(() => DisplayResults(items)));
return;
}
listView1.BeginUpdate();
try
{
listView1.Items.Clear();
// 使用AddRange批量添加(比逐个添加快10倍以上)
if (items.Length > 0)
{
listView1.Items.AddRange(items);
// 自动调整列宽
foreach (ColumnHeader column in listView1.Columns)
{
column.Width = -2; // -2表示根据内容自动调整
}
}
else
{
listView1.Items.Add("没有找到匹配结果").ForeColor = Color.Gray;
}
}
finally
{
listView1.EndUpdate();
}
}
private void OpenSelectedItem()
{
if (listView1.SelectedItems.Count == 0) return;
string path = listView1.SelectedItems[0].Tag as string;
if (string.IsNullOrEmpty(path)) return;
try
{
Process.Start(new ProcessStartInfo
{
FileName = path,
UseShellExecute = true
});
}
catch (Exception ex)
{
MessageBox.Show($"无法打开文件: {ex.Message}", "错误");
}
}
private void RenameSelectedItem()
{
if (listView1.SelectedItems.Count == 0) return;
string oldPath = listView1.SelectedItems[0].Tag as string;
if (string.IsNullOrEmpty(oldPath)) return;
string newName = Microsoft.VisualBasic.Interaction.InputBox(
"输入新文件名:", "重命名", Path.GetFileName(oldPath));
if (!string.IsNullOrEmpty(newName))
{
try
{
string newPath = Path.Combine(Path.GetDirectoryName(oldPath), newName);
File.Move(oldPath, newPath);
SearchButton_Click(null, null); // 刷新搜索
}
catch (Exception ex)
{
MessageBox.Show($"重命名失败: {ex.Message}", "错误");
}
}
}
private void OpenContainingFolder()
{
if (listView1.SelectedItems.Count == 0) return;
string path = listView1.SelectedItems[0].Tag as string;
if (string.IsNullOrEmpty(path)) return;
try
{
Process.Start("explorer.exe", $"/select,\"{path}\"");
}
catch (Exception ex)
{
MessageBox.Show($"无法打开所在文件夹: {ex.Message}", "错误");
}
}
private void CopyItemPath()
{
if (listView1.SelectedItems.Count == 0) return;
string path = listView1.SelectedItems[0].Tag as string;
if (!string.IsNullOrEmpty(path))
{
Clipboard.SetText(path);
}
}
private void ShowProperties()
{
if (listView1.SelectedItems.Count == 0) return;
string path = listView1.SelectedItems[0].Tag as string;
if (string.IsNullOrEmpty(path)) return;
try
{
var psi = new ProcessStartInfo
{
FileName = "explorer.exe",
Arguments = $"/e,/root,\"{path}\"",
Verb = "properties"
};
Process.Start(psi);
}
catch (Exception ex)
{
MessageBox.Show($"无法显示属性: {ex.Message}", "错误");
}
}
private void SearchButton_Click_1(object sender, EventArgs e)
{
string searchText = searchTextBox.Text.Trim();
if (string.IsNullOrEmpty(searchText)) return;
listView1.Items.Clear();
Everything_SetSearch(searchText);
if (!Everything_Query(true))
{
MessageBox.Show($"搜索失败,错误代码: {Everything_GetLastError()}", "错误");
return;
}
int resultCount = Everything_GetNumResults();
StringBuilder pathBuilder = new StringBuilder(260);
for (int i = 0; i < resultCount; i++)
{
Everything_GetResultFullPathName(i, pathBuilder, pathBuilder.Capacity);
string fullPath = pathBuilder.ToString();
var item = new ListViewItem(Path.GetFileName(fullPath));
item.SubItems.Add(fullPath);
try
{
var fileInfo = new FileInfo(fullPath);
item.SubItems.Add(fileInfo.Length.ToString("N0"));
item.SubItems.Add(fileInfo.LastWriteTime.ToString());
item.Tag = fullPath; // 存储完整路径
}
catch
{
item.SubItems.Add("");
item.SubItems.Add("");
}
listView1.Items.Add(item);
}
}
}
}