From c8c82e1a43991f1258878a1224f48142c2738fce Mon Sep 17 00:00:00 2001 From: Haerbin23456 <60066765+Haerbin23456@users.noreply.github.com> Date: Thu, 5 Mar 2026 16:20:17 +0800 Subject: [PATCH 1/2] chore: unify build setup and clean warnings --- .github/workflows/build.yml | 4 +- .gitignore | 8 +-- .vscode/launch.json | 21 ++++++ .vscode/settings.json | 9 +++ .vscode/tasks.json | 49 ++++++++++++++ BenchmarkSuite1/BenchmarkSuite1.csproj | 16 ----- BenchmarkSuite1/PackageScannerBenchmark.cs | 15 ----- BenchmarkSuite1/Program.cs | 12 ---- .../Converters/IconToImageConverter.cs | 13 ++-- .../Core/ExtensionManager.cs | 11 ++- .../Core/Helpers/SmoothScrollingHelper.cs | 7 +- ContextMenuProfiler.UI/Core/PackageScanner.cs | 27 ++++---- .../Core/RegistryScanner.cs | 8 +-- .../Core/Services/LogService.cs | 2 +- ContextMenuProfiler.UI/MainWindow.xaml.cs | 2 +- .../ViewModels/DashboardViewModel.cs | 6 +- ContextMenuProfiler.sln | 14 ---- scripts/build_hook.bat | 67 +++++++++++++------ scripts/redeploy.bat | 11 +++ 19 files changed, 184 insertions(+), 118 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 .vscode/tasks.json delete mode 100644 BenchmarkSuite1/BenchmarkSuite1.csproj delete mode 100644 BenchmarkSuite1/PackageScannerBenchmark.cs delete mode 100644 BenchmarkSuite1/Program.cs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4688591..e5c094a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,8 +22,8 @@ jobs: with: dotnet-version: 8.0.x - - name: Build WPF UI - run: dotnet build ContextMenuProfiler.UI\ContextMenuProfiler.UI.csproj -c Release + - name: Build Solution + run: dotnet build ContextMenuProfiler.sln -c Release - name: Upload Build Artifacts uses: actions/upload-artifact@v4 diff --git a/.gitignore b/.gitignore index e184b8f..ed864d2 100644 --- a/.gitignore +++ b/.gitignore @@ -16,10 +16,10 @@ crash_log.txt *.ilk # VS Code -.vscode/ -! .vscode/launch.json -! .vscode/tasks.json -! .vscode/settings.json +.vscode/* +!.vscode/launch.json +!.vscode/tasks.json +!.vscode/settings.json .trae/ # .NET / C# diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..0b36e72 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,21 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "ContextMenuProfiler.UI", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceFolder}/ContextMenuProfiler.UI/bin/Debug/net8.0-windows10.0.19041.0/ContextMenuProfiler.UI.dll", + "args": [], + "cwd": "${workspaceFolder}/ContextMenuProfiler.UI", + "console": "internalConsole", + "stopAtEntry": false + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach" + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..d7cad5e --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "dotnet.defaultSolution": "ContextMenuProfiler.sln", + "files.watcherExclude": { + "**/wpfui-repo/**": true, + "**/ContextMenuManager-repo/**": true + }, + "omnisharp.path": "latest", + "omnisharp.useModernNet": true +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..95984c3 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,49 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/ContextMenuProfiler.sln", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary;ForceNoAlign" + ], + "problemMatcher": "$msCompile", + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/ContextMenuProfiler.UI/ContextMenuProfiler.UI.csproj", + "-c", + "Release", + "-r", + "win-x64", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary;ForceNoAlign" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "--project", + "${workspaceFolder}/ContextMenuProfiler.UI/ContextMenuProfiler.UI.csproj" + ], + "problemMatcher": "$msCompile" + } + ] +} diff --git a/BenchmarkSuite1/BenchmarkSuite1.csproj b/BenchmarkSuite1/BenchmarkSuite1.csproj deleted file mode 100644 index 46e05c2..0000000 --- a/BenchmarkSuite1/BenchmarkSuite1.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - - net8.0-windows10.0.19041.0 - Exe - - - - - - - - - - - diff --git a/BenchmarkSuite1/PackageScannerBenchmark.cs b/BenchmarkSuite1/PackageScannerBenchmark.cs deleted file mode 100644 index 909ded4..0000000 --- a/BenchmarkSuite1/PackageScannerBenchmark.cs +++ /dev/null @@ -1,15 +0,0 @@ -using BenchmarkDotNet.Attributes; -using ContextMenuProfiler.UI.Core; -using System.Collections.Generic; -using System.Linq; -using Microsoft.VSDiagnostics; - -[CPUUsageDiagnoser] -public class PackageScannerBenchmark -{ - [Benchmark] - public List ScanPackagedExtensions() - { - return PackageScanner.ScanPackagedExtensions(null).ToList(); - } -} \ No newline at end of file diff --git a/BenchmarkSuite1/Program.cs b/BenchmarkSuite1/Program.cs deleted file mode 100644 index 68e2fdd..0000000 --- a/BenchmarkSuite1/Program.cs +++ /dev/null @@ -1,12 +0,0 @@ -using BenchmarkDotNet.Running; - -namespace BenchmarkSuite1 -{ - internal class Program - { - static void Main(string[] args) - { - var _ = BenchmarkRunner.Run(typeof(Program).Assembly); - } - } -} diff --git a/ContextMenuProfiler.UI/Converters/IconToImageConverter.cs b/ContextMenuProfiler.UI/Converters/IconToImageConverter.cs index afb1445..202260d 100644 --- a/ContextMenuProfiler.UI/Converters/IconToImageConverter.cs +++ b/ContextMenuProfiler.UI/Converters/IconToImageConverter.cs @@ -88,7 +88,7 @@ public object Convert(object value, Type targetType, object parameter, CultureIn { string? path = value as string; - if (string.IsNullOrEmpty(path) || path == "NONE") return null; + if (string.IsNullOrEmpty(path) || path == "NONE") return DependencyProperty.UnsetValue; if (_iconCache.TryGetValue(path, out var cached)) return cached; @@ -102,9 +102,9 @@ public object Convert(object value, Type targetType, object parameter, CultureIn { _iconCache.TryAdd(path, result); } - return result; + return result ?? DependencyProperty.UnsetValue; } - catch { return null; } + catch { return DependencyProperty.UnsetValue; } } private ImageSource? InnerConvert(string path) @@ -114,8 +114,9 @@ public object Convert(object value, Type targetType, object parameter, CultureIn // Handle ms-appx:// URIs (UWP resources) if (path.StartsWith("ms-appx://")) { - path = ResolveMsAppxUri(path); - if (string.IsNullOrEmpty(path)) return null; + var resolvedPath = ResolveMsAppxUri(path); + if (string.IsNullOrEmpty(resolvedPath)) return null; + path = resolvedPath; } // Expand environment variables @@ -224,4 +225,4 @@ public object ConvertBack(object value, Type targetType, object parameter, Cultu [DllImport("user32.dll", EntryPoint = "DestroyIcon", SetLastError = true)] private static extern int DestroyIcon(IntPtr hIcon); } -} \ No newline at end of file +} diff --git a/ContextMenuProfiler.UI/Core/ExtensionManager.cs b/ContextMenuProfiler.UI/Core/ExtensionManager.cs index eed5c37..79954f0 100644 --- a/ContextMenuProfiler.UI/Core/ExtensionManager.cs +++ b/ContextMenuProfiler.UI/Core/ExtensionManager.cs @@ -160,7 +160,11 @@ private static void CopyRegistryKey(RegistryKey source, RegistryKey dest) // Copy values foreach (var valueName in source.GetValueNames()) { - dest.SetValue(valueName, source.GetValue(valueName), source.GetValueKind(valueName)); + var value = source.GetValue(valueName); + if (value != null) + { + dest.SetValue(valueName, value, source.GetValueKind(valueName)); + } } // Copy subkeys @@ -169,7 +173,10 @@ private static void CopyRegistryKey(RegistryKey source, RegistryKey dest) using (var srcSub = source.OpenSubKey(subKeyName)) using (var destSub = dest.CreateSubKey(subKeyName)) { - CopyRegistryKey(srcSub, destSub); + if (srcSub != null && destSub != null) + { + CopyRegistryKey(srcSub, destSub); + } } } } diff --git a/ContextMenuProfiler.UI/Core/Helpers/SmoothScrollingHelper.cs b/ContextMenuProfiler.UI/Core/Helpers/SmoothScrollingHelper.cs index 5788a7a..caf0868 100644 --- a/ContextMenuProfiler.UI/Core/Helpers/SmoothScrollingHelper.cs +++ b/ContextMenuProfiler.UI/Core/Helpers/SmoothScrollingHelper.cs @@ -25,7 +25,7 @@ private static void OnIsSmoothScrollingEnabledChanged(DependencyObject d, Depend } } - private static void Element_PreviewMouseWheel(object sender, MouseWheelEventArgs e) + private static void Element_PreviewMouseWheel(object? sender, MouseWheelEventArgs e) { var uiElement = sender as UIElement; var scrollViewer = FindParentScrollViewer(uiElement); @@ -38,8 +38,9 @@ private static void Element_PreviewMouseWheel(object sender, MouseWheelEventArgs GetSmoother(scrollViewer).DoScroll(e.Delta); } - private static ScrollViewer FindParentScrollViewer(DependencyObject child) + private static ScrollViewer? FindParentScrollViewer(DependencyObject? child) { + if (child == null) return null; var parent = VisualTreeHelper.GetParent(child); while (parent != null && !(parent is ScrollViewer)) { @@ -89,7 +90,7 @@ public void DoScroll(int delta) } } - private void OnRendering(object sender, EventArgs e) + private void OnRendering(object? sender, EventArgs e) { double current = _sv.VerticalOffset; double diff = _targetOffset - current; diff --git a/ContextMenuProfiler.UI/Core/PackageScanner.cs b/ContextMenuProfiler.UI/Core/PackageScanner.cs index 516b1d7..c57d65a 100644 --- a/ContextMenuProfiler.UI/Core/PackageScanner.cs +++ b/ContextMenuProfiler.UI/Core/PackageScanner.cs @@ -48,7 +48,7 @@ public static IEnumerable ScanPackagedExtensions(string? target private static void ProcessPackage(Package package, List results, string targetExt, bool scanAll) { - string installPath = package.InstalledLocation?.Path; + string? installPath = package.InstalledLocation?.Path; if (string.IsNullOrEmpty(installPath)) return; string manifestPath = Path.Combine(installPath, "AppxManifest.xml"); @@ -83,7 +83,7 @@ private static void ProcessExtensionElement(Package package, XElement extElement foreach (var itemType in itemTypes) { - string type = itemType.Attribute("Type")?.Value?.ToLower(); + string? type = itemType.Attribute("Type")?.Value?.ToLower(); if (string.IsNullOrEmpty(type)) continue; if (!scanAll && !IsTypeMatch(type, targetExt)) continue; @@ -91,7 +91,7 @@ private static void ProcessExtensionElement(Package package, XElement extElement var verbs = itemType.Descendants().Where(e => e.Name.LocalName == "Verb"); foreach (var verb in verbs) { - if (TryParseVerb(package, verb, clsidToPath, installPath, out var result)) + if (TryParseVerb(package, verb, clsidToPath, installPath, out var result) && result != null) { if (!results.Any(r => r.Clsid == result.Clsid)) results.Add(result); @@ -101,19 +101,19 @@ private static void ProcessExtensionElement(Package package, XElement extElement } private static bool TryParseVerb(Package package, XElement verb, Dictionary clsidToPath, - string installPath, out BenchmarkResult result) + string installPath, out BenchmarkResult? result) { result = null; - string clsidStr = verb.Attribute("Clsid")?.Value; + string? clsidStr = verb.Attribute("Clsid")?.Value; if (!Guid.TryParse(clsidStr, out Guid clsid)) return false; string name = package.DisplayName; if (string.IsNullOrEmpty(name)) name = package.Id.Name; - string verbId = verb.Attribute("Id")?.Value; + string? verbId = verb.Attribute("Id")?.Value; if (!string.IsNullOrEmpty(verbId)) name += $" ({verbId})"; - string logoPath = ResolveBestLogo(package, verb.Document, installPath); + string? logoPath = ResolveBestLogo(package, verb.Document, installPath); string binaryPath = clsidToPath.TryGetValue(clsid, out var relPath) ? ResolveBinaryPath(installPath, relPath) : installPath; @@ -135,12 +135,13 @@ private static bool TryParseVerb(Package package, XElement verb, Dictionary e.Name.LocalName == "VisualElements"); if (visualElements != null) @@ -170,8 +171,8 @@ private static Dictionary MapClsidToBinaryPath(XDocument doc, stri foreach (var cls in classes) { - string idStr = cls.Attribute("Id")?.Value; - string path = cls.Attribute("Path")?.Value; + string? idStr = cls.Attribute("Id")?.Value; + string? path = cls.Attribute("Path")?.Value; if (Guid.TryParse(idStr, out Guid guid) && !string.IsNullOrEmpty(path)) { map[guid] = path; @@ -221,4 +222,4 @@ private static bool IsTypeMatch(string type, string targetExt) catch { return null; } } } -} \ No newline at end of file +} diff --git a/ContextMenuProfiler.UI/Core/RegistryScanner.cs b/ContextMenuProfiler.UI/Core/RegistryScanner.cs index 9de0049..5cd3138 100644 --- a/ContextMenuProfiler.UI/Core/RegistryScanner.cs +++ b/ContextMenuProfiler.UI/Core/RegistryScanner.cs @@ -70,7 +70,7 @@ public static Dictionary> ScanHandlers(ScanMode ScanLocation(handlers, $"SystemFileAssociations\\{keyName}\\shellex\\-ContextMenuHandlers", $"Extension ({keyName}) [Disabled]"); // Get ProgID - string progId = GetProgID(keyName); + string? progId = GetProgID(keyName); if (!string.IsNullOrEmpty(progId)) { ScanLocation(handlers, $"{progId}\\shellex\\ContextMenuHandlers", $"ProgID ({progId} for {keyName})"); @@ -109,7 +109,7 @@ private static void ScanLocation(ConcurrentDictionary> verb if (string.IsNullOrEmpty(command)) continue; // Get Display Name (MUIVerb > Default) - string displayName = verbKey.GetValue("MUIVerb") as string; + string? displayName = verbKey.GetValue("MUIVerb") as string; if (string.IsNullOrEmpty(displayName)) { displayName = verbKey.GetValue("") as string; // Default value diff --git a/ContextMenuProfiler.UI/Core/Services/LogService.cs b/ContextMenuProfiler.UI/Core/Services/LogService.cs index 5bc84c0..8c748d2 100644 --- a/ContextMenuProfiler.UI/Core/Services/LogService.cs +++ b/ContextMenuProfiler.UI/Core/Services/LogService.cs @@ -16,7 +16,7 @@ private LogService() try { var dir = Path.GetDirectoryName(LogFile); - if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); + if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) Directory.CreateDirectory(dir); } catch { /* Best effort */ } } diff --git a/ContextMenuProfiler.UI/MainWindow.xaml.cs b/ContextMenuProfiler.UI/MainWindow.xaml.cs index 203615c..ed5a6bf 100644 --- a/ContextMenuProfiler.UI/MainWindow.xaml.cs +++ b/ContextMenuProfiler.UI/MainWindow.xaml.cs @@ -130,7 +130,7 @@ private void Window_DragOver(object sender, DragEventArgs e) } } - private T FindChild(DependencyObject parent) where T : DependencyObject + private T? FindChild(DependencyObject? parent) where T : DependencyObject { if (parent == null) return null; diff --git a/ContextMenuProfiler.UI/ViewModels/DashboardViewModel.cs b/ContextMenuProfiler.UI/ViewModels/DashboardViewModel.cs index 578c914..2eb5c6c 100644 --- a/ContextMenuProfiler.UI/ViewModels/DashboardViewModel.cs +++ b/ContextMenuProfiler.UI/ViewModels/DashboardViewModel.cs @@ -447,7 +447,7 @@ private async Task ScanFile(string filePath) { var results = await Task.Run(() => { - List threadResult = null; + List? threadResult = null; var thread = new Thread(() => { try @@ -462,10 +462,10 @@ private async Task ScanFile(string filePath) thread.SetApartmentState(ApartmentState.STA); thread.Start(); thread.Join(); - return threadResult; + return threadResult ?? new List(); }); - if (results != null) + if (results.Count > 0) { // Use InsertSorted logic for consistency and performance foreach (var res in results.OrderByDescending(r => r.TotalTime)) diff --git a/ContextMenuProfiler.sln b/ContextMenuProfiler.sln index 154b532..b88bf9f 100644 --- a/ContextMenuProfiler.sln +++ b/ContextMenuProfiler.sln @@ -4,8 +4,6 @@ VisualStudioVersion = 18.3.11520.95 d18.3 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ContextMenuProfiler.UI", "ContextMenuProfiler.UI\ContextMenuProfiler.UI.csproj", "{AE0FB575-F9F7-4FA5-BACF-E007199E47E4}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BenchmarkSuite1", "BenchmarkSuite1\BenchmarkSuite1.csproj", "{A20861A9-411E-6150-BF5C-69E8196E5D22}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -28,18 +26,6 @@ Global {AE0FB575-F9F7-4FA5-BACF-E007199E47E4}.Release|x64.Build.0 = Release|Any CPU {AE0FB575-F9F7-4FA5-BACF-E007199E47E4}.Release|x86.ActiveCfg = Release|Any CPU {AE0FB575-F9F7-4FA5-BACF-E007199E47E4}.Release|x86.Build.0 = Release|Any CPU - {A20861A9-411E-6150-BF5C-69E8196E5D22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A20861A9-411E-6150-BF5C-69E8196E5D22}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A20861A9-411E-6150-BF5C-69E8196E5D22}.Debug|x64.ActiveCfg = Debug|Any CPU - {A20861A9-411E-6150-BF5C-69E8196E5D22}.Debug|x64.Build.0 = Debug|Any CPU - {A20861A9-411E-6150-BF5C-69E8196E5D22}.Debug|x86.ActiveCfg = Debug|Any CPU - {A20861A9-411E-6150-BF5C-69E8196E5D22}.Debug|x86.Build.0 = Debug|Any CPU - {A20861A9-411E-6150-BF5C-69E8196E5D22}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A20861A9-411E-6150-BF5C-69E8196E5D22}.Release|Any CPU.Build.0 = Release|Any CPU - {A20861A9-411E-6150-BF5C-69E8196E5D22}.Release|x64.ActiveCfg = Release|Any CPU - {A20861A9-411E-6150-BF5C-69E8196E5D22}.Release|x64.Build.0 = Release|Any CPU - {A20861A9-411E-6150-BF5C-69E8196E5D22}.Release|x86.ActiveCfg = Release|Any CPU - {A20861A9-411E-6150-BF5C-69E8196E5D22}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/scripts/build_hook.bat b/scripts/build_hook.bat index 2f692e2..d579c78 100644 --- a/scripts/build_hook.bat +++ b/scripts/build_hook.bat @@ -1,4 +1,5 @@ @echo off +setlocal EnableExtensions cd /d "%~dp0.." echo Building ContextMenuProfiler.Hook (x64) - Modularized... @@ -7,39 +8,48 @@ set "OBJ_DIR=%BUILD_DIR%\obj" if not exist "%BUILD_DIR%" mkdir "%BUILD_DIR%" if not exist "%OBJ_DIR%" mkdir "%OBJ_DIR%" -:: Check if cl.exe is already in the path and configured for x64 -:: We use 'where' which is more stable in both CMD and PowerShell -where cl >nul 2>nul -if %ERRORLEVEL% EQU 0 ( - cl 2>&1 | findstr /i "x64" >nul - if %ERRORLEVEL% EQU 0 ( - echo Environment already configured for x64, skipping vcvars64.bat - goto :compile - ) +if /I "%VSCMD_ARG_TGT_ARCH%"=="x64" ( + echo Environment already configured for x64, skipping vcvars64.bat + goto :compile ) :: Try to find VS path using vswhere -for /f "usebackq tokens=*" %%i in (`"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath`) do set "VS_PATH=%%i" +set "VS_PATH=" +set "VSWHERE_EXE=%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" +if exist "%VSWHERE_EXE%" ( + for /f "usebackq tokens=*" %%i in (`"%VSWHERE_EXE%" -latest -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do set "VS_PATH=%%i" +) -if not exist "%VS_PATH%" ( - :: Fallback to common paths - set "VS_PATH=C:\Program Files\Microsoft Visual Studio\2022\Community" +if not defined VS_PATH ( + for %%E in (Community Professional Enterprise BuildTools) do ( + if exist "C:\Program Files\Microsoft Visual Studio\2022\%%E\VC\Auxiliary\Build\vcvars64.bat" set "VS_PATH=C:\Program Files\Microsoft Visual Studio\2022\%%E" + ) ) -if not exist "%VS_PATH%" ( - echo Error: Visual Studio not found. Please install VS 2022 or higher, or edit build_hook.bat to set VS_PATH. +if not defined VS_PATH ( + echo Error: Visual Studio C++ build tools not found. + echo Hint: Install VS 2022 with Desktop development with C++ workload. exit /b 1 ) +if not exist "%VS_PATH%\VC\Auxiliary\Build\vcvars64.bat" ( + echo Error: vcvars64.bat not found in "%VS_PATH%". + exit /b 1 +) echo Using VS Path: %VS_PATH% -if exist "%VS_PATH%\VC\Auxiliary\Build\vcvars64.bat" ( - call "%VS_PATH%\VC\Auxiliary\Build\vcvars64.bat" -) else ( - echo Error: vcvars64.bat not found in %VS_PATH% +call "%VS_PATH%\VC\Auxiliary\Build\vcvars64.bat" >nul 2>&1 +if %ERRORLEVEL% NEQ 0 ( + echo Error: Failed to initialize VC++ x64 environment. exit /b 1 ) :compile +where cl >nul 2>nul +if %ERRORLEVEL% NEQ 0 ( + echo Error: cl.exe not found after environment initialization. + exit /b 1 +) + :: Build Hook DLL cl /LD /MT /Zi /EHsc /utf-8 /Fo"%OBJ_DIR%\\" /Fd"%BUILD_DIR%\\vc140.pdb" ^ ContextMenuProfiler.Hook\src\dllmain.cpp ^ @@ -54,18 +64,31 @@ cl /LD /MT /Zi /EHsc /utf-8 /Fo"%OBJ_DIR%\\" /Fd"%BUILD_DIR%\\vc140.pdb" ^ ContextMenuProfiler.Hook\src\hde\hde64.c ^ /I ContextMenuProfiler.Hook\include ^ /link /DLL /DEBUG /OUT:"%BUILD_DIR%\\ContextMenuProfiler.Hook.dll" /PDB:"%BUILD_DIR%\\ContextMenuProfiler.Hook.pdb" /IMPLIB:"%BUILD_DIR%\\ContextMenuProfiler.Hook.lib" user32.lib ole32.lib shell32.lib shlwapi.lib advapi32.lib gdiplus.lib comctl32.lib gdi32.lib -if %ERRORLEVEL% NEQ 0 exit /b %ERRORLEVEL% +if %ERRORLEVEL% NEQ 0 ( + echo Error: Hook DLL build failed. + exit /b %ERRORLEVEL% +) echo Building Injector... cl /MT /Zi /EHsc /utf-8 /Fo"%OBJ_DIR%\\" /Fd"%BUILD_DIR%\\vc140.pdb" ^ ContextMenuProfiler.Hook\src\injector.cpp ^ /I ContextMenuProfiler.Hook\include ^ /link /DEBUG /OUT:"%BUILD_DIR%\\ContextMenuProfiler.Injector.exe" /PDB:"%BUILD_DIR%\\ContextMenuProfiler.Injector.pdb" user32.lib kernel32.lib advapi32.lib -if %ERRORLEVEL% NEQ 0 exit /b %ERRORLEVEL% +if %ERRORLEVEL% NEQ 0 ( + echo Error: Injector build failed. + exit /b %ERRORLEVEL% +) copy /Y "%BUILD_DIR%\ContextMenuProfiler.Hook.dll" "ContextMenuProfiler.Hook.dll" >nul +if %ERRORLEVEL% NEQ 0 ( + echo Error: Failed to copy ContextMenuProfiler.Hook.dll + exit /b 1 +) copy /Y "%BUILD_DIR%\ContextMenuProfiler.Injector.exe" "ContextMenuProfiler.Injector.exe" >nul -if %ERRORLEVEL% NEQ 0 exit /b 1 +if %ERRORLEVEL% NEQ 0 ( + echo Error: Failed to copy ContextMenuProfiler.Injector.exe + exit /b 1 +) echo Done. exit /b 0 diff --git a/scripts/redeploy.bat b/scripts/redeploy.bat index ba75581..0014de5 100644 --- a/scripts/redeploy.bat +++ b/scripts/redeploy.bat @@ -30,9 +30,20 @@ echo Waiting for Explorer to initialize... timeout /t 8 /nobreak >nul echo Injecting DLL... +if not exist ContextMenuProfiler.Injector.exe ( + echo Injection FAILED: ContextMenuProfiler.Injector.exe not found. + echo Hint: Run scripts\build_hook.bat and verify output files. + exit /b 1 +) +if not exist ContextMenuProfiler.Hook.dll ( + echo Injection FAILED: ContextMenuProfiler.Hook.dll not found. + echo Hint: Run scripts\build_hook.bat and verify output files. + exit /b 1 +) ContextMenuProfiler.Injector.exe ContextMenuProfiler.Hook.dll if %ERRORLEVEL% NEQ 0 ( echo Injection FAILED. + echo Hint: Re-run as Administrator and ensure Explorer is running. exit /b 1 ) From 210a27ffb5019cbcba241962a2c8a47781c84762 Mon Sep 17 00:00:00 2001 From: Haerbin23456 <60066765+Haerbin23456@users.noreply.github.com> Date: Thu, 5 Mar 2026 16:50:15 +0800 Subject: [PATCH 2/2] ci: enable manual workflow triggers and guard release step --- .github/workflows/build.yml | 2 +- .github/workflows/release.yml | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e5c094a..78c54a5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,7 +4,7 @@ on: push: branches: [ "main" ] pull_request: - branches: [ "main" ] + workflow_dispatch: jobs: build: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bc8c69e..9fb5a11 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,6 +4,7 @@ on: push: tags: - "v*" + workflow_dispatch: permissions: contents: write @@ -55,6 +56,7 @@ jobs: if (!(Test-Path "artifacts/ContextMenuProfiler-win-x64-self-contained.zip")) { throw "self-contained zip missing" } - name: Create GitHub Release + if: startsWith(github.ref, 'refs/tags/v') uses: softprops/action-gh-release@v2 with: draft: false