using System;
using System.Threading;
using System.IO;
using System.Drawing;
using System.Windows.Forms;
using System.Diagnostics;
using System.Text;
using System.ComponentModel;
namespace AppliStation.Util
{
public class ToolStripPetitLauncherMenuItem : ToolStripMenuItem
{
private Thread thread;
private string baseFolderPath;
private Form invokerForm;
///
/// 親フォルダー
///
[ReadOnly(true)]
public string BaseFolderPath {
get { return baseFolderPath; }
set {
baseFolderPath = value;
BuildItems();
}
}
///
/// 別スレッドからInvokeするときのオブジェクト
///
public Form InvokerForm {
get { return invokerForm; }
set { invokerForm = value; }
}
///
/// ドロップアイテムの(再)生成を行う
///
public void BuildItems()
{
if (thread != null) {
if (! thread.Join(500)) {
thread.Interrupt();
}
thread = null;
}
if (Directory.Exists(baseFolderPath)) {
thread = new Thread(new ThreadStart(buildItems));
thread.Start();
}
}
#region スレッド処理
private delegate int ToolStripItemCollection_AddDelegate(ToolStripItem item);
private void _addToItemsInv(ToolStripItem item)
{
if (InvokerForm.InvokeRequired) {
InvokerForm.Invoke(new ToolStripItemCollection_AddDelegate(DropDownItems.Add), item);
} else {
DropDownItems.Add(item);
}
}
private delegate void ToolStripItemCollection_InsertDelegate(int index, ToolStripItem item);
private void _insertToItemsInv(int index, ToolStripItem item)
{
if (InvokerForm.InvokeRequired) {
InvokerForm.Invoke(new ToolStripItemCollection_InsertDelegate(DropDownItems.Insert), index, item);
} else {
DropDownItems.Insert(index, item);
}
}
private void _insertItemFor(string filepath, ref bool cmdIsAdded, string basedir)
{
string extension = Path.GetExtension(filepath).ToLower();
string dirname = Path.GetDirectoryName(filepath);
string itemtext = NaGet.Utils.GetRelativePath(basedir, filepath);
#if DEBUG
Debug.Assert(! itemtext.Contains(".."), string.Format("{2} -- base:{0}, dirname:{1}", basedir, dirname, itemtext));
#endif
if (extension == ".exe") {
switch (NaGet.InteropServices.PEFileInfoUtils.GetPEFileType(filepath)) {
case NaGet.InteropServices.PEFileType.WinGUI:
_addToItemsInv(CreateMenuItemForFile(filepath, itemtext));
break;
case NaGet.InteropServices.PEFileType.WinConsole:
case NaGet.InteropServices.PEFileType.MSDosCom:
if (! cmdIsAdded) {
_insertToItemsInv(0, CreateMenuItemForCmdAt(basedir));
cmdIsAdded = true;
}
break;
}
} else if ((extension == ".bat") || (extension == ".lnk")) {
_addToItemsInv(CreateMenuItemForFile(filepath, itemtext));
}
}
private void buildItems()
{
DropDownItems.Clear();
try {
string folderPath = Path.GetFullPath(baseFolderPath);
ToolStripSeparator sep = new ToolStripSeparator();
bool cmdIsAdded = false;
_addToItemsInv(CreateMenuItemForFolder(folderPath));
_addToItemsInv(sep);
if (Directory.Exists(folderPath)) {
foreach (string filepath in Directory.GetFiles(folderPath)) {
if (baseFolderPath != folderPath) return; // 途中でなんか操作されているならば終了
_insertItemFor(filepath, ref cmdIsAdded, folderPath);
}
string bindir = Path.Combine(folderPath, "bin");
if (Directory.Exists(bindir)) {
foreach (string filepath in Directory.GetFiles(bindir)) {
if (baseFolderPath != folderPath) return; // 途中でなんか操作されているならば終了
_insertItemFor(filepath, ref cmdIsAdded, folderPath);
}
}
}
} catch (ThreadInterruptedException) {}
}
#endregion
///
/// 与えられたフォルダーを開くメニューアイテムを生成する
///
///
///
private static ToolStripMenuItem CreateMenuItemForFolder(string folderPath)
{
ToolStripMenuItem item = CreateMenuItemForFile(folderPath, "フォルダーを開く(&O)");
item.Image = GUIUtils.ShellIconForFolder.ToBitmap();
item.ShowShortcutKeys = true;
return item;
}
///
/// 与えられたファイルのランチャーに相当するメニューアイテムを生成する
///
/// ファイルパス
/// 生成されたメニューアイテム
private static ToolStripMenuItem CreateMenuItemForFile(string filePath, string text)
{
ToolStripMenuItem item = new ToolStripMenuItem();
item.Text = text;
item.ShowShortcutKeys = false;
item.Tag = filePath;
item.Click += new System.EventHandler(menuItemForFileClicked);
if (File.Exists(filePath)) {
item.Image = Icon.ExtractAssociatedIcon(filePath).ToBitmap();
StringBuilder sb = new StringBuilder();
sb.AppendFormat("場所: {0}", Path.GetDirectoryName(filePath));
if (File.Exists(filePath)) {
FileVersionInfo vInfo = FileVersionInfo.GetVersionInfo(filePath);
if (! string.IsNullOrEmpty(vInfo.FileDescription))
sb.AppendFormat("\r\nファイルの説明: {0}", vInfo.FileDescription);
if (! string.IsNullOrEmpty(vInfo.CompanyName))
sb.AppendFormat("\r\n会社: {0}", vInfo.CompanyName);
if (! string.IsNullOrEmpty(vInfo.FileVersion))
sb.AppendFormat("\r\nファイルバージョン: {0}", vInfo.FileVersion);
}
item.ToolTipText = sb.ToString();
} else {
item.ToolTipText = filePath;
}
return item;
}
///
/// により使われるイベントハンドラ
///
///
///
private static void menuItemForFileClicked(object sender, EventArgs e)
{
ToolStripMenuItem item = (ToolStripMenuItem) sender;
ProcessStartInfo procInfo = new ProcessStartInfo(item.Tag.ToString());
procInfo.WorkingDirectory = Path.GetDirectoryName(procInfo.FileName);
try {
Process.Start(procInfo);
} catch (Win32Exception ex) {
MessageBox.Show(ex.Message, procInfo.FileName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
///
/// 与えられたフォルダーのところでコマンドプロンプトを開く。
///
/// カレントフォルダー及びパスに追加されるフォルダー
/// 生成されたメニューアイテム
private static ToolStripMenuItem CreateMenuItemForCmdAt(string folderPath)
{
string cmdPath = Environment.GetEnvironmentVariable("comspec");
if (string.IsNullOrEmpty(cmdPath) || (!File.Exists(cmdPath)))
throw new FileNotFoundException(null, Environment.ExpandEnvironmentVariables("%comspec%"));
ToolStripMenuItem item = new ToolStripMenuItem();
item.Text = string.Format("この場所で{0}を開く(&C)", (cmdPath.EndsWith(@"\command.com"))? "MS-DOSプロンプト" : "コマンドプロンプト");
item.Tag = folderPath;
item.Click += new System.EventHandler(menuItemForCmdAtClicked);
try {
item.Image = Icon.ExtractAssociatedIcon(cmdPath).ToBitmap();
} catch (Exception) {}
return item;
}
///
/// により使われるイベントハンドラ
///
///
///
private static void menuItemForCmdAtClicked(object sender, EventArgs e)
{
ToolStripMenuItem item = (ToolStripMenuItem) sender;
string cmdPath = Environment.GetEnvironmentVariable("comspec");
ProcessStartInfo procInfo = new ProcessStartInfo(cmdPath);
procInfo.UseShellExecute = false;
procInfo.WorkingDirectory = item.Tag.ToString();
procInfo.EnvironmentVariables["PATH"] = Environment.GetEnvironmentVariable("path")
+ Path.PathSeparator + item.Tag.ToString();
Process.Start(procInfo);
}
}
}