Adding FxCop to Microsoft.Plugin.WindowWalker (#6260)

* Adding FxCop to Microsoft.Plugin.WindowWalker

* Delete WindowResult.cs -- Fix for CA1812 WindowResult is an internal class that is apparently never instantiated. If so, remove the code from the assembly. If this class is intended to contain only static members, make it static (Shared in Visual Basic).

* Fix for CA1806 UpdateOpenWindowsList calls EnumWindows but does not use the HRESULT or error code that the method returns. This could lead to unexpected behavior in error conditions or low-resource situations. Use the result in a conditional statement, assign the result to a variable, or pass it as an argument to another method.

* Fix for: CA1066 Type Microsoft.Plugin.WindowWalker.Components.InteropAndHelpers.RECT should implement IEquatable<T> because it overrides Equals

* Fix for:  CA1052 Type 'FuzzyMatching' is a static holder type but is neither static nor NotInheritable

* Suppress for CA1069 - These values are defined in
https://docs.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles.

CA1069 The enum member 'WS_EX_LTRREADING' has the same constant value '0' as member 'WS_EX_LEFT'
CA1069 The enum member 'WS_EX_RIGHTSCROLLBAR' has the same constant value '0' as member 'WS_EX_LEFT'

* Supress CA1069

Code Description
CA1069 The enum member 'SWP_NOREPOSITION' has the same constant value '512' as member 'SWP_NOOWNERZORDER'
CA1069 The enum member 'SWP_FRAMECHANGED' has the same constant value '32' as member 'SWP_DRAWFRAME'

* Suprress CA1069 for ShowWindow values.  See

https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow

CA1069 The enum member 'ShowMaximized' has the same constant value '3' as member 'Maximize'

* Fix code formatting error

* Fix for CA2235: Making POINT serializable

CA2235 Field MinPosition is a member of type WINDOWPLACEMENT which is serializable but is of type Microsoft.Plugin.WindowWalker.Components.InteropAndHelpers.POINT which is not serializable
CA2235 Field MaxPosition is a member of type WINDOWPLACEMENT which is serializable but is of type Microsoft.Plugin.WindowWalker.Components.InteropAndHelpers.POINT which is not serializable

* Fix CA2235 Making RECT serializable

CA2235 Field NormalPosition is a member of type WINDOWPLACEMENT which is serializable but is of type Microsoft.Plugin.WindowWalker.Components.InteropAndHelpers.RECT which is not serializable

* Fixes for CA2101 Specify marshaling for P/Invoke string arguments.

* Fixes for CA2007 Consider calling ConfigureAwait on the awaited task

* Fixes for the following (CA1822 / CA1801):
CA1822 Member 'OnOpenWindowsUpdate' does not access instance data and can be marked as static
Code Description
CA1801 Parameter value of method add_OnOpenWindowsUpdate is never used. Remove the parameter or use it in the method body.
CA1801 Parameter value of method remove_OnOpenWindowsUpdate is never used. Remove the parameter or use it in the method body.

* Fix: CA1710 Rename OpenWindowsUpdateHandler to end in 'EventHandler'

* Fix CA1822 Member 'GetProcessIDFromWindowHandle' does not access instance data and can be marked as static

* Fix CA1062 In externally visible method 'List<int> FuzzyMatching.FindBestFuzzyMatch(string text, string searchText)', validate parameter 'searchText' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.

* Fixes for CA1304 The behavior of 'string.ToLower()' could vary based on the current user's locale settings.

CA1304 The behavior of 'string.ToLower()' could vary based on the current user's locale settings. Replace this call in 'FuzzyMatching.FindBestFuzzyMatch(string, string)' with a call to 'string.ToLower(CultureInfo)'.

Code Description
CA1304 The behavior of 'string.ToLower()' could vary based on the current user's locale settings. Replace this call in 'FuzzyMatching.FindBestFuzzyMatch(string, string)' with a call to 'string.ToLower(CultureInfo)'.

* Supressing warning for CA1814: Prefer jagged arrays over multidimensional however this might be something to consider if needing to optimize the window walker search.

* Fix: CA1062 In externally visible method 'List<List<int>> FuzzyMatching.GetAllMatchIndexes(bool[,] matches)', validate parameter 'matches' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.

* Fix for CA1062 In externally visible method 'int FuzzyMatching.CalculateScoreForMatches(List<int> matches)', validate parameter 'matches' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.

* Fixes for CA1806 Calls x...  but does not use the HRESULT or error code that the method returns. This could lead to unexpected behavior in error conditions or low-resource situations. Use the result in a conditional statement, assign the result to a variable, or pass it as an argument to another method.

Using discard for methods that return void, and checking the hresult before returning parameters.

* Fix for CA1820 Test for empty strings using 'string.Length' property or 'string.IsNullOrEmpty' method instead of an Equality check

* Supress CA1031 Modify 'get_WindowIcon' to catch a more specific allowed exception type, or rethrow the exception

* Code Description
CA1062 In externally visible method 'List<Result> Main.Query(Query query)', validate parameter 'query' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.

* Fixes For CA1304 The behavior of 'string.ToUpper()' could vary based on the current user's locale settings.

CA1304 The behavior of 'string.ToLower()' could vary based on the current user's locale settings. Replace this call in 'SearchController.SearchText.set' with a call to 'string.ToLower(CultureInfo)'.
CA1304 The behavior of 'string.ToLower()' could vary based on the current user's locale settings. Replace this call in 'Window.ProcessName.get' with a call to 'string.ToLower(CultureInfo)'.
CA1304 The behavior of 'string.ToLower()' could vary based on the current user's locale settings. Replace this call in 'Window.SwitchToWindow()' with a call to 'string.ToLower(CultureInfo)'.
CA1304 The behavior of 'string.ToUpper()' could vary based on the current user's locale settings. Replace this call in 'Window.ToString()' with a call to 'string.ToUpper(CultureInfo)'.
CA1307 The behavior of 'string.Equals(string?)' could vary based on the current user's locale settings. Replace this call in 'Microsoft.Plugin.WindowWalker.Components.Window.SwitchToWindow()' with a call to 'string.Equals(string?, System.StringComparison)'.

* Fix: CA1710 Rename SearchResultUpdateHandler to end in 'EventHandler'

* Fix CA1060 Move pinvokes to native methods class

* Fix: CS0067 The event 'OpenWindows.OnOpenWindowsUpdateEventHandler' is never used

1) Remove SearchController::OpenWindowsUpdateHandler(object sender, SearchResultUpdateEventArgs e) as it wasn't being called and was redundant with Update Search Text.
2) In Main.cs calling UpdateOpenWindowsList before UpdateSearchText so that the latest enumerated windows will be called.
3) Removing unused OnOpenWindowsUpdateEventHandler and related code.

* Revert "Fixes for CA2101 Specify marshaling for P/Invoke string arguments."

This reverts commit b3dfe07915.

* Fixing CA2101 by turning off best fit mapping for methods that require ANSI marshalling.

See: https://docs.microsoft.com/en-us/visualstudio/code-quality/ca2101?view=vs-2019

* Previous fix for CA1806 misunderstood int result as hresult.  The actual return value is number of characters written.
NativeMethods.GetWindowText(hwnd, titleBuffer, sizeOfTitle);

* Previous fix for CA1806 misunderstood int result as hresult.  The actual return value is number of characters written.

NativeMethods.GetClassName(Hwnd, windowClassName, windowClassName.MaxCapacity);

* Removing unused window code.  This was done instead of validating fxcop changes in WindowIcon.

* Fixing typos in Window.cs (charachter -> character)
This commit is contained in:
ryanbodrug-microsoft 2020-09-10 09:44:22 -07:00 committed by GitHub
parent efd5c33a92
commit c4cb3df306
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 108 additions and 177 deletions

View File

@ -3,7 +3,9 @@
// See the LICENSE file in the project root for more information.
// Code forked from Betsegaw Tadele's https://github.com/betsegaw/windowwalker/
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
namespace Microsoft.Plugin.WindowWalker.Components
@ -11,7 +13,7 @@ namespace Microsoft.Plugin.WindowWalker.Components
/// <summary>
/// Class housing fuzzy matching methods
/// </summary>
public class FuzzyMatching
public static class FuzzyMatching
{
/// <summary>
/// Finds the best match (the one with the most
@ -22,10 +24,21 @@ namespace Microsoft.Plugin.WindowWalker.Components
/// <param name="text">The text to search inside of</param>
/// <param name="searchText">the text to search for</param>
/// <returns>returns the index location of each of the letters of the matches</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1814:Prefer jagged arrays over multidimensional", Justification = "matches does not waste space with the current implementation, however this could probably be optimized to store the indices of matches instead of boolean values. Currently there are no unit tests for this, but we could refactor if memory/perf becomes an issue. ")]
public static List<int> FindBestFuzzyMatch(string text, string searchText)
{
searchText = searchText.ToLower();
text = text.ToLower();
if (searchText == null)
{
throw new ArgumentNullException(nameof(searchText));
}
if (text == null)
{
throw new ArgumentNullException(nameof(text));
}
searchText = searchText.ToLower(CultureInfo.CurrentCulture);
text = text.ToLower(CultureInfo.CurrentCulture);
// Create a grid to march matches like
// eg.
@ -71,8 +84,14 @@ namespace Microsoft.Plugin.WindowWalker.Components
/// a two dimensional array with the first dimension the text and the second
/// one the search string and each cell marked as an intersection between the two</param>
/// <returns>a list of the possible combinations that match the search text</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1814:Prefer jagged arrays over multidimensional", Justification = "matches does not waste space with the current implementation, however this could probably be optimized to store the indices of matches instead of boolean values. Currently there are no unit tests for this, but we could refactor if memory/perf becomes an issue. ")]
public static List<List<int>> GetAllMatchIndexes(bool[,] matches)
{
if (matches == null)
{
throw new ArgumentNullException(nameof(matches));
}
List<List<int>> results = new List<List<int>>();
for (int secondIndex = 0; secondIndex < matches.GetLength(1); secondIndex++)
@ -109,6 +128,11 @@ namespace Microsoft.Plugin.WindowWalker.Components
/// <returns>an integer representing the score</returns>
public static int CalculateScoreForMatches(List<int> matches)
{
if (matches == null)
{
throw new ArgumentNullException(nameof(matches));
}
var score = 0;
for (int currentIndex = 1; currentIndex < matches.Count; currentIndex++)

View File

@ -18,9 +18,9 @@ namespace Microsoft.Plugin.WindowWalker.Components
/// <param name="hwnd">handle to the window to exclude</param>
public static void SetWindowExclusionFromLivePreview(IntPtr hwnd)
{
int renderPolicy = (int)InteropAndHelpers.DwmNCRenderingPolicy.Enabled;
int renderPolicy = (int)NativeMethods.DwmNCRenderingPolicy.Enabled;
InteropAndHelpers.DwmSetWindowAttribute(
_ = NativeMethods.DwmSetWindowAttribute(
hwnd,
12,
ref renderPolicy,
@ -34,11 +34,11 @@ namespace Microsoft.Plugin.WindowWalker.Components
/// <param name="windowToSpare">the window which should not be transparent but is not the target window</param>
public static void ActivateLivePreview(IntPtr targetWindow, IntPtr windowToSpare)
{
InteropAndHelpers.DwmpActivateLivePreview(
_ = NativeMethods.DwmpActivateLivePreview(
true,
targetWindow,
windowToSpare,
InteropAndHelpers.LivePreviewTrigger.Superbar,
NativeMethods.LivePreviewTrigger.Superbar,
IntPtr.Zero);
}
@ -47,11 +47,11 @@ namespace Microsoft.Plugin.WindowWalker.Components
/// </summary>
public static void DeactivateLivePreview()
{
InteropAndHelpers.DwmpActivateLivePreview(
_ = NativeMethods.DwmpActivateLivePreview(
false,
IntPtr.Zero,
IntPtr.Zero,
InteropAndHelpers.LivePreviewTrigger.AltTab,
NativeMethods.LivePreviewTrigger.AltTab,
IntPtr.Zero);
}
}

View File

@ -12,7 +12,7 @@ namespace Microsoft.Plugin.WindowWalker.Components
/// <summary>
/// Interop calls with helper layers
/// </summary>
internal class InteropAndHelpers
internal class NativeMethods
{
public delegate bool CallBackPtr(IntPtr hwnd, IntPtr lParam);
@ -20,6 +20,7 @@ namespace Microsoft.Plugin.WindowWalker.Components
/// Some flags for interop calls to SetWindowPosition
/// </summary>
[Flags]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1069:Enums values should not be duplicated", Justification = "These are defined in win32 libraries. See https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowpos")]
public enum SetWindowPosFlags : uint
{
/// <summary>
@ -150,6 +151,7 @@ namespace Microsoft.Plugin.WindowWalker.Components
/// <summary>
/// Show Window Enums
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1069:Enums values should not be duplicated", Justification = "This is defined in the ShowWindow win32 method. See https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow")]
public enum ShowWindowCommands
{
/// <summary>
@ -425,8 +427,9 @@ namespace Microsoft.Plugin.WindowWalker.Components
/// <summary>
/// Required pointless variables that we don't use in making a windows show
/// </summary>
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct RECT
public struct RECT : IEquatable<RECT>
{
public int Left;
public int Top;
@ -567,6 +570,7 @@ namespace Microsoft.Plugin.WindowWalker.Components
/// <summary>
/// Same as the RECT struct above
/// </summary>
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
@ -647,6 +651,7 @@ namespace Microsoft.Plugin.WindowWalker.Components
/// The following are the extended window styles
/// </summary>
[Flags]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1069:Enums values should not be duplicated", Justification = "These values are specific in the win32 libraries. See https://docs.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles")]
public enum ExtendedWindowStyles : uint
{
/// <summary>
@ -847,10 +852,10 @@ namespace Microsoft.Plugin.WindowWalker.Components
[DllImport("user32.dll", SetLastError = true)]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("psapi.dll")]
[DllImport("psapi.dll", BestFitMapping = false)]
public static extern uint GetProcessImageFileName(IntPtr hProcess, [Out] StringBuilder lpImageFileName, [In][MarshalAs(UnmanagedType.U4)] int nSize);
[DllImport("user32.dll", SetLastError = true)]
[DllImport("user32.dll", SetLastError = true, BestFitMapping = false)]
public static extern IntPtr GetProp(IntPtr hWnd, string lpString);
[DllImport("kernel32.dll")]
@ -865,7 +870,7 @@ namespace Microsoft.Plugin.WindowWalker.Components
[DllImport("dwmapi.dll", PreserveSig = false)]
public static extern int DwmGetWindowAttribute(IntPtr hwnd, int dwAttribute, out int pvAttribute, int cbAttribute);
[DllImport("user32.dll")]
[DllImport("user32.dll", BestFitMapping = false)]
public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
[DllImport("user32.dll", SetLastError = true)]

View File

@ -16,16 +16,7 @@ namespace Microsoft.Plugin.WindowWalker.Components
/// <summary>
/// Delegate handler for open windows updates
/// </summary>
public delegate void OpenWindowsUpdateHandler(object sender, SearchController.SearchResultUpdateEventArgs e);
/// <summary>
/// Event raised when there is an update to the list of open windows
/// </summary>
public event OpenWindowsUpdateHandler OnOpenWindowsUpdate
{
add { }
remove { }
}
public delegate void OpenWindowsUpdateEventHandler(object sender, SearchController.SearchResultUpdateEventArgs e);
/// <summary>
/// List of all the open windows
@ -78,8 +69,8 @@ namespace Microsoft.Plugin.WindowWalker.Components
public void UpdateOpenWindowsList()
{
windows.Clear();
InteropAndHelpers.CallBackPtr callbackptr = new InteropAndHelpers.CallBackPtr(WindowEnumerationCallBack);
InteropAndHelpers.EnumWindows(callbackptr, 0);
NativeMethods.CallBackPtr callbackptr = new NativeMethods.CallBackPtr(WindowEnumerationCallBack);
_ = NativeMethods.EnumWindows(callbackptr, 0);
}
/// <summary>

View File

@ -5,6 +5,7 @@
// Code forked from Betsegaw Tadele's https://github.com/betsegaw/windowwalker/
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
@ -34,12 +35,12 @@ namespace Microsoft.Plugin.WindowWalker.Components
/// <summary>
/// Delegate handler for open windows updates
/// </summary>
public delegate void SearchResultUpdateHandler(object sender, SearchResultUpdateEventArgs e);
public delegate void SearchResultUpdateEventHandler(object sender, SearchResultUpdateEventArgs e);
/// <summary>
/// Event raised when there is an update to the list of open windows
/// </summary>
public event SearchResultUpdateHandler OnSearchResultUpdate;
public event SearchResultUpdateEventHandler OnSearchResultUpdateEventHandler;
/// <summary>
/// Gets or sets the current search text
@ -53,7 +54,7 @@ namespace Microsoft.Plugin.WindowWalker.Components
set
{
searchText = value.ToLower().Trim();
searchText = value.ToLower(CultureInfo.CurrentCulture).Trim();
}
}
@ -88,7 +89,6 @@ namespace Microsoft.Plugin.WindowWalker.Components
private SearchController()
{
searchText = string.Empty;
OpenWindows.Instance.OnOpenWindowsUpdate += OpenWindowsUpdateHandler;
}
/// <summary>
@ -97,17 +97,7 @@ namespace Microsoft.Plugin.WindowWalker.Components
public async Task UpdateSearchText(string searchText)
{
SearchText = searchText;
await SyncOpenWindowsWithModelAsync();
}
/// <summary>
/// Event handler called when the OpenWindows list changes
/// </summary>
/// <param name="sender">sending item</param>
/// <param name="e">event arg</param>
public async void OpenWindowsUpdateHandler(object sender, SearchResultUpdateEventArgs e)
{
await SyncOpenWindowsWithModelAsync();
await SyncOpenWindowsWithModelAsync().ConfigureAwait(false);
}
/// <summary>
@ -119,16 +109,16 @@ namespace Microsoft.Plugin.WindowWalker.Components
List<Window> snapshotOfOpenWindows = OpenWindows.Instance.Windows;
if (SearchText == string.Empty)
if (string.IsNullOrWhiteSpace(SearchText))
{
searchMatches = new List<SearchResult>();
}
else
{
searchMatches = await FuzzySearchOpenWindowsAsync(snapshotOfOpenWindows);
searchMatches = await FuzzySearchOpenWindowsAsync(snapshotOfOpenWindows).ConfigureAwait(false);
}
OnSearchResultUpdate?.Invoke(this, new SearchResultUpdateEventArgs());
OnSearchResultUpdateEventHandler?.Invoke(this, new SearchResultUpdateEventArgs());
}
/// <summary>

View File

@ -7,6 +7,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@ -33,12 +34,6 @@ namespace Microsoft.Plugin.WindowWalker.Components
/// </summary>
private static readonly Dictionary<IntPtr, string> _handlesToProcessCache = new Dictionary<IntPtr, string>();
/// <summary>
/// The list of icons from process so that we don't have to keep
/// loading them from disk
/// </summary>
private static readonly Dictionary<uint, ImageSource> _processIdsToIconsCache = new Dictionary<uint, ImageSource>();
/// <summary>
/// The handle to the window
/// </summary>
@ -51,11 +46,16 @@ namespace Microsoft.Plugin.WindowWalker.Components
{
get
{
int sizeOfTitle = InteropAndHelpers.GetWindowTextLength(hwnd);
int sizeOfTitle = NativeMethods.GetWindowTextLength(hwnd);
if (sizeOfTitle++ > 0)
{
StringBuilder titleBuffer = new StringBuilder(sizeOfTitle);
InteropAndHelpers.GetWindowText(hwnd, titleBuffer, sizeOfTitle);
var numCharactersWritten = NativeMethods.GetWindowText(hwnd, titleBuffer, sizeOfTitle);
if (numCharactersWritten == 0)
{
return string.Empty;
}
return titleBuffer.ToString();
}
else
@ -106,11 +106,11 @@ namespace Microsoft.Plugin.WindowWalker.Components
}
}
if (_handlesToProcessCache[hwnd].ToLower() == "applicationframehost.exe")
if (_handlesToProcessCache[hwnd].ToUpperInvariant() == "APPLICATIONFRAMEHOST.EXE")
{
new Task(() =>
{
InteropAndHelpers.CallBackPtr callbackptr = new InteropAndHelpers.CallBackPtr((IntPtr hwnd, IntPtr lParam) =>
NativeMethods.CallBackPtr callbackptr = new NativeMethods.CallBackPtr((IntPtr hwnd, IntPtr lParam) =>
{
var childProcessId = GetProcessIDFromWindowHandle(hwnd);
if (childProcessId != ProcessID)
@ -123,7 +123,7 @@ namespace Microsoft.Plugin.WindowWalker.Components
return true;
}
});
InteropAndHelpers.EnumChildWindows(Hwnd, callbackptr, 0);
_ = NativeMethods.EnumChildWindows(Hwnd, callbackptr, 0);
}).Start();
}
@ -140,46 +140,17 @@ namespace Microsoft.Plugin.WindowWalker.Components
get
{
StringBuilder windowClassName = new StringBuilder(300);
InteropAndHelpers.GetClassName(Hwnd, windowClassName, windowClassName.MaxCapacity);
var numCharactersWritten = NativeMethods.GetClassName(Hwnd, windowClassName, windowClassName.MaxCapacity);
if (numCharactersWritten == 0)
{
return string.Empty;
}
return windowClassName.ToString();
}
}
/// <summary>
/// Gets represents the Window Icon for the specified window
/// </summary>
public ImageSource WindowIcon
{
get
{
lock (_processIdsToIconsCache)
{
InteropAndHelpers.GetWindowThreadProcessId(Hwnd, out uint processId);
if (!_processIdsToIconsCache.ContainsKey(processId))
{
try
{
Process process = Process.GetProcessById((int)processId);
Icon tempIcon = Icon.ExtractAssociatedIcon(process.Modules[0].FileName);
_processIdsToIconsCache.Add(processId, Imaging.CreateBitmapSourceFromHIcon(
tempIcon.Handle,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions()));
}
catch
{
BitmapImage failedImage = new BitmapImage(new Uri(@"Images\failedIcon.jpg", UriKind.Relative));
_processIdsToIconsCache.Add(processId, failedImage);
}
}
return _processIdsToIconsCache[processId];
}
}
}
/// <summary>
/// Gets a value indicating whether is the window visible (might return false if it is a hidden IE tab)
/// </summary>
@ -187,7 +158,7 @@ namespace Microsoft.Plugin.WindowWalker.Components
{
get
{
return InteropAndHelpers.IsWindowVisible(Hwnd);
return NativeMethods.IsWindowVisible(Hwnd);
}
}
@ -198,7 +169,7 @@ namespace Microsoft.Plugin.WindowWalker.Components
{
get
{
return InteropAndHelpers.IsWindow(Hwnd);
return NativeMethods.IsWindow(Hwnd);
}
}
@ -209,9 +180,9 @@ namespace Microsoft.Plugin.WindowWalker.Components
{
get
{
return (InteropAndHelpers.GetWindowLong(Hwnd, InteropAndHelpers.GWL_EXSTYLE) &
(uint)InteropAndHelpers.ExtendedWindowStyles.WS_EX_TOOLWINDOW) ==
(uint)InteropAndHelpers.ExtendedWindowStyles.WS_EX_TOOLWINDOW;
return (NativeMethods.GetWindowLong(Hwnd, NativeMethods.GWL_EXSTYLE) &
(uint)NativeMethods.ExtendedWindowStyles.WS_EX_TOOLWINDOW) ==
(uint)NativeMethods.ExtendedWindowStyles.WS_EX_TOOLWINDOW;
}
}
@ -222,9 +193,9 @@ namespace Microsoft.Plugin.WindowWalker.Components
{
get
{
return (InteropAndHelpers.GetWindowLong(Hwnd, InteropAndHelpers.GWL_EXSTYLE) &
(uint)InteropAndHelpers.ExtendedWindowStyles.WS_EX_APPWINDOW) ==
(uint)InteropAndHelpers.ExtendedWindowStyles.WS_EX_APPWINDOW;
return (NativeMethods.GetWindowLong(Hwnd, NativeMethods.GWL_EXSTYLE) &
(uint)NativeMethods.ExtendedWindowStyles.WS_EX_APPWINDOW) ==
(uint)NativeMethods.ExtendedWindowStyles.WS_EX_APPWINDOW;
}
}
@ -235,18 +206,7 @@ namespace Microsoft.Plugin.WindowWalker.Components
{
get
{
return InteropAndHelpers.GetProp(Hwnd, "ITaskList_Deleted") != IntPtr.Zero;
}
}
/// <summary>
/// Gets a value indicating whether get a value indicating whether the app is a cloaked UWP app
/// </summary>
public bool IsUWPCloaked
{
get
{
return IsWindowCloaked() && ClassName == "ApplicationFrameWindow";
return NativeMethods.GetProp(Hwnd, "ITaskList_Deleted") != IntPtr.Zero;
}
}
@ -257,21 +217,10 @@ namespace Microsoft.Plugin.WindowWalker.Components
{
get
{
return InteropAndHelpers.GetWindow(Hwnd, InteropAndHelpers.GetWindowCmd.GW_OWNER) != null;
return NativeMethods.GetWindow(Hwnd, NativeMethods.GetWindowCmd.GW_OWNER) != null;
}
}
/// <summary>
/// Gets a value indicating whether is the window cloaked. To detect UWP apps in background or win32 apps running in another virtual desktop
/// </summary>
public bool IsWindowCloaked()
{
int isCloaked = 0;
const int DWMWA_CLOAKED = 14;
InteropAndHelpers.DwmGetWindowAttribute(hwnd, DWMWA_CLOAKED, out isCloaked, sizeof(int));
return isCloaked != 0;
}
/// <summary>
/// Gets a value indicating whether returns true if the window is minimized
/// </summary>
@ -294,14 +243,6 @@ namespace Microsoft.Plugin.WindowWalker.Components
this.hwnd = hwnd;
}
/// <summary>
/// Highlights a window to help the user identify the window that has been selected
/// </summary>
public void HighlightWindow()
{
throw new NotImplementedException();
}
/// <summary>
/// Switches desktop focus to the window
/// </summary>
@ -311,16 +252,16 @@ namespace Microsoft.Plugin.WindowWalker.Components
// 1) There is a weird flashing behavior when trying
// to use ShowWindow for switching tabs in IE
// 2) SetForegroundWindow fails on minimized windows
if (ProcessName.ToLower().Equals("iexplore.exe") || !Minimized)
if (ProcessName.ToUpperInvariant().Equals("IEXPLORE.EXE", StringComparison.Ordinal) || !Minimized)
{
InteropAndHelpers.SetForegroundWindow(Hwnd);
NativeMethods.SetForegroundWindow(Hwnd);
}
else
{
InteropAndHelpers.ShowWindow(Hwnd, InteropAndHelpers.ShowWindowCommands.Restore);
NativeMethods.ShowWindow(Hwnd, NativeMethods.ShowWindowCommands.Restore);
}
InteropAndHelpers.FlashWindow(Hwnd, true);
NativeMethods.FlashWindow(Hwnd, true);
}
/// <summary>
@ -329,7 +270,7 @@ namespace Microsoft.Plugin.WindowWalker.Components
/// <returns>The title of the window</returns>
public override string ToString()
{
return Title + " (" + ProcessName.ToUpper() + ")";
return Title + " (" + ProcessName.ToUpper(CultureInfo.CurrentCulture) + ")";
}
/// <summary>
@ -338,16 +279,16 @@ namespace Microsoft.Plugin.WindowWalker.Components
/// <returns>The state (minimized, maximized, etc..) of the window</returns>
public WindowSizeState GetWindowSizeState()
{
InteropAndHelpers.GetWindowPlacement(Hwnd, out InteropAndHelpers.WINDOWPLACEMENT placement);
NativeMethods.GetWindowPlacement(Hwnd, out NativeMethods.WINDOWPLACEMENT placement);
switch (placement.ShowCmd)
{
case InteropAndHelpers.ShowWindowCommands.Normal:
case NativeMethods.ShowWindowCommands.Normal:
return WindowSizeState.Normal;
case InteropAndHelpers.ShowWindowCommands.Minimize:
case InteropAndHelpers.ShowWindowCommands.ShowMinimized:
case NativeMethods.ShowWindowCommands.Minimize:
case NativeMethods.ShowWindowCommands.ShowMinimized:
return WindowSizeState.Minimized;
case InteropAndHelpers.ShowWindowCommands.Maximize: // No need for ShowMaximized here since its also of value 3
case NativeMethods.ShowWindowCommands.Maximize: // No need for ShowMaximized here since its also of value 3
return WindowSizeState.Maximized;
default:
// throw new Exception("Don't know how to handle window state = " + placement.ShowCmd);
@ -375,10 +316,10 @@ namespace Microsoft.Plugin.WindowWalker.Components
{
uint processId = GetProcessIDFromWindowHandle(hwnd);
ProcessID = processId;
IntPtr processHandle = InteropAndHelpers.OpenProcess(InteropAndHelpers.ProcessAccessFlags.AllAccess, true, (int)processId);
IntPtr processHandle = NativeMethods.OpenProcess(NativeMethods.ProcessAccessFlags.AllAccess, true, (int)processId);
StringBuilder processName = new StringBuilder(MaximumFileNameLength);
if (InteropAndHelpers.GetProcessImageFileName(processHandle, processName, MaximumFileNameLength) != 0)
if (NativeMethods.GetProcessImageFileName(processHandle, processName, MaximumFileNameLength) != 0)
{
return processName.ToString().Split('\\').Reverse().ToArray()[0];
}
@ -393,9 +334,9 @@ namespace Microsoft.Plugin.WindowWalker.Components
/// </summary>
/// <param name="hwnd">The handle to the window</param>
/// <returns>The process ID</returns>
private uint GetProcessIDFromWindowHandle(IntPtr hwnd)
private static uint GetProcessIDFromWindowHandle(IntPtr hwnd)
{
InteropAndHelpers.GetWindowThreadProcessId(hwnd, out uint processId);
_ = NativeMethods.GetWindowThreadProcessId(hwnd, out uint processId);
return processId;
}
}

View File

@ -1,31 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.Plugin.WindowWalker.Components
{
internal class WindowResult : Window
{
/// <summary>
/// Number of letters in between constant for when
/// the result hasn't been set yet
/// </summary>
public const int NoResult = -1;
/// <summary>
/// Gets or sets properties that signify how many characters (including spaces)
/// were found when matching the results
/// </summary>
public int LettersInBetweenScore { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="WindowResult"/> class.
/// Constructor for WindowResult
/// </summary>
public WindowResult(Window window)
: base(window.Hwnd)
{
LettersInBetweenScore = NoResult;
}
}
}

View File

@ -2,6 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Plugin.WindowWalker.Components;
@ -19,14 +20,20 @@ namespace Microsoft.Plugin.WindowWalker
static Main()
{
SearchController.Instance.OnSearchResultUpdate += SearchResultUpdated;
SearchController.Instance.OnSearchResultUpdateEventHandler += SearchResultUpdated;
OpenWindows.Instance.UpdateOpenWindowsList();
}
public List<Result> Query(Query query)
{
SearchController.Instance.UpdateSearchText(query.RawQuery).Wait();
if (query == null)
{
throw new ArgumentNullException(nameof(query));
}
OpenWindows.Instance.UpdateOpenWindowsList();
SearchController.Instance.UpdateSearchText(query.RawQuery).Wait();
return _results.Select(x => new Result()
{
Title = x.Result.Title,

View File

@ -66,6 +66,10 @@
<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2020.1.0" />
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="3.3.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="System.Runtime" Version="4.3.1" />
</ItemGroup>
<ItemGroup>