OSDN Git Service

AppliStation-GUI,「インストー先のフォルダー」の表示で直前に選択していたパッケージのファイルが表示されることがある不具合を修正
[applistation/AppliStation.git] / AppliStation / AppliStation.Util / ToolStripPetitLauncherMenuItem.cs
1 using System;\r
2 using System.Threading;\r
3 using System.IO;\r
4 using System.Drawing;\r
5 using System.Windows.Forms;\r
6 using System.Diagnostics;\r
7 using System.Text;\r
8 \r
9 using System.ComponentModel;\r
10 \r
11 namespace AppliStation.Util\r
12 {\r
13         public class ToolStripPetitLauncherMenuItem : ToolStripMenuItem\r
14         {\r
15                 private Thread thread;\r
16                 \r
17                 private string baseFolderPath;\r
18                 \r
19                 private Form invokerForm;\r
20                 \r
21                 /// <summary>\r
22                 /// 親フォルダー\r
23                 /// </summary>\r
24                 [ReadOnly(true)]\r
25                 public string BaseFolderPath {\r
26                         get { return baseFolderPath; }\r
27                         set {\r
28                                 baseFolderPath = value;\r
29                                 BuildItems();\r
30                         }\r
31                 }\r
32                 \r
33                 /// <summary>\r
34                 /// 別スレッドからInvokeするときのオブジェクト\r
35                 /// </summary>\r
36                 public Form InvokerForm {\r
37                         get { return invokerForm; }\r
38                         set { invokerForm = value; }\r
39                 }\r
40                 \r
41                 /// <summary>\r
42                 /// ドロップアイテムの(再)生成を行う\r
43                 /// </summary>\r
44                 public void BuildItems()\r
45                 {\r
46                         if (thread != null) {\r
47                                 if (! thread.Join(500)) {\r
48                                         thread.Interrupt();\r
49                                 }\r
50                                 thread = null;\r
51                         }\r
52                         \r
53                         if (Directory.Exists(baseFolderPath)) {\r
54                                 thread = new Thread(new ThreadStart(buildItems));\r
55                                 thread.Start();\r
56                         }\r
57                 }\r
58                 \r
59                 #region スレッド処理\r
60                 \r
61                 private delegate int ToolStripItemCollection_AddDelegate(ToolStripItem item);\r
62                 private void _addToItemsInv(ToolStripItem item)\r
63                 {\r
64                         if (InvokerForm.InvokeRequired) {\r
65                                 InvokerForm.Invoke(new ToolStripItemCollection_AddDelegate(DropDownItems.Add), item);\r
66                         } else {\r
67                                 DropDownItems.Add(item);\r
68                         }\r
69                 }\r
70                 private delegate void ToolStripItemCollection_InsertDelegate(int index, ToolStripItem item);\r
71                 private void _insertToItemsInv(int index, ToolStripItem item)\r
72                 {\r
73                         if (InvokerForm.InvokeRequired) {\r
74                                 InvokerForm.Invoke(new ToolStripItemCollection_InsertDelegate(DropDownItems.Insert), index, item);\r
75                         } else {\r
76                                 DropDownItems.Insert(index, item);\r
77                         }\r
78                 }\r
79                 \r
80                 private void _insertItemFor(string filepath, ref bool cmdIsAdded, string basedir)\r
81                 {\r
82                         string extension = Path.GetExtension(filepath).ToLower();\r
83                         \r
84                         string dirname = Path.GetDirectoryName(filepath);\r
85                         string itemtext = NaGet.Utils.GetRelativePath(basedir, filepath);\r
86 #if DEBUG\r
87 Debug.Assert(! itemtext.Contains(".."), string.Format("{2} -- base:{0}, dirname:{1}", basedir, dirname, itemtext));\r
88 #endif\r
89                         \r
90                         if (extension == ".exe") {\r
91                                 switch (NaGet.InteropServices.PEFileInfoUtils.GetPEFileType(filepath)) {\r
92                                         case NaGet.InteropServices.PEFileType.WinGUI:\r
93                                                 _addToItemsInv(CreateMenuItemForFile(filepath, itemtext));\r
94                                                 break;\r
95                                         case NaGet.InteropServices.PEFileType.WinConsole:\r
96                                         case NaGet.InteropServices.PEFileType.MSDosCom:\r
97                                                 if (! cmdIsAdded) {\r
98                                                         _insertToItemsInv(0, CreateMenuItemForCmdAt(basedir));\r
99                                                         cmdIsAdded = true;\r
100                                                 }\r
101                                                 break;\r
102                                 }\r
103                         } else if ((extension == ".bat") || (extension == ".lnk")) {\r
104                                 _addToItemsInv(CreateMenuItemForFile(filepath, itemtext));\r
105                         }\r
106                 }\r
107                 \r
108                         \r
109                 private void buildItems()\r
110                 {\r
111                         DropDownItems.Clear();\r
112                         \r
113                         try {\r
114                                 string folderPath = Path.GetFullPath(baseFolderPath);\r
115                                 ToolStripSeparator sep = new ToolStripSeparator();\r
116                                 bool cmdIsAdded = false;\r
117                                 \r
118                                 _addToItemsInv(CreateMenuItemForFolder(folderPath));\r
119                                 _addToItemsInv(sep);\r
120                                 \r
121                                 if (Directory.Exists(folderPath)) {                                     \r
122                                         foreach (string filepath in Directory.GetFiles(folderPath)) {\r
123                                                 if (baseFolderPath != folderPath) return; // 途中でなんか操作されているならば終了\r
124                                                 \r
125                                                 _insertItemFor(filepath, ref cmdIsAdded, folderPath);\r
126                                         }\r
127                                         \r
128                                         string bindir = Path.Combine(folderPath, "bin");\r
129                                         if (Directory.Exists(bindir)) {\r
130                                                 foreach (string filepath in Directory.GetFiles(bindir)) {\r
131                                                         if (baseFolderPath != folderPath) return; // 途中でなんか操作されているならば終了\r
132                                                         \r
133                                                         _insertItemFor(filepath, ref cmdIsAdded, folderPath);\r
134                                                 }\r
135                                         }\r
136                                 }\r
137                         } catch (ThreadInterruptedException) {}\r
138                 }\r
139                 \r
140                 #endregion\r
141                 \r
142                 /// <summary>\r
143                 /// 与えられたフォルダーを開くメニューアイテムを生成する\r
144                 /// </summary>\r
145                 /// <param name="folderPath"></param>\r
146                 /// <returns></returns>\r
147                 private static ToolStripMenuItem CreateMenuItemForFolder(string folderPath)\r
148                 {\r
149                         ToolStripMenuItem item = CreateMenuItemForFile(folderPath, "フォルダーを開く(&O)");\r
150                         item.Image = GUIUtils.ShellIconForFolder.ToBitmap();\r
151                         item.ShowShortcutKeys = true;\r
152                         return item;\r
153                 }\r
154 \r
155                 /// <summary>\r
156                 /// 与えられたファイルのランチャーに相当するメニューアイテムを生成する\r
157                 /// </summary>\r
158                 /// <param name="filePath">ファイルパス</param>\r
159                 /// <returns>生成されたメニューアイテム</returns>\r
160                 private static ToolStripMenuItem CreateMenuItemForFile(string filePath, string text)\r
161                 {\r
162                         ToolStripMenuItem item = new ToolStripMenuItem();\r
163                         \r
164                         item.Text = text;\r
165                         item.ShowShortcutKeys = false;\r
166                         item.Tag = filePath;\r
167                         item.Click += new System.EventHandler(menuItemForFileClicked);\r
168                         \r
169                         if (File.Exists(filePath)) {\r
170                                 item.Image = Icon.ExtractAssociatedIcon(filePath).ToBitmap();\r
171                                 \r
172                                 StringBuilder sb = new StringBuilder();\r
173                                 sb.AppendFormat("場所: {0}", Path.GetDirectoryName(filePath));\r
174                                 if (File.Exists(filePath)) {\r
175                                         FileVersionInfo vInfo = FileVersionInfo.GetVersionInfo(filePath);\r
176                                         \r
177                                         if (! string.IsNullOrEmpty(vInfo.FileDescription))\r
178                                                 sb.AppendFormat("\r\nファイルの説明: {0}", vInfo.FileDescription);\r
179                                         if (! string.IsNullOrEmpty(vInfo.CompanyName))\r
180                                                 sb.AppendFormat("\r\n会社: {0}", vInfo.CompanyName);\r
181                                         if (! string.IsNullOrEmpty(vInfo.FileVersion))\r
182                                                 sb.AppendFormat("\r\nファイルバージョン: {0}", vInfo.FileVersion);\r
183                                 }\r
184                                 item.ToolTipText = sb.ToString();\r
185                         } else {\r
186                                 item.ToolTipText = filePath;\r
187                         }\r
188                         \r
189                         return item;\r
190                 }\r
191                 \r
192                 /// <summary>\r
193                 /// <see cref="CreateMenuItemForFile" />により使われるイベントハンドラ\r
194                 /// </summary>\r
195                 /// <param name="sender"></param>\r
196                 /// <param name="e"></param>\r
197                 private static void menuItemForFileClicked(object sender, EventArgs e)\r
198                 {\r
199                         ToolStripMenuItem item = (ToolStripMenuItem) sender;\r
200                         \r
201                         ProcessStartInfo procInfo = new ProcessStartInfo(item.Tag.ToString());\r
202                         procInfo.WorkingDirectory = Path.GetDirectoryName(procInfo.FileName);\r
203                         try {\r
204                                 Process.Start(procInfo);\r
205                         } catch (Win32Exception ex) {\r
206                                 MessageBox.Show(ex.Message, procInfo.FileName, MessageBoxButtons.OK, MessageBoxIcon.Error);\r
207                         }\r
208                 }\r
209                 \r
210                 /// <summary>\r
211                 /// 与えられたフォルダーのところでコマンドプロンプトを開く。\r
212                 /// </summary>\r
213                 /// <param name="folderPath">カレントフォルダー及びパスに追加されるフォルダー</param>\r
214                 /// <returns>生成されたメニューアイテム</returns>\r
215                 private static ToolStripMenuItem CreateMenuItemForCmdAt(string folderPath)\r
216                 {\r
217                         string cmdPath = Environment.GetEnvironmentVariable("comspec");\r
218                         if (string.IsNullOrEmpty(cmdPath) || (!File.Exists(cmdPath)))\r
219                                 throw new FileNotFoundException(null, Environment.ExpandEnvironmentVariables("%comspec%"));\r
220                         \r
221                         ToolStripMenuItem item = new ToolStripMenuItem();\r
222                         \r
223                         item.Text = string.Format("この場所で{0}を開く(&C)", (cmdPath.EndsWith(@"\command.com"))? "MS-DOSプロンプト" : "コマンドプロンプト");\r
224                         item.Tag = folderPath;\r
225                         item.Click += new System.EventHandler(menuItemForCmdAtClicked);\r
226                         try {\r
227                                 item.Image = Icon.ExtractAssociatedIcon(cmdPath).ToBitmap();\r
228                         } catch (Exception) {}\r
229                         \r
230                         return item;\r
231                 }\r
232                 \r
233                 /// <summary>\r
234                 /// <see cref="CreateMenuItemForCmdAt" />により使われるイベントハンドラ\r
235                 /// </summary>\r
236                 /// <param name="sender"></param>\r
237                 /// <param name="e"></param>\r
238                 private static void menuItemForCmdAtClicked(object sender, EventArgs e)\r
239                 {\r
240                         ToolStripMenuItem item = (ToolStripMenuItem) sender;\r
241                         string cmdPath = Environment.GetEnvironmentVariable("comspec");\r
242                         \r
243                         ProcessStartInfo procInfo = new ProcessStartInfo(cmdPath);\r
244                         procInfo.UseShellExecute = false;\r
245                         procInfo.WorkingDirectory = item.Tag.ToString();\r
246                         procInfo.EnvironmentVariables["PATH"] = Environment.GetEnvironmentVariable("path")\r
247                                 + Path.PathSeparator + item.Tag.ToString();\r
248                         Process.Start(procInfo);\r
249                 }\r
250         }\r
251 }\r