Quick way to connect Windows 10 embedded VPN connections
-
Hi there,
in work we use a checkpoint firewall thats also giving us vpn access. Since Windows 10 is supporting Checkpoint VPN named “Capsule” on the store:
https://www.microsoft.com/de-de/store/p/check-point-capsule-vpn/9wzdncrdjxtj
It’s possible to use Windows 10 internal VPN instead of installing Checkpoints VPN Client.Windows 10 from 1511 to 1607 just offered a real bad way to connect this VPN Connection by GUI, you had to click several times until the connection has been connected. A minimum is 5 clicks.
With 1703 this has changed and you can now access your VPN directly from Systray:
Applause Microsoft now i only need 3 Click up to a connection
I still hate it to need to click so often for a simple VPN Connection so i wrote myself something.The program is called VPNTool, it’s a single exe binary that will place a systray icon:
with the following options:
- left or right click on the icon will show a popupmenu:
- Connect/Disconnect
- Reconnect on connection drop
- Notifications about connection state on/off
- Close the App for example:
The program cannot be closed by click against accidents you need to press STRG + ALT + X (global Hotkey)
-
Every Action can additional to mouse done by global Hotkeys as seen on the Screenshot (open popup)
-
Doubleclick on the systray icon will dial or disconnect depending on connection state.
Now i just need a double click or 2 normal clicks or just need to press STRG + ALT + V to connect my VPN.
I will paste my source code here:
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, CoolTrayIcon, Menus, StdCtrls, ImgList, TextTrayIcon, StrUtils, ExtCtrls, ShellAPI; type TForm1 = class(TForm) TextTrayIcon1: TTextTrayIcon; Timer1: TTimer; PopupMenu1: TPopupMenu; VerbindenAuflegen1: TMenuItem; Beenden1: TMenuItem; Wiederverbinden1: TMenuItem; Timer2: TTimer; Benachrichtigungen1: TMenuItem; ListBox1: TListBox; procedure FormCreate(Sender: TObject); procedure Timer1Timer(Sender: TObject); procedure VerbindenAuflegen1Click(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure Beenden1Click(Sender: TObject); procedure Wiederverbinden1Click(Sender: TObject); procedure Timer2Timer(Sender: TObject); procedure TextTrayIcon1DblClick(Sender: TObject); procedure Benachrichtigungen1Click(Sender: TObject); private id1, id2, id3, id4 : Integer; procedure WMHotKey(var Msg: TWMHotKey); message WM_HOTKEY; { Private declarations } public MinIcon : array[0..1] of TIcon; { Public declarations } end; var Form1: TForm1; mHandle: THandle; // Mutexhandle implementation {$R *.dfm} procedure TForm1.WMHotKey(var Msg: TWMHotKey); begin if Msg.HotKey = id1 then Form1.VerbindenAuflegen1.Click; if Msg.HotKey = id2 then Form1.Close; if Msg.HotKey = id3 then Form1.Wiederverbinden1.Click; if Msg.HotKey = id4 then Form1.Benachrichtigungen1.Click; end; function Konsole(const Command: String): String; var StartupInfo: TStartupInfo; ProcessInfo: TProcessInformation; SecurityAttr: TSecurityAttributes; OutputPipeRead, OutputPipeWrite: THandle; Res: Boolean; BufSize: Cardinal; Buffer: String; BytesRead: Cardinal; begin //Initialisierung ProcessInfo FillChar(ProcessInfo, SizeOf(TProcessInformation), 0); //Initialisierung SecurityAttr FillChar(SecurityAttr, SizeOf(TSecurityAttributes), 0); SecurityAttr.nLength := SizeOf(SecurityAttr); SecurityAttr.bInheritHandle := true; SecurityAttr.lpSecurityDescriptor := nil; //Pipe erzeugen CreatePipe(OutputPipeRead, OutputPipeWrite, @SecurityAttr, 0); //Initialisierung StartupInfo FillChar(StartupInfo, SizeOf(TStartupInfo), 0); StartupInfo.cb:=SizeOf(StartupInfo); StartupInfo.hStdInput := 0; StartupInfo.hStdOutput := OutputPipeWrite; StartupInfo.hStdError := OutputPipeWrite; StartupInfo.wShowWindow := SW_HIDE; StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES; //Prozess erzeugen Res := CreateProcess(nil, PChar(command), nil, nil, true, CREATE_DEFAULT_ERROR_MODE or CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, ProcessInfo); //OutputPipeWrite schließen CloseHandle(OutputPipeWrite); Result := ''; if Res then begin //OutputPipeRead auslesen SetLength(Buffer, 5000); BufSize := Length(Buffer); repeat Res := ReadFile(OutputPipeRead, Buffer[1], BufSize, BytesRead, nil); Result := Result + Copy(Buffer, 1, BytesRead); until not Res; //auf Prozessende warten WaitForSingleObject(ProcessInfo.hProcess, INFINITE); CloseHandle(ProcessInfo.hProcess); end; //OutputPipeRead schließen CloseHandle(OutputPipeRead); end; procedure TForm1.FormCreate(Sender: TObject); const MOD_ALT = 1; MOD_CONTROL = 2; VK_B = $42; VK_V = $56; VK_W = $57; VK_X = $58; begin mHandle := CreateMutex(nil,True,'VPNTool'); if GetLastError = ERROR_ALREADY_EXISTS then begin Halt; end; MinIcon[0]:=TIcon.Create; MinIcon[1]:=TIcon.Create; MinIcon[0].Handle:=LoadIcon(hInstance,'lock'); MinIcon[1].Handle:=LoadIcon(hInstance,'lock2'); id1 := GlobalAddAtom('Hotkey1'); RegisterHotKey(Handle, id1, MOD_CONTROL + MOD_Alt, VK_V); id2 := GlobalAddAtom('Hotkey2'); RegisterHotKey(Handle, id2, MOD_CONTROL + MOD_Alt, VK_X); id3 := GlobalAddAtom('Hotkey3'); RegisterHotKey(Handle, id3, MOD_CONTROL + MOD_Alt, VK_W); id4 := GlobalAddAtom('Hotkey4'); RegisterHotKey(Handle, id4, MOD_CONTROL + MOD_Alt, VK_B); Self.Hide; WindowState := wsMinimized; ShowWindow(Application.Handle, SW_Hide); if AnsiContainsText(Konsole('cmd /c rasdial'),'hergestellt') then begin TextTrayIcon1.Icon := MinIcon[0]; PopupMenu1.Items[0].Caption := 'Auflegen'; end else begin TextTrayIcon1.Icon := MinIcon[1]; PopupMenu1.Items[0].Caption := 'Verbinden'; end; end; procedure TForm1.Timer1Timer(Sender: TObject); begin if AnsiContainsText(Konsole('cmd /c rasdial'),'hergestellt') then begin TextTrayIcon1.Icon := MinIcon[0]; PopupMenu1.Items[0].Caption := 'Auflegen'; end else begin TextTrayIcon1.Icon := MinIcon[1]; PopupMenu1.Items[0].Caption := 'Verbinden'; end; end; procedure TForm1.Timer2Timer(Sender: TObject); begin if AnsiContainsText(Konsole('cmd /c rasdial'),'Keine') then if PopupMenu1.Tag = 1 then Form1.VerbindenAuflegen1.Click; end; procedure TForm1.VerbindenAuflegen1Click(Sender: TObject); begin //if AnsiContainsText(Konsole('ipconfig'),'VPN Haan') if AnsiContainsText(Konsole('cmd /c rasdial'),'hergestellt') then begin ShellExecute(handle,'open',PChar('rasdial'), PChar('"VPN Haan" /d'),'',SW_HIDE); if Form1.Tag = 1 then begin ListBox1.Items[2] := '$notificationTitle = "VPN Verbindung getrennt. " + [DateTime]::Now.ToShortTimeString()'; ListBox1.Items.SaveToFile(SysUtils.GetEnvironmentVariable('temp') + '\VPNTool.ps1'); ShellExecute(handle,'open',PChar('Powershell.exe'), PChar('-ExecutionPolicy Bypass -File ' + SysUtils.GetEnvironmentVariable('temp') + '\VPNTool.ps1'),'',SW_HIDE); end; end else begin ShellExecute(handle,'open',PChar('rasdial'), PChar('"VPN Haan"'),'',SW_HIDE); if Form1.Tag = 1 then begin ListBox1.Items[2] := '$notificationTitle = "VPN Verbindung hergestellt. " + [DateTime]::Now.ToShortTimeString()'; ListBox1.Items.SaveToFile(SysUtils.GetEnvironmentVariable('temp') + '\VPNTool.ps1'); ShellExecute(handle,'open',PChar('Powershell.exe'), PChar('-ExecutionPolicy Bypass -File ' + SysUtils.GetEnvironmentVariable('temp') + '\VPNTool.ps1'),'',SW_HIDE); end; end; end; procedure TForm1.Wiederverbinden1Click(Sender: TObject); begin if PopupMenu1.Items[1].Checked = False then begin PopupMenu1.Tag := 0; Timer2.Enabled := False; end else begin PopupMenu1.Tag := 1; Timer2.Enabled := True; end; end; procedure TForm1.Benachrichtigungen1Click(Sender: TObject); begin if PopupMenu1.Items[2].Checked = False then Form1.Tag := 0 else Form1.Tag := 1; end; procedure TForm1.Beenden1Click(Sender: TObject); begin if Form1.Tag = 1 then begin ListBox1.Items[2] := '$notificationTitle = "STRG + ALT + X zum beenden."'; ListBox1.Items.SaveToFile(SysUtils.GetEnvironmentVariable('temp') + '\VPNTool.ps1'); ShellExecute(handle,'open',PChar('Powershell.exe'), PChar('-ExecutionPolicy Bypass -File ' + SysUtils.GetEnvironmentVariable('temp') + '\VPNTool.ps1'),'',SW_HIDE); end; end; procedure TForm1.FormDestroy(Sender: TObject); begin UnRegisterHotKey(Handle, id1); GlobalDeleteAtom(id1); UnRegisterHotKey(Handle, id2); GlobalDeleteAtom(id2); UnRegisterHotKey(Handle, id3); GlobalDeleteAtom(id3); UnRegisterHotKey(Handle, id4); GlobalDeleteAtom(id4); if mHandle <> 0 then CloseHandle(mHandle) end; procedure TForm1.TextTrayIcon1DblClick(Sender: TObject); begin Form1.VerbindenAuflegen1.Click; end; end.
Sorry i completely left it uncommented for now.
If anyone is interested i can also share binarys, actually all the strings are for german language but i can easily make it international.At this time the VPN Name and a little more is hardcoded, but it would be no pain to make this adjustable with an ini file.
Also polling for the rasdial connection state while triggering cmd and reading its console returns is not really that what i would understand under best practice, so maybe someone has any ideas to solve this more system-orientated.
If anyone with development skills is really reading my source code, i know i am a bad ass and please forgive me i am not a developer just a stupid technician and i know delphi is dead but i can do with it.
Regards X23