2020-08-17 10:00:56 -07:00
// 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.
using System ;
using System.Collections.Generic ;
using System.Diagnostics ;
using System.IO ;
using System.Reflection ;
using System.Threading.Tasks ;
using System.Windows ;
using System.Windows.Input ;
using Microsoft.Plugin.Indexer.SearchHelper ;
using Wox.Infrastructure ;
using Wox.Infrastructure.Logger ;
using Wox.Plugin ;
namespace Microsoft.Plugin.Indexer
{
internal class ContextMenuLoader : IContextMenu
{
private readonly PluginInitContext _context ;
public enum ResultType
{
Folder ,
File ,
}
// Extensions for adding run as admin context menu item for applications
private readonly string [ ] appExtensions = { ".exe" , ".bat" , ".appref-ms" , ".lnk" } ;
public ContextMenuLoader ( PluginInitContext context )
{
_context = context ;
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "We want to keep the process alive, and instead log and show an error message")]
public List < ContextMenuResult > LoadContextMenus ( Result selectedResult )
{
var contextMenus = new List < ContextMenuResult > ( ) ;
if ( selectedResult . ContextData is SearchResult record )
{
ResultType type = Path . HasExtension ( record . Path ) ? ResultType . File : ResultType . Folder ;
if ( type = = ResultType . File )
{
contextMenus . Add ( CreateOpenContainingFolderResult ( record ) ) ;
}
// Test to check if File can be Run as admin, if yes, we add a 'run as admin' context menu item
if ( CanFileBeRunAsAdmin ( record . Path ) )
{
contextMenus . Add ( CreateRunAsAdminContextMenu ( record ) ) ;
}
contextMenus . Add ( new ContextMenuResult
{
PluginName = Assembly . GetExecutingAssembly ( ) . GetName ( ) . Name ,
2020-09-02 15:24:59 -07:00
Title = Properties . Resources . Microsoft_plugin_indexer_copy_path ,
2020-08-17 10:00:56 -07:00
Glyph = "\xE8C8" ,
FontFamily = "Segoe MDL2 Assets" ,
AcceleratorKey = Key . C ,
AcceleratorModifiers = ModifierKeys . Control ,
Action = ( context ) = >
{
try
{
Clipboard . SetText ( record . Path ) ;
return true ;
}
catch ( Exception e )
{
2020-09-08 11:51:24 -07:00
var message = Properties . Resources . Microsoft_plugin_indexer_clipboard_failed ;
2020-09-23 16:32:06 -07:00
Log . Exception ( message , e , GetType ( ) ) ;
2020-08-17 10:00:56 -07:00
_context . API . ShowMsg ( message ) ;
return false ;
}
} ,
} ) ;
contextMenus . Add ( new ContextMenuResult
{
PluginName = Assembly . GetExecutingAssembly ( ) . GetName ( ) . Name ,
2020-09-02 15:24:59 -07:00
Title = Properties . Resources . Microsoft_plugin_indexer_open_in_console ,
2020-08-17 10:00:56 -07:00
Glyph = "\xE756" ,
FontFamily = "Segoe MDL2 Assets" ,
AcceleratorKey = Key . C ,
AcceleratorModifiers = ModifierKeys . Control | ModifierKeys . Shift ,
Action = ( context ) = >
{
try
{
if ( type = = ResultType . File )
{
Helper . OpenInConsole ( Path . GetDirectoryName ( record . Path ) ) ;
}
else
{
Helper . OpenInConsole ( record . Path ) ;
}
return true ;
}
catch ( Exception e )
{
2020-09-23 16:32:06 -07:00
Log . Exception ( $"Failed to open {record.Path} in console, {e.Message}" , e , GetType ( ) ) ;
2020-08-17 10:00:56 -07:00
return false ;
}
} ,
} ) ;
}
return contextMenus ;
}
// Function to add the context menu item to run as admin
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "We want to keep the process alive, and instead log the exeption message")]
2020-09-02 15:24:59 -07:00
private static ContextMenuResult CreateRunAsAdminContextMenu ( SearchResult record )
2020-08-17 10:00:56 -07:00
{
return new ContextMenuResult
{
PluginName = Assembly . GetExecutingAssembly ( ) . GetName ( ) . Name ,
2020-09-02 15:24:59 -07:00
Title = Properties . Resources . Microsoft_plugin_indexer_run_as_administrator ,
2020-08-17 10:00:56 -07:00
Glyph = "\xE7EF" ,
FontFamily = "Segoe MDL2 Assets" ,
AcceleratorKey = Key . Enter ,
AcceleratorModifiers = ModifierKeys . Control | ModifierKeys . Shift ,
Action = _ = >
{
try
{
Task . Run ( ( ) = > Helper . RunAsAdmin ( record . Path ) ) ;
return true ;
}
catch ( Exception e )
{
2020-09-23 16:32:06 -07:00
Log . Exception ( $"Failed to run {record.Path} as admin, {e.Message}" , e , MethodBase . GetCurrentMethod ( ) . DeclaringType ) ;
2020-08-17 10:00:56 -07:00
return false ;
}
} ,
} ;
}
// Function to test if the file can be run as admin
private bool CanFileBeRunAsAdmin ( string path )
{
string fileExtension = Path . GetExtension ( path ) ;
foreach ( string extension in appExtensions )
{
if ( extension . Equals ( fileExtension , StringComparison . OrdinalIgnoreCase ) )
{
return true ;
}
}
return false ;
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "We want to keep the process alive, and instead log and show an error message")]
private ContextMenuResult CreateOpenContainingFolderResult ( SearchResult record )
{
return new ContextMenuResult
{
PluginName = Assembly . GetExecutingAssembly ( ) . GetName ( ) . Name ,
2020-09-02 15:24:59 -07:00
Title = Properties . Resources . Microsoft_plugin_indexer_open_containing_folder ,
2020-08-17 10:00:56 -07:00
Glyph = "\xE838" ,
FontFamily = "Segoe MDL2 Assets" ,
AcceleratorKey = Key . E ,
AcceleratorModifiers = ModifierKeys . Control | ModifierKeys . Shift ,
Action = _ = >
{
try
{
Process . Start ( "explorer.exe" , $" /select,\" { record . Path } \ "" ) ;
}
catch ( Exception e )
{
2020-09-08 11:51:24 -07:00
var message = $"{Properties.Resources.Microsoft_plugin_indexer_folder_open_failed} {record.Path}" ;
2020-09-23 16:32:06 -07:00
Log . Exception ( message , e , GetType ( ) ) ;
2020-08-17 10:00:56 -07:00
_context . API . ShowMsg ( message ) ;
return false ;
}
return true ;
} ,
} ;
}
}
}