Skip to content

Instantly share code, notes, and snippets.

@earlgreyxxx
Last active February 28, 2021 14:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save earlgreyxxx/270f1d6bcb2039ed0b1cf88e90b4693f to your computer and use it in GitHub Desktop.
Save earlgreyxxx/270f1d6bcb2039ed0b1cf88e90b4693f to your computer and use it in GitHub Desktop.
/*************************************************************************
*
* プログラムに複数のファイルを渡すショートカットメニューハンドラ
* Windows Explorerのシェルエクステンション(COMサーバー)
*
* SharpShellを使用したシェルエクステンション
* base library : https://github.com/dwmkerr/sharpshell
*
* tutorial: https://www.codeproject.com/Articles/512956/NET-Shell-Extensions-Shell-Context-Menus
* -----------------------------------------
* build: Visual Studio 2019 Community
* nugetパッケージ管理にて SharpShell インストール必須
*
* install: ServerManger from https://github.com/dwmkerr/sharpshell/releases
* nugetパッケージ管理のSharpShell Toolsはバージョンが古い?ので正常に動かなかった。
* githubで配布されているものを使う。
*
* -----------------------------------------
* 設定ファイル: %LOCALAPPDATA%\.mssm
* このシェルエクステンションで使用する設定ファイル。
* どのプログラムをどういうパラメータで起動するか、メニューのラベル名を設定
* 無ければ自動的に作成する。
*
*************************************************************************/
using System;
using System.IO;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using SharpShell.Attributes;
using SharpShell.SharpContextMenu;
namespace jp.ptsv.shellext
{
[ComVisible(true)]
[COMServerAssociation(AssociationType.AllFiles)]
public class MultiSelectedShortcutMenu : SharpContextMenu
{
private MySetting Setting = new MySetting(Environment.ExpandEnvironmentVariables(Path.Combine("%LOCALAPPDATA%", ".mssm")));
protected override bool CanShowMenu()
{
return SelectedItemPaths.Where(c => File.Exists(c)).Count() == 2;
}
protected override ContextMenuStrip CreateMenu()
{
var contextMenuStrip = new ContextMenuStrip();
var miSeparator = new ToolStripSeparator();
var miDiff = new ToolStripMenuItem();
miDiff.Text = Setting.Get("label") ?? TEXT.DEFAULT_LABEL;
miDiff.Click += (sender,e) => miDiff_onClick();
contextMenuStrip.Items.Add(miSeparator);
contextMenuStrip.Items.Add(miDiff);
return contextMenuStrip;
}
private void miDiff_onClick()
{
var pathes = SelectedItemPaths.Select((v) => string.Format("\"{0}\"", v)).ToArray();
try
{
if (pathes.Length != 2)
throw new Exception(TEXT.ERROR_ARGUMENTS);
var argument = string.Format(Setting.Get("parameter") ?? TEXT.DEFAULT_PARAMETER, pathes);
using (var proc = Process.Start(Setting.Get("command") ?? TEXT.DEFAULT_COMMAND, argument))
{
proc.Close();
}
}
catch (Exception exception)
{
MessageBox.Show(exception.Message, TEXT.ERROR_DLG_TITLE);
}
}
}
public class TEXT
{
public static string DEFAULT_LABEL = "差分";
public static string DEFAULT_COMMAND = "gvim.exe";
public static string DEFAULT_PARAMETER = "-d {0} {1}";
public static string ERROR_DLG_TITLE = "エラー";
public static string ERROR_ARGUMENTS = "選択されたファイル数が2つである必要があります。";
public static string ERROR_FILE_NOT_FOUND = "指定したファイルがありません。";
}
public class MySetting : Dictionary<string,string>
{
protected string SettingFilePath;
public MySetting(string filePath) : base()
{
SettingFilePath = filePath;
if (!File.Exists(filePath))
Create();
Load();
}
public string Get(string key)
{
string rv = null;
if(ContainsKey(key))
rv = this[key];
return rv;
}
private void Load()
{
using (var sr = new StreamReader(SettingFilePath))
{
while (sr.Peek() > -1)
{
string buf = sr.ReadLine();
string[] temp = buf.Split(new char[] { '=' }, 2);
if (temp.Length == 2)
this[temp[0].Trim()] = temp[1].Trim();
}
}
}
private void Create()
{
using (var sw = new StreamWriter(SettingFilePath))
{
sw.WriteLine("label={0}", TEXT.DEFAULT_LABEL);
sw.WriteLine("command={0}", TEXT.DEFAULT_COMMAND);
sw.WriteLine("parameter={0}", TEXT.DEFAULT_PARAMETER);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment