1 // OpenTween - Client of Twitter
2 // Copyright (c) 2007-2011 kiri_feather (@kiri_feather) <kiri.feather@gmail.com>
3 // (c) 2008-2011 Moz (@syo68k)
4 // (c) 2008-2011 takeshik (@takeshik) <http://www.takeshik.org/>
5 // (c) 2010-2011 anis774 (@anis774) <http://d.hatena.ne.jp/anis774/>
6 // (c) 2010-2011 fantasticswallow (@f_swallow) <http://twitter.com/f_swallow>
7 // (c) 2011 Egtra (@egtra) <http://dev.activebasic.com/egtra/>
8 // All rights reserved.
10 // This file is part of OpenTween.
12 // This program is free software; you can redistribute it and/or modify it
13 // under the terms of the GNU General public License as published by the Free
14 // Software Foundation; either version 3 of the License, or (at your option)
17 // This program is distributed in the hope that it will be useful, but
18 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General public License
22 // You should have received a copy of the GNU General public License along
23 // with this program. if not, see <http://www.gnu.org/licenses/>, or write to
24 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
25 // Boston, MA 02110-1301, USA.
28 using System.Diagnostics;
31 using System.Runtime.InteropServices;
32 using System.Threading;
33 using System.Windows.Forms;
37 public static class Win32Api
39 #region "先行起動プロセスをアクティブにする"
41 public static void WakeupWindow(IntPtr hWnd)
43 // メイン・ウィンドウが最小化されていれば元に戻す
46 ShowWindowAsync(hWnd, SW_RESTORE);
50 SetForegroundWindow(hWnd);
53 // 外部プロセスのメイン・ウィンドウを起動するためのWin32 API
54 [DllImport("user32.dll")]
55 private extern static bool SetForegroundWindow(
59 [DllImport("user32.dll")]
60 private extern static bool ShowWindowAsync(
64 // 指定されたウィンドウが最小化( アイコン化)されているかどうかを調べる
65 [DllImport("user32.dll")]
66 private extern static bool IsIconic(
69 // ShowWindowAsync関数のパラメータに渡す定義値
70 private const int SW_RESTORE = 9; // 画面を元の大きさに戻す
72 // 実行中の同じアプリケーションのプロセスを取得する
73 public static Process GetPreviousProcess()
75 var curProcess = Process.GetCurrentProcess();
78 return Process.GetProcessesByName(curProcess.ProcessName)
79 .Where(p => p.Id != curProcess.Id)
80 .FirstOrDefault(p => string.Compare(p.MainModule.FileName, curProcess.MainModule.FileName, StringComparison.OrdinalIgnoreCase) == 0);
89 #region "タスクトレイアイコンのクリック"
90 // 指定されたクラス名およびウィンドウ名と一致するトップレベルウィンドウのハンドルを取得します
91 [DllImport("user32.dll", CharSet = CharSet.Auto, BestFitMapping = false, ThrowOnUnmappableChar = true)]
92 private extern static IntPtr FindWindow(
93 [MarshalAs(UnmanagedType.LPTStr)] string lpClassName,
94 [MarshalAs(UnmanagedType.LPTStr)] string lpWindowName);
96 // 指定された文字列と一致するクラス名とウィンドウ名文字列を持つウィンドウのハンドルを返します
97 [DllImport("user32.dll", CharSet = CharSet.Auto, BestFitMapping = false, ThrowOnUnmappableChar = true)]
98 private extern static IntPtr FindWindowEx(
101 [MarshalAs(UnmanagedType.LPTStr)] string lpsz1,
102 [MarshalAs(UnmanagedType.LPTStr)] string lpsz2);
104 // 指定されたウィンドウへ、指定されたメッセージを送信します
105 [DllImport("user32.dll")]
106 private extern static IntPtr SendMessage(
108 SendMessageType wMsg,
112 // SendMessageで送信するメッセージ
113 private enum SendMessageType : int
115 WM_USER = 0x400, //ユーザー定義メッセージ
116 TB_GETBUTTON = WM_USER + 23, //ツールバーのボタン取得
117 TB_BUTTONCOUNT = WM_USER + 24, //ツールバーのボタン(アイコン)数取得
118 TB_GETBUTTONINFO = WM_USER + 65, //ツールバーのボタン詳細情報取得
120 TCM_FIRST = 0x1300, //タブコントロールメッセージ
121 TCM_SETMINTABWIDTH = TCM_FIRST + 49, //タブアイテムの最小幅を設定
123 LVM_FIRST = 0x1000, //リストビューメッセージ
124 LVM_GETSELECTIONMARK = LVM_FIRST + 66, //複数選択時の起点になるアイテムの位置を取得
125 LVM_SETSELECTIONMARK = LVM_FIRST + 67, //複数選択時の起点になるアイテムを設定
128 [StructLayout(LayoutKind.Sequential, Pack = 1)]
129 private struct TBBUTTON
132 public IntPtr idCommand;
135 public byte bReserved0;
136 public byte bReserved1;
141 [StructLayout(LayoutKind.Sequential)]
142 private struct TBBUTTONINFO
146 public Int32 idCommand;
151 public IntPtr lParam;
152 public IntPtr pszText;
153 public Int32 cchText;
155 // TBBUTTONINFOのlParamでポイントされるアイコン情報(PostMessageで使用)
156 [StructLayout(LayoutKind.Sequential)]
157 private struct TRAYNOTIFY
161 public UInt32 uCallbackMessage;
162 public UInt32 dwDummy1;
163 public UInt32 dwDummy2;
166 // TBBUTTONINFOに指定するマスク情報
168 private enum ToolbarButtonMask : int
174 // 指定されたウィンドウを作成したスレッドの ID を取得します
175 [DllImport("user32.dll", SetLastError = true)]
176 private static extern int GetWindowThreadProcessId(
178 out int lpdwProcessId);
180 // 指定したプロセスIDに対するプロセスハンドルを取得します
181 [DllImport("kernel32.dll")]
182 private static extern IntPtr OpenProcess(
183 ProcessAccess dwDesiredAccess,
184 [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle,
187 // OpenProcessで指定するアクセス権
189 private enum ProcessAccess : int
191 /// <summary>Specifies all possible access flags for the process object.</summary>
192 AllAccess = CreateThread | DuplicateHandle | QueryInformation | SetInformation | Terminate | VMOperation | VMRead | VMWrite | Synchronize,
193 /// <summary>Enables usage of the process handle in the CreateRemoteThread function to create a thread in the process.</summary>
195 /// <summary>Enables usage of the process handle as either the source or target process in the DuplicateHandle function to duplicate a handle.</summary>
196 DuplicateHandle = 0x40,
197 /// <summary>Enables usage of the process handle in the GetExitCodeProcess and GetPriorityClass functions to read information from the process object.</summary>
198 QueryInformation = 0x400,
199 /// <summary>Enables usage of the process handle in the SetPriorityClass function to set the priority class of the process.</summary>
200 SetInformation = 0x200,
201 /// <summary>Enables usage of the process handle in the TerminateProcess function to terminate the process.</summary>
203 /// <summary>Enables usage of the process handle in the VirtualProtectEx and WriteProcessMemory functions to modify the virtual memory of the process.</summary>
205 /// <summary>Enables usage of the process handle in the ReadProcessMemory function to read from the virtual memory of the process.</summary>
207 /// <summary>Enables usage of the process handle in the WriteProcessMemory function to write to the virtual memory of the process.</summary>
209 /// <summary>Enables usage of the process handle in any of the wait functions to wait for the process to terminate.</summary>
210 Synchronize = 0x100000,
212 // 指定したプロセスの仮想アドレス空間にメモリ領域を確保
213 [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
214 private static extern IntPtr VirtualAllocEx(
218 AllocationTypes flAllocationType,
219 MemoryProtectionTypes flProtect);
223 private enum AllocationTypes : uint
232 WriteWatch = 0x200000,
233 LargePages = 0x20000000,
235 // アロケートしたメモリに対する保護レベル
237 private enum MemoryProtectionTypes : uint
241 ExecuteReadWrite = 0x40,
242 ExecuteWriteCopy = 0x80,
247 GuardModifierflag = 0x100,
248 NoCacheModifierflag = 0x200,
249 WriteCombineModifierflag = 0x400,
251 // オープンしているカーネルオブジェクトのハンドルをクローズします
252 [DllImport("kernel32.dll", SetLastError = true)]
253 private static extern bool CloseHandle(IntPtr hHandle);
255 // 指定されたプロセスの仮想アドレス空間内のメモリ領域を解放またはコミット解除します
256 [DllImport("kernel32.dll")]
257 private static extern bool VirtualFreeEx(
261 MemoryFreeTypes dwFreeType);
265 private enum MemoryFreeTypes
269 //指定したプロセスのメモリ領域にデータをコピーする
270 [DllImport("kernel32.dll", SetLastError = true)]
271 private static extern bool WriteProcessMemory(
273 IntPtr lpBaseAddress,
274 ref TBBUTTONINFO lpBuffer,
276 out int lpNumberOfBytesWritten);
278 //指定したプロセスのメモリ領域のデータを呼び出し側プロセスのバッファにコピーする
279 [DllImport("kernel32.dll", SetLastError = true)]
280 private static extern bool ReadProcessMemory(
282 IntPtr lpBaseAddress,
285 out int lpNumberOfBytesRead);
287 //メッセージをウィンドウのメッセージ キューに置き、対応するウィンドウがメッセージを処理するのを待たずに戻ります
288 [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
289 private static extern bool PostMessage(
295 //PostMessageで送信するメッセージ
296 private enum PM_Message : uint
298 WM_LBUTTONDOWN = 0x201, //左マウスボタン押し下げ
299 WM_LBUTTONUP = 0x202, //左マウスボタン離し
303 /// タブコントロールのアイテムの最小幅を設定します
305 /// <param name="tabControl">対象となるタブコントロール</param>
306 /// <param name="width">アイテムの最小幅。-1 を指定するとデフォルトの幅が使用されます</param>
307 /// <returns>設定前の最小幅</returns>
308 public static int SetMinTabWidth(TabControl tabControl, int width)
310 return (int)SendMessage(tabControl.Handle, SendMessageType.TCM_SETMINTABWIDTH, IntPtr.Zero, (IntPtr)width);
314 public static bool ClickTasktrayIcon(string tooltip)
316 const string TRAY_WINDOW = "Shell_TrayWnd";
317 const string TRAY_NOTIFYWINDOW = "TrayNotifyWnd";
318 const string TRAY_PAGER = "SysPager";
319 const string TOOLBAR_CONTROL = "ToolbarWindow32";
321 var taskbarWin = FindWindow(TRAY_WINDOW, null);
322 if (taskbarWin.Equals(IntPtr.Zero)) return false;
324 var trayWin = FindWindowEx(taskbarWin, IntPtr.Zero, TRAY_NOTIFYWINDOW, null);
325 if (trayWin.Equals(IntPtr.Zero)) return false;
326 //SysPagerの有無確認。(XP/2000はSysPagerあり)
327 var tempWin = FindWindowEx(trayWin, IntPtr.Zero, TRAY_PAGER, null);
328 if (tempWin.Equals(IntPtr.Zero)) tempWin = trayWin;
329 //タスクトレイがツールバーで出来ているか確認
331 var toolWin = FindWindowEx(tempWin, IntPtr.Zero, TOOLBAR_CONTROL, null);
332 if (toolWin.Equals(IntPtr.Zero)) return false;
333 //タスクトレイのプロセス(Explorer)を取得し、外部から参照するために開く
335 GetWindowThreadProcessId(toolWin, out expPid);
336 var hProc = OpenProcess(ProcessAccess.VMOperation | ProcessAccess.VMRead | ProcessAccess.VMWrite, false, expPid);
337 if (hProc.Equals(IntPtr.Zero)) return false;
339 //プロセスを閉じるためにtry-finally
342 var tbButtonLocal = new TBBUTTON(); //本プロセス内のタスクバーボタン情報作成(サイズ特定でのみ使用)
343 //Explorer内のタスクバーボタン格納メモリ確保
344 var ptbSysButton = VirtualAllocEx(hProc, IntPtr.Zero, (IntPtr)Marshal.SizeOf(tbButtonLocal), AllocationTypes.Reserve | AllocationTypes.Commit, MemoryProtectionTypes.ReadWrite);
345 if (ptbSysButton.Equals(IntPtr.Zero)) return false; //メモリ確保失敗
348 var tbButtonInfoLocal = new TBBUTTONINFO(); //本プロセス内ツールバーボタン詳細情報作成
349 //Explorer内のタスクバーボタン詳細情報格納メモリ確保
350 var ptbSysInfo = VirtualAllocEx(hProc, IntPtr.Zero, (IntPtr)Marshal.SizeOf(tbButtonInfoLocal), AllocationTypes.Reserve | AllocationTypes.Commit, MemoryProtectionTypes.ReadWrite);
351 if (ptbSysInfo.Equals(IntPtr.Zero)) return false; //メモリ確保失敗
354 const int titleSize = 256; //Tooltip文字列長
355 var title = ""; //Tooltip文字列
356 //共有メモリにTooltip読込メモリ確保
357 var pszTitle = Marshal.AllocCoTaskMem(titleSize);
358 if (pszTitle.Equals(IntPtr.Zero)) return false; //メモリ確保失敗
361 //Explorer内にTooltip読込メモリ確保
362 var pszSysTitle = VirtualAllocEx(hProc, IntPtr.Zero, (IntPtr)titleSize, AllocationTypes.Reserve | AllocationTypes.Commit, MemoryProtectionTypes.ReadWrite);
363 if (pszSysTitle.Equals(IntPtr.Zero)) return false; //メモリ確保失敗
367 var iCount = (int)SendMessage(toolWin, SendMessageType.TB_BUTTONCOUNT, new IntPtr(0), new IntPtr(0));
369 for (var i = 0; i < iCount; i++)
371 var dwBytes = 0; //読み書きバイト数
372 var tbButtonLocal2 = new TBBUTTON(); //ボタン情報
373 var tbButtonInfoLocal2 = new TBBUTTONINFO(); //ボタン詳細情報
375 var ptrLocal = Marshal.AllocCoTaskMem(Marshal.SizeOf(tbButtonLocal));
376 if (ptrLocal.Equals(IntPtr.Zero)) return false; //メモリ確保失敗
379 Marshal.StructureToPtr(tbButtonLocal, ptrLocal, true); //共有メモリ初期化
380 //ボタン情報取得(idCommandを取得するため)
383 SendMessageType.TB_GETBUTTON,
386 //Explorer内のメモリを共有メモリに読み込み
391 (IntPtr)Marshal.SizeOf(tbButtonLocal),
394 tbButtonLocal2 = (TBBUTTON)Marshal.PtrToStructure(
400 Marshal.FreeCoTaskMem(ptrLocal); //共有メモリ解放
403 //ボタン詳細情報を取得するためのマスク等を設定
404 tbButtonInfoLocal.cbSize = Marshal.SizeOf(tbButtonInfoLocal);
405 tbButtonInfoLocal.dwMask = (int)(ToolbarButtonMask.TBIF_COMMAND | ToolbarButtonMask.TBIF_LPARAM | ToolbarButtonMask.TBIF_TEXT);
406 tbButtonInfoLocal.pszText = pszSysTitle; //Tooltip書き込み先領域
407 tbButtonInfoLocal.cchText = titleSize;
408 //マスク設定等をExplorerのメモリへ書き込み
412 ref tbButtonInfoLocal,
413 (IntPtr)Marshal.SizeOf(tbButtonInfoLocal),
418 SendMessageType.TB_GETBUTTONINFO,
419 tbButtonLocal2.idCommand,
421 //共有メモリにボタン詳細情報を読み込む領域確保
422 var ptrInfo = Marshal.AllocCoTaskMem(Marshal.SizeOf(tbButtonInfoLocal));
423 if (ptrInfo.Equals(IntPtr.Zero)) return false; //共有メモリ確保失敗
426 Marshal.StructureToPtr(tbButtonInfoLocal, ptrInfo, true); //共有メモリ初期化
427 //Explorer内のメモリを共有メモリに読み込み
432 (IntPtr)Marshal.SizeOf(tbButtonInfoLocal),
435 tbButtonInfoLocal2 = (TBBUTTONINFO)Marshal.PtrToStructure(
437 typeof(TBBUTTONINFO));
441 Marshal.FreeCoTaskMem(ptrInfo); //共有メモリ解放
443 //Tooltipの内容をExplorer内のメモリから共有メモリへ読込
444 ReadProcessMemory(hProc, pszSysTitle, pszTitle, (IntPtr)titleSize, out dwBytes);
446 title = Marshal.PtrToStringAnsi(pszTitle, titleSize);
448 //Tooltipが指定文字列を含んでいればクリック
449 if (title.Contains(tooltip))
451 //PostMessageでクリックを送るために、ボタン詳細情報のlParamでポイントされているTRAYNOTIFY情報が必要
452 var tNotify = new TRAYNOTIFY();
453 var tNotify2 = new TRAYNOTIFY();
455 var ptNotify = Marshal.AllocCoTaskMem(Marshal.SizeOf(tNotify));
456 if (ptNotify.Equals(IntPtr.Zero)) return false; //メモリ確保失敗
459 Marshal.StructureToPtr(tNotify, ptNotify, true); //初期化
463 tbButtonInfoLocal2.lParam,
465 (IntPtr)Marshal.SizeOf(tNotify),
468 tNotify2 = (TRAYNOTIFY)
469 Marshal.PtrToStructure(
475 Marshal.FreeCoTaskMem(ptNotify); //共有メモリ解放
477 //クリックするためには通知領域がアクティブでなければならない
478 SetForegroundWindow(tNotify2.hWnd);
480 PostMessage(tNotify2.hWnd, tNotify2.uCallbackMessage, (IntPtr)tNotify2.uID, (IntPtr)PM_Message.WM_LBUTTONDOWN);
481 PostMessage(tNotify2.hWnd, tNotify2.uCallbackMessage, (IntPtr)tNotify2.uID, (IntPtr)PM_Message.WM_LBUTTONUP);
489 VirtualFreeEx(hProc, pszSysTitle, (IntPtr)titleSize, MemoryFreeTypes.Release); //メモリ解放
494 Marshal.FreeCoTaskMem(pszTitle); //共有メモリ解放
499 VirtualFreeEx(hProc, ptbSysInfo, (IntPtr)Marshal.SizeOf(tbButtonInfoLocal), MemoryFreeTypes.Release); //メモリ解放
504 VirtualFreeEx(hProc, ptbSysButton, (IntPtr)Marshal.SizeOf(tbButtonLocal), MemoryFreeTypes.Release); //メモリ解放
509 CloseHandle(hProc); //Explorerのプロセス閉じる
515 public static bool FlashMyWindow(IntPtr hwnd,
516 FlashSpecification flashType,
519 var fInfo = new FLASHWINFO();
520 fInfo.cbSize = Convert.ToInt32(Marshal.SizeOf(fInfo));
522 fInfo.dwFlags = (int)FlashSpecification.FlashAll;
523 fInfo.uCount = flashCount;
526 return FlashWindowEx(ref fInfo);
529 public enum FlashSpecification : uint
531 FlashStop = FLASHW_STOP,
532 FlashCaption = FLASHW_CAPTION,
533 FlashTray = FLASHW_TRAY,
534 FlashAll = FLASHW_ALL,
535 FlashTimer = FLASHW_TIMER,
536 FlashTimerNoForeground = FLASHW_TIMERNOFG,
538 /// http://www.atmarkit.co.jp/fdotnet/dotnettips/723flashwindow/flashwindow.html
539 [DllImport("user32.dll")]
540 private static extern bool FlashWindowEx(
541 ref FLASHWINFO FWInfo);
544 private struct FLASHWINFO
546 public Int32 cbSize; // FLASHWINFO構造体のサイズ
547 public IntPtr hwnd; // 点滅対象のウィンドウ・ハンドル
548 public Int32 dwFlags; // 以下の「FLASHW_XXX」のいずれか
549 public Int32 uCount; // 点滅する回数
550 public Int32 dwTimeout; // 点滅する間隔(ミリ秒単位)
554 private const Int32 FLASHW_STOP = 0;
556 private const Int32 FLASHW_CAPTION = 0x1;
558 private const Int32 FLASHW_TRAY = 0x2;
559 // タスクバー・ボタンとタイトルバーを点滅させる
560 private const Int32 FLASHW_ALL = 0x3;
561 // FLASHW_STOPが指定されるまでずっと点滅させる
562 private const Int32 FLASHW_TIMER = 0x4;
563 // ウィンドウが最前面に来るまでずっと点滅させる
564 private const Int32 FLASHW_TIMERNOFG = 0xC;
567 [DllImport("user32.dll")]
568 public static extern bool ValidateRect(
572 #region "selection mark"
573 // 複数選択時の起点になるアイテム (selection mark) の位置を取得する
574 public static int ListView_GetSelectionMark(IntPtr hwndLV)
576 return SendMessage(hwndLV, SendMessageType.LVM_GETSELECTIONMARK, IntPtr.Zero, IntPtr.Zero).ToInt32();
579 // 複数選択時の起点になるアイテム (selection mark) を設定する
580 public static void ListView_SetSelectionMark(IntPtr hwndLV, int itemIndex)
582 SendMessage(hwndLV, SendMessageType.LVM_SETSELECTIONMARK, IntPtr.Zero, (IntPtr)itemIndex);
586 #region "スクリーンセーバー起動中か判定"
587 [DllImport("user32", CharSet = CharSet.Auto)]
588 private static extern int SystemParametersInfo(
593 // returns non-zero value if function succeeds
595 //スクリーンセーバーが起動中かを取得する定数
596 private const int SPI_GETSCREENSAVERRUNNING = 0x0072;
598 public static bool IsScreenSaverRunning()
600 var isRunning = false;
601 SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, ref isRunning, 0);
607 [DllImport("user32")]
608 private static extern int RegisterHotKey(IntPtr hwnd, int id,
609 int fsModifiers, int vk);
610 [DllImport("user32")]
611 private static extern int UnregisterHotKey(IntPtr hwnd, int id);
612 [DllImport("kernel32", CharSet = CharSet.Auto, BestFitMapping = false, ThrowOnUnmappableChar = true)]
613 private static extern ushort GlobalAddAtom([MarshalAs(UnmanagedType.LPTStr)] string lpString);
614 [DllImport("kernel32")]
615 private static extern ushort GlobalDeleteAtom(ushort nAtom);
617 private static int registerCount = 0;
618 // register a global hot key
619 public static int RegisterGlobalHotKey(int hotkeyValue, int modifiers, Form targetForm)
624 // use the GlobalAddAtom API to get a unique ID (as suggested by MSDN docs)
626 var atomName = Thread.CurrentThread.ManagedThreadId.ToString("X8") + targetForm.Name + registerCount.ToString();
627 hotkeyID = GlobalAddAtom(atomName);
630 throw new Exception("Unable to generate unique hotkey ID. Error code: " +
631 Marshal.GetLastWin32Error().ToString());
634 // register the hotkey, throw if any error
635 if (RegisterHotKey(targetForm.Handle, hotkeyID, modifiers, hotkeyValue) == 0)
637 throw new Exception("Unable to register hotkey. Error code: " +
638 Marshal.GetLastWin32Error().ToString());
644 // clean up if hotkey registration failed
645 UnregisterGlobalHotKey(hotkeyID, targetForm);
650 // unregister a global hotkey
651 public static void UnregisterGlobalHotKey(ushort hotkeyID, Form targetForm)
655 UnregisterHotKey(targetForm.Handle, hotkeyID);
656 // clean up the atom list
657 GlobalDeleteAtom(hotkeyID);
663 #region "プロセスのProxy設定"
664 [DllImport("wininet.dll", SetLastError =true)]
665 private static extern bool InternetSetOption(IntPtr hInternet,
668 int lpdwBufferLength);
670 private struct INTERNET_PROXY_INFO : IDisposable
672 public int dwAccessType;
674 public IntPtr proxyBypass;
676 public void Dispose()
681 private void Dispose(bool disposing)
683 if (proxy != IntPtr.Zero) Marshal.FreeHGlobal(proxy);
684 if (proxyBypass != IntPtr.Zero) Marshal.FreeHGlobal(proxyBypass);
688 private static void RefreshProxySettings(string strProxy)
690 const int INTERNET_OPTION_PROXY = 38;
691 //const int INTERNET_OPEN_TYPE_PRECONFIG = 0; //IE setting
692 const int INTERNET_OPEN_TYPE_DIRECT = 1; //Direct
693 const int INTERNET_OPEN_TYPE_PROXY = 3; //Custom
695 INTERNET_PROXY_INFO ipi;
697 // Filling in structure
698 if (!string.IsNullOrEmpty(strProxy))
700 ipi.dwAccessType = INTERNET_OPEN_TYPE_PROXY;
701 ipi.proxy = Marshal.StringToHGlobalAnsi(strProxy);
702 ipi.proxyBypass = Marshal.StringToHGlobalAnsi("local");
704 else if (strProxy == null)
707 var p = WebRequest.GetSystemWebProxy();
708 if (p.IsBypassed(new Uri("http://www.google.com/")))
710 ipi.dwAccessType = INTERNET_OPEN_TYPE_DIRECT;
711 ipi.proxy = IntPtr.Zero;
712 ipi.proxyBypass = IntPtr.Zero;
716 ipi.dwAccessType = INTERNET_OPEN_TYPE_PROXY;
717 ipi.proxy = Marshal.StringToHGlobalAnsi(p.GetProxy(new Uri("http://www.google.com/")).Authority);
718 ipi.proxyBypass = Marshal.StringToHGlobalAnsi("local");
723 ipi.dwAccessType = INTERNET_OPEN_TYPE_DIRECT;
724 ipi.proxy = IntPtr.Zero;
725 ipi.proxyBypass = IntPtr.Zero;
731 var pIpi = Marshal.AllocCoTaskMem(Marshal.SizeOf(ipi));
732 if (pIpi.Equals(IntPtr.Zero)) return;
735 // Converting structure to IntPtr
736 Marshal.StructureToPtr(ipi, pIpi, true);
737 var ret = InternetSetOption(IntPtr.Zero,
738 INTERNET_OPTION_PROXY,
740 Marshal.SizeOf(ipi));
744 Marshal.FreeCoTaskMem(pIpi);
753 private static void RefreshProxyAccount(string username, string password)
755 const int INTERNET_OPTION_PROXY_USERNAME = 43;
756 const int INTERNET_OPTION_PROXY_PASSWORD = 44;
758 if (!string.IsNullOrEmpty(username) || !string.IsNullOrEmpty(password))
760 var ret = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_PROXY_USERNAME, IntPtr.Zero, 0);
761 ret = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_PROXY_PASSWORD, IntPtr.Zero, 0);
765 var pUser = Marshal.StringToBSTR(username);
766 var pPass = Marshal.StringToBSTR(password);
769 var ret = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_PROXY_USERNAME, pUser, username.Length + 1);
770 ret = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_PROXY_PASSWORD, pPass, password.Length + 1);
774 Marshal.FreeBSTR(pUser);
775 Marshal.FreeBSTR(pPass);
780 public static void SetProxy(HttpConnection.ProxyType pType, string host, int port, string username, string password)
785 case HttpConnection.ProxyType.IE:
788 case HttpConnection.ProxyType.None:
791 case HttpConnection.ProxyType.Specified:
792 proxy = host + (port > 0 ? ":" + port.ToString() : "");
795 RefreshProxySettings(proxy);
796 RefreshProxyAccount(username, password);