1 // OpenTween - Client of Twitter
2 // Copyright (c) 2007-2012 kiri_feather (@kiri_feather) <kiri.feather@gmail.com>
3 // (c) 2008-2012 Moz (@syo68k)
4 // (c) 2008-2012 takeshik (@takeshik) <http://www.takeshik.org/>
5 // (c) 2010-2012 anis774 (@anis774) <http://d.hatena.ne.jp/anis774/>
6 // (c) 2010-2012 fantasticswallow (@f_swallow) <http://twitter.com/f_swallow>
7 // (c) 2012 Egtra (@egtra) <http://dev.activebasic.com/egtra/>
8 // (c) 2012 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
9 // All rights reserved.
11 // This file is part of OpenTween.
13 // This program is free software; you can redistribute it and/or modify it
14 // under the terms of the GNU General public License as published by the Free
15 // Software Foundation; either version 3 of the License, or (at your option)
18 // This program is distributed in the hope that it will be useful, but
19 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General public License
23 // You should have received a copy of the GNU General public License along
24 // with this program. If not, see <http://www.gnu.org/licenses/>, or write to
25 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
26 // Boston, MA 02110-1301, USA.
29 using System.Collections.Generic;
32 using System.Diagnostics;
33 using System.Windows.Forms;
34 using System.Text.RegularExpressions;
35 using System.Threading;
36 using System.Threading.Tasks;
37 using System.Globalization;
38 using System.Reflection;
39 using Microsoft.Win32;
43 internal class MyApplication
46 /// 起動時に指定されたオプションを取得します
48 public static IDictionary<string, string> StartupOptions { get; private set; }
51 /// アプリケーションのメイン エントリ ポイントです。
54 static int Main(string[] args)
56 if (!CheckRuntimeVersion())
58 var message = string.Format(Properties.Resources.CheckRuntimeVersion_Error, ".NET Framework 4.5.1");
59 MessageBox.Show(message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
63 StartupOptions = ParseArguments(args);
65 if (!SetConfigDirectoryPath())
70 // 同じ設定ファイルを使用する OpenTween プロセスの二重起動を防止する
71 string pt = MyCommon.settingPath.Replace("\\", "/") + "/" + Application.ProductName;
72 using (Mutex mt = new Mutex(false, pt))
74 if (!mt.WaitOne(0, false))
76 var text = string.Format(MyCommon.ReplaceAppName(Properties.Resources.StartupText1), MyCommon.GetAssemblyName());
77 MessageBox.Show(text, MyCommon.ReplaceAppName(Properties.Resources.StartupText2), MessageBoxButtons.OK, MessageBoxIcon.Information);
79 TryActivatePreviousWindow();
83 TaskScheduler.UnobservedTaskException += (s, e) =>
86 OnUnhandledException(e.Exception.Flatten());
88 Application.ThreadException += (s, e) => OnUnhandledException(e.Exception);
89 AppDomain.CurrentDomain.UnhandledException += (s, e) => OnUnhandledException((Exception)e.ExceptionObject);
91 Application.EnableVisualStyles();
92 Application.SetCompatibleTextRenderingDefault(false);
93 Application.Run(new TweenMain());
102 /// 動作中の .NET Framework のバージョンが適切かチェックします
104 private static bool CheckRuntimeVersion()
106 // Mono 上で動作している場合はバージョンチェックを無視します
107 if (Type.GetType("Mono.Runtime", false) != null)
110 // .NET Framework 4.5.1 以降で動作しているかチェックする
111 // 参照: http://msdn.microsoft.com/en-us/library/hh925568%28v=vs.110%29.aspx
113 using (var lmKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32))
114 using (var ndpKey = lmKey.OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\"))
116 var releaseKey = (int)ndpKey.GetValue("Release");
117 return releaseKey >= 378675;
122 /// “/key:value”形式の起動オプションを解釈し IDictionary に変換する
125 /// 不正な形式のオプションは除外されます。
126 /// また、重複したキーのオプションが入力された場合は末尾に書かれたオプションが採用されます。
128 internal static IDictionary<string, string> ParseArguments(IEnumerable<string> arguments)
130 var optionPattern = new Regex(@"^/(.+?)(?::(.*))?$");
132 return arguments.Select(x => optionPattern.Match(x))
133 .Where(x => x.Success)
134 .GroupBy(x => x.Groups[1].Value)
135 .ToDictionary(x => x.Key, x => x.Last().Groups[2].Value);
138 private static void TryActivatePreviousWindow()
140 // 実行中の同じアプリケーションのウィンドウ・ハンドルの取得
141 var prevProcess = GetPreviousProcess();
142 if (prevProcess == null)
147 IntPtr windowHandle = NativeMethods.GetWindowHandle((uint)prevProcess.Id, Application.ProductName);
148 if (windowHandle != IntPtr.Zero)
150 NativeMethods.SetActiveWindow(windowHandle);
154 private static Process GetPreviousProcess()
156 var currentProcess = Process.GetCurrentProcess();
159 return Process.GetProcessesByName(currentProcess.ProcessName)
160 .Where(p => p.Id != currentProcess.Id)
161 .FirstOrDefault(p => p.MainModule.FileName.Equals(currentProcess.MainModule.FileName, StringComparison.OrdinalIgnoreCase));
169 private static void OnUnhandledException(Exception ex)
171 if (MyCommon.ExceptionOut(ex))
177 private static bool IsEqualCurrentCulture(string CultureName)
179 return Thread.CurrentThread.CurrentUICulture.Name.StartsWith(CultureName, StringComparison.Ordinal);
182 public static string CultureCode
186 if (MyCommon.cultureStr == null)
188 var cfgCommon = SettingCommon.Load();
189 MyCommon.cultureStr = cfgCommon.Language;
190 if (MyCommon.cultureStr == "OS")
192 if (!IsEqualCurrentCulture("ja") &&
193 !IsEqualCurrentCulture("en") &&
194 !IsEqualCurrentCulture("zh-CN"))
196 MyCommon.cultureStr = "en";
200 return MyCommon.cultureStr;
204 public static void InitCulture()
208 var culture = CultureInfo.CurrentCulture;
209 if (CultureCode != "OS")
210 culture = new CultureInfo(CultureCode);
212 CultureInfo.DefaultThreadCurrentUICulture = culture;
213 Thread.CurrentThread.CurrentUICulture = culture;
220 private static bool SetConfigDirectoryPath()
223 if (StartupOptions.TryGetValue("configDir", out configDir) && !string.IsNullOrEmpty(configDir))
225 // 起動オプション /configDir で設定ファイルの参照先を変更できます
226 if (!Directory.Exists(configDir))
228 var text = string.Format(Properties.Resources.ConfigDirectoryNotExist, configDir);
229 MessageBox.Show(text, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
233 MyCommon.settingPath = Path.GetFullPath(configDir);
237 if (File.Exists(Path.Combine(Application.StartupPath, "roaming")))
239 MyCommon.settingPath = MySpecialPath.UserAppDataPath();
243 MyCommon.settingPath = Application.StartupPath;