[Powertoys Run] Implemented "hidden files" flag in native Windows Search (#5500)

* Implemented "hidden files" flag in native Windows Search

* add missing file

* Change InitQueryHelper back to static

* Fix Line Endings

* Add files via github

Co-authored-by: Roy <royvou@hotmailcom>
This commit is contained in:
Roy
2020-08-15 23:11:56 +02:00
committed by GitHub
parent 04c80915e5
commit 55dc5dc19d
3 changed files with 85 additions and 55 deletions

View File

@@ -39,7 +39,7 @@ namespace Microsoft.Plugin.Indexer.SearchHelper
{ {
while (!wDSResults.IsClosed && wDSResults.Read()) while (!wDSResults.IsClosed && wDSResults.Read())
{ {
List<object> fieldData = new List<object>(); List<object> fieldData = new List<object>(wDSResults.FieldCount);
for (int i = 0; i < wDSResults.FieldCount; i++) for (int i = 0; i < wDSResults.FieldCount; i++)
{ {
fieldData.Add(wDSResults.GetValue(i)); fieldData.Add(wDSResults.GetValue(i));

View File

@@ -4,7 +4,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Microsoft.Search.Interop; using Microsoft.Search.Interop;
@@ -54,25 +53,19 @@ namespace Microsoft.Plugin.Indexer.SearchHelper
// Loop over all records from the database // Loop over all records from the database
foreach (OleDBResult oleDBResult in oleDBResults) foreach (OleDBResult oleDBResult in oleDBResults)
{ {
if (oleDBResult.FieldData[0] == DBNull.Value || oleDBResult.FieldData[1] == DBNull.Value || oleDBResult.FieldData[2] == DBNull.Value) if (oleDBResult.FieldData[0] == DBNull.Value || oleDBResult.FieldData[1] == DBNull.Value)
{ {
continue; continue;
} }
uint fileAttributes = (uint)((long)oleDBResult.FieldData[2]); var uri_path = new Uri((string)oleDBResult.FieldData[0]);
bool isFileHidden = (fileAttributes & _fileAttributeHidden) == _fileAttributeHidden; var result = new SearchResult
if (DisplayHiddenFiles || !isFileHidden)
{ {
var uri_path = new Uri((string)oleDBResult.FieldData[0]); Path = uri_path.LocalPath,
var result = new SearchResult Title = (string)oleDBResult.FieldData[1],
{ };
Path = uri_path.LocalPath,
Title = (string)oleDBResult.FieldData[1],
};
results.Add(result); results.Add(result);
}
} }
return results; return results;
@@ -108,7 +101,7 @@ namespace Microsoft.Plugin.Indexer.SearchHelper
} }
} }
public static void InitQueryHelper(out ISearchQueryHelper queryHelper, int maxCount) public static void InitQueryHelper(out ISearchQueryHelper queryHelper, int maxCount, bool displayHiddenFiles)
{ {
// This uses the Microsoft.Search.Interop assembly // This uses the Microsoft.Search.Interop assembly
CSearchManager manager = new CSearchManager(); CSearchManager manager = new CSearchManager();
@@ -128,6 +121,12 @@ namespace Microsoft.Plugin.Indexer.SearchHelper
// Set additional query restriction // Set additional query restriction
queryHelper.QueryWhereRestrictions = "AND scope='file:'"; queryHelper.QueryWhereRestrictions = "AND scope='file:'";
if (!displayHiddenFiles)
{
// https://docs.microsoft.com/en-us/windows/win32/search/all-bitwise
queryHelper.QueryWhereRestrictions += " AND System.FileAttributes <> SOME BITWISE " + _fileAttributeHidden;
}
// To filter based on title for now // To filter based on title for now
queryHelper.QueryContentProperties = "System.FileName"; queryHelper.QueryContentProperties = "System.FileName";
@@ -138,7 +137,7 @@ namespace Microsoft.Plugin.Indexer.SearchHelper
public IEnumerable<SearchResult> Search(string keyword, bool isFullQuery = false, string pattern = "*", int maxCount = 30) public IEnumerable<SearchResult> Search(string keyword, bool isFullQuery = false, string pattern = "*", int maxCount = 30)
{ {
ISearchQueryHelper queryHelper; ISearchQueryHelper queryHelper;
InitQueryHelper(out queryHelper, maxCount); InitQueryHelper(out queryHelper, maxCount, DisplayHiddenFiles);
ModifyQueryHelper(ref queryHelper, pattern); ModifyQueryHelper(ref queryHelper, pattern);
return ExecuteQuery(queryHelper, keyword, isFullQuery); return ExecuteQuery(queryHelper, keyword, isFullQuery);
} }

View File

@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation // Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license. // The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
@@ -34,7 +34,7 @@ namespace Wox.Test.Plugins
ISearchQueryHelper queryHelper = null; ISearchQueryHelper queryHelper = null;
// Act // Act
WindowsSearchAPI.InitQueryHelper(out queryHelper, maxCount); WindowsSearchAPI.InitQueryHelper(out queryHelper, maxCount, api.DisplayHiddenFiles);
// Assert // Assert
Assert.IsNotNull(queryHelper); Assert.IsNotNull(queryHelper);
@@ -48,8 +48,8 @@ namespace Wox.Test.Plugins
ISearchQueryHelper queryHelper; ISearchQueryHelper queryHelper;
string pattern = "*"; string pattern = "*";
WindowsSearchAPI api = GetWindowsSearchAPI(); WindowsSearchAPI api = GetWindowsSearchAPI();
WindowsSearchAPI.InitQueryHelper(out queryHelper, 10); WindowsSearchAPI.InitQueryHelper(out queryHelper, 10, api.DisplayHiddenFiles);
// Act // Act
WindowsSearchAPI.ModifyQueryHelper(ref queryHelper, pattern); WindowsSearchAPI.ModifyQueryHelper(ref queryHelper, pattern);
@@ -65,7 +65,7 @@ namespace Wox.Test.Plugins
ISearchQueryHelper queryHelper; ISearchQueryHelper queryHelper;
string pattern = "tt*^&)"; string pattern = "tt*^&)";
WindowsSearchAPI api = GetWindowsSearchAPI(); WindowsSearchAPI api = GetWindowsSearchAPI();
WindowsSearchAPI.InitQueryHelper(out queryHelper, 10); WindowsSearchAPI.InitQueryHelper(out queryHelper, 10, api.DisplayHiddenFiles);
// Act // Act
WindowsSearchAPI.ModifyQueryHelper(ref queryHelper, pattern); WindowsSearchAPI.ModifyQueryHelper(ref queryHelper, pattern);
@@ -82,7 +82,7 @@ namespace Wox.Test.Plugins
ISearchQueryHelper queryHelper; ISearchQueryHelper queryHelper;
string pattern = "tt%^&)"; string pattern = "tt%^&)";
WindowsSearchAPI api = GetWindowsSearchAPI(); WindowsSearchAPI api = GetWindowsSearchAPI();
WindowsSearchAPI.InitQueryHelper(out queryHelper, 10); WindowsSearchAPI.InitQueryHelper(out queryHelper, 10, api.DisplayHiddenFiles);
// Act // Act
WindowsSearchAPI.ModifyQueryHelper(ref queryHelper, pattern); WindowsSearchAPI.ModifyQueryHelper(ref queryHelper, pattern);
@@ -99,7 +99,7 @@ namespace Wox.Test.Plugins
ISearchQueryHelper queryHelper; ISearchQueryHelper queryHelper;
string pattern = "tt_^&)"; string pattern = "tt_^&)";
WindowsSearchAPI api = GetWindowsSearchAPI(); WindowsSearchAPI api = GetWindowsSearchAPI();
WindowsSearchAPI.InitQueryHelper(out queryHelper, 10); WindowsSearchAPI.InitQueryHelper(out queryHelper, 10, api.DisplayHiddenFiles);
// Act // Act
WindowsSearchAPI.ModifyQueryHelper(ref queryHelper, pattern); WindowsSearchAPI.ModifyQueryHelper(ref queryHelper, pattern);
@@ -116,7 +116,7 @@ namespace Wox.Test.Plugins
ISearchQueryHelper queryHelper; ISearchQueryHelper queryHelper;
string pattern = "tt?^&)"; string pattern = "tt?^&)";
WindowsSearchAPI api = GetWindowsSearchAPI(); WindowsSearchAPI api = GetWindowsSearchAPI();
WindowsSearchAPI.InitQueryHelper(out queryHelper, 10); WindowsSearchAPI.InitQueryHelper(out queryHelper, 10, api.DisplayHiddenFiles);
// Act // Act
WindowsSearchAPI.ModifyQueryHelper(ref queryHelper, pattern); WindowsSearchAPI.ModifyQueryHelper(ref queryHelper, pattern);
@@ -133,7 +133,7 @@ namespace Wox.Test.Plugins
ISearchQueryHelper queryHelper; ISearchQueryHelper queryHelper;
string pattern = "tt^&)bc"; string pattern = "tt^&)bc";
WindowsSearchAPI api = GetWindowsSearchAPI(); WindowsSearchAPI api = GetWindowsSearchAPI();
WindowsSearchAPI.InitQueryHelper(out queryHelper, 10); WindowsSearchAPI.InitQueryHelper(out queryHelper, 10, api.DisplayHiddenFiles);
// Act // Act
WindowsSearchAPI.ModifyQueryHelper(ref queryHelper, pattern); WindowsSearchAPI.ModifyQueryHelper(ref queryHelper, pattern);
@@ -158,11 +158,11 @@ namespace Wox.Test.Plugins
} }
[Test] [Test]
public void WindowsSearchAPI_ShouldShowHiddenFiles_WhenDisplayHiddenFilesIsTrue() public void WindowsSearchAPI_ShouldReturnResults_WhenSearchWasExecuted()
{ {
// Arrange // Arrange
OleDBResult unHiddenFile = new OleDBResult(new List<object>() { "C:/test/path/file1.txt", "file1.txt", 0x0L }); OleDBResult unHiddenFile = new OleDBResult(new List<object>() { "C:/test/path/file1.txt", "file1.txt" });
OleDBResult hiddenFile = new OleDBResult(new List<object>() { "C:/test/path/file2.txt", "file2.txt", 0x2L }); OleDBResult hiddenFile = new OleDBResult(new List<object>() { "C:/test/path/file2.txt", "file2.txt" });
List<OleDBResult> results = new List<OleDBResult>() { hiddenFile, unHiddenFile }; List<OleDBResult> results = new List<OleDBResult>() { hiddenFile, unHiddenFile };
var mock = new Mock<ISearch>(); var mock = new Mock<ISearch>();
mock.Setup(x => x.Query(It.IsAny<string>(), It.IsAny<string>())).Returns(results); mock.Setup(x => x.Query(It.IsAny<string>(), It.IsAny<string>())).Returns(results);
@@ -177,34 +177,13 @@ namespace Wox.Test.Plugins
Assert.IsTrue(windowsSearchAPIResults.Any(x => x.Title == "file2.txt")); Assert.IsTrue(windowsSearchAPIResults.Any(x => x.Title == "file2.txt"));
} }
[Test]
public void WindowsSearchAPI_ShouldNotShowHiddenFiles_WhenDisplayHiddenFilesIsFalse()
{
// Arrange
OleDBResult unHiddenFile = new OleDBResult(new List<object>() { "C:/test/path/file1.txt", "file1.txt", 0x0L });
OleDBResult hiddenFile = new OleDBResult(new List<object>() { "C:/test/path/file2.txt", "file2.txt", 0x2L });
List<OleDBResult> results = new List<OleDBResult>() { hiddenFile, unHiddenFile };
var mock = new Mock<ISearch>();
mock.Setup(x => x.Query(It.IsAny<string>(), It.IsAny<string>())).Returns(results);
WindowsSearchAPI api = new WindowsSearchAPI(mock.Object, false);
// Act
var windowsSearchAPIResults = api.Search("FilePath");
// Assert
Assert.IsTrue(windowsSearchAPIResults.Count() == 1);
Assert.IsTrue(windowsSearchAPIResults.Any(x => x.Title == "file1.txt"));
Assert.IsFalse(windowsSearchAPIResults.Any(x => x.Title == "file2.txt"));
}
[Test] [Test]
public void WindowsSearchAPI_ShouldNotReturnResultsWithNullValue_WhenDbResultHasANullColumn() public void WindowsSearchAPI_ShouldNotReturnResultsWithNullValue_WhenDbResultHasANullColumn()
{ {
// Arrange // Arrange
OleDBResult file1 = new OleDBResult(new List<object>() { "C:/test/path/file1.txt", DBNull.Value, 0x0L }); OleDBResult unHiddenFile = new OleDBResult(new List<object>() { "C:/test/path/file1.txt", DBNull.Value });
OleDBResult file2 = new OleDBResult(new List<object>() { "C:/test/path/file2.txt", "file2.txt", 0x0L }); OleDBResult hiddenFile = new OleDBResult(new List<object>() { "C:/test/path/file2.txt", "file2.txt" });
List<OleDBResult> results = new List<OleDBResult>() { hiddenFile, unHiddenFile };
List<OleDBResult> results = new List<OleDBResult>() { file1, file2 };
var mock = new Mock<ISearch>(); var mock = new Mock<ISearch>();
mock.Setup(x => x.Query(It.IsAny<string>(), It.IsAny<string>())).Returns(results); mock.Setup(x => x.Query(It.IsAny<string>(), It.IsAny<string>())).Returns(results);
WindowsSearchAPI api = new WindowsSearchAPI(mock.Object, false); WindowsSearchAPI api = new WindowsSearchAPI(mock.Object, false);
@@ -218,6 +197,58 @@ namespace Wox.Test.Plugins
Assert.IsTrue(windowsSearchAPIResults.Any(x => x.Title == "file2.txt")); Assert.IsTrue(windowsSearchAPIResults.Any(x => x.Title == "file2.txt"));
} }
[Test]
public void WindowsSearchAPI_ShouldRequestNormalRequest_WhenDisplayHiddenFilesIsTrue()
{
ISearchQueryHelper queryHelper;
String pattern = "notepad";
WindowsSearchAPI _api = GetWindowsSearchAPI();
_api.DisplayHiddenFiles = true;
// Act
WindowsSearchAPI.InitQueryHelper(out queryHelper, 10, _api.DisplayHiddenFiles);
WindowsSearchAPI.ModifyQueryHelper(ref queryHelper, pattern);
// Assert
Assert.IsFalse(queryHelper.QueryWhereRestrictions.Contains("AND System.FileAttributes <> SOME BITWISE 2"));
}
[Test]
public void WindowsSearchAPI_ShouldRequestFilteredRequest_WhenDisplayHiddenFilesIsFalse()
{
ISearchQueryHelper queryHelper;
String pattern = "notepad";
WindowsSearchAPI _api = GetWindowsSearchAPI();
_api.DisplayHiddenFiles = false;
// Act
WindowsSearchAPI.InitQueryHelper(out queryHelper, 10, _api.DisplayHiddenFiles);
WindowsSearchAPI.ModifyQueryHelper(ref queryHelper, pattern);
// Assert
Assert.IsTrue(queryHelper.QueryWhereRestrictions.Contains("AND System.FileAttributes <> SOME BITWISE 2"));
}
[Test]
public void WindowsSearchAPI_ShouldRequestNormalRequest_WhenDisplayHiddenFilesIsTrue_AfterRuntimeSwap()
{
ISearchQueryHelper queryHelper;
String pattern = "notepad";
WindowsSearchAPI _api = GetWindowsSearchAPI();
_api.DisplayHiddenFiles = false;
// Act
WindowsSearchAPI.InitQueryHelper(out queryHelper, 10, _api.DisplayHiddenFiles);
WindowsSearchAPI.ModifyQueryHelper(ref queryHelper, pattern);
_api.DisplayHiddenFiles = true;
WindowsSearchAPI.InitQueryHelper(out queryHelper, 10, _api.DisplayHiddenFiles);
WindowsSearchAPI.ModifyQueryHelper(ref queryHelper, pattern);
// Assert
Assert.IsFalse(queryHelper.QueryWhereRestrictions.Contains("AND System.FileAttributes <> SOME BITWISE 2"));
}
[TestCase("item.exe")] [TestCase("item.exe")]
[TestCase("item.bat")] [TestCase("item.bat")]
[TestCase("item.appref-ms")] [TestCase("item.appref-ms")]
@@ -379,8 +410,8 @@ namespace Wox.Test.Plugins
public void WindowsSearchAPI_ShouldReturnEmptyResults_WhenIsFullQueryIsTrueAndTheQueryDoesNotRequireLIKESyntax() public void WindowsSearchAPI_ShouldReturnEmptyResults_WhenIsFullQueryIsTrueAndTheQueryDoesNotRequireLIKESyntax()
{ {
// Arrange // Arrange
OleDBResult file1 = new OleDBResult(new List<object>() { "C:/test/path/file1.txt", DBNull.Value, (Int64)0x0 }); OleDBResult file1 = new OleDBResult(new List<object>() { "C:/test/path/file1.txt", DBNull.Value });
OleDBResult file2 = new OleDBResult(new List<object>() { "C:/test/path/file2.txt", "file2.txt", (Int64)0x0 }); OleDBResult file2 = new OleDBResult(new List<object>() { "C:/test/path/file2.txt", "file2.txt" });
List<OleDBResult> results = new List<OleDBResult>() { file1, file2 }; List<OleDBResult> results = new List<OleDBResult>() { file1, file2 };
var mock = new Mock<ISearch>(); var mock = new Mock<ISearch>();