1- Una forma consiste en automatizar el menú contextual de la bandeja del sistema (System Tray), haciendo click en los comandos "Conectar" y "Desconectar" de dicho menú según sea el estado actual de la conexión VPN. Esto es una técnica bastante más eficiente que la estrategia de automatización de la GUI que compartí para la versión de pago en el post anterior aquí arriba, ya que no depende de coordenadas ni de averiguar el color del botón "Conectar/Desconectar", pero de todas formas si la barra de tareas estuviese oculta/colapsada o si el icono de ProtonVPN estuviese oculto en el área de notificación colapsado, supondría una barrera que requeriría implementar más lógica adicional de automatización para la barra de tareas. Al menos el método de automatización que ya compartí no tiene esas barreras.
2- La otra forma, la cual descubrí investigando en un hilo de Reddit, y la cual considero que es la forma más efectiva de todas (o al menos la menos invasiva), consiste en enviar una señal de detención al servicio de Windows de ProtonVPN. Esto provocará una reconexión de la interfaz de red de Proton (y con ello un cambio aleatorio de servidor). El único requisito es estar corriendo ProtonVPN y tener activado el modo "País aleatorio" para que al reiniciar el servicio la nueva conexión se establezca alternando a otro servidor diferente.
3- Existiría una tercera vía mediante la comunicación directa con la canalización con nombre (Named Pipe) de Proton. En teoría se podría lograr importando las librerías DLL necesarias de la aplicación (NET 8+), pero es una opción poco viable para poder compartirlo como solución de distribución general en un foro. En su defecto se supone que se podría implementar un proxy WCF (Windows Communication Foundation), pero esta opción tampoco sería muy viable, aparte del ingente esfuerzo para implementar todas las interfaces necesarias (ver aquí), la solución sería extremadamente frágil, ya que cualquier modificación en los contratos de interfaz del código fuente original de Proton invalidaría el proxy por completo. No llegué a implementar esta solución y, para ser sinceros, tampoco es que tenga experiencia en hacerlo.
En fin. Teniendo todo esto en cuenta, considero que llevar a cabo el "reinicio" del servicio de ProtonVPN es la solución que tiene el "trade-off" más factible entre todas las demás soluciones que descubrí. Aquí les dejo el código fuente:
Código
''' <summary> ''' Restarts the Proton VPN Windows Service to force a server reconnection. ''' </summary> ''' ''' <remarks> ''' This method validates that a connection is active by checking the ''' "ProtonVPN" network interface status before attempting to restart the service. ''' </remarks> ''' ''' <exception cref="InvalidOperationException"> ''' Thrown when the Proton VPN network interface is not found or is not connected, ''' or if the <b>ProtonVPN</b> Windows service fails to complete the restart sequence. ''' </exception> ''' ''' <exception cref="Exception"> ''' Thrown when the <b>ProtonVPN</b> Windows service service restarted and network interface is UP, ''' but no data flow (Bytes Received) was detected. ''' </exception> <EditorBrowsable(EditorBrowsableState.Advanced)> <DebuggerStepThrough> Private Sub ChangeProtonVpnServerByWindowsService() Const ProtonVPN_NetworkInterfaceName As String = "ProtonVPN" Const ProtonVPN_WindowsServiceName As String = "ProtonVPN Service" Dim isProtonVpnConnected As Boolean = False Dim interfaces As NetworkInterface() = NetworkInterface.GetAllNetworkInterfaces() For Each ni As NetworkInterface In interfaces ' We look for the specific name Proton uses for its virtual adapters If ni.Name.Equals(ProtonVPN_NetworkInterfaceName, StringComparison.OrdinalIgnoreCase) Then If ni.OperationalStatus = OperationalStatus.Up Then isProtonVpnConnected = True Exit For End If End If Next ni If Not isProtonVpnConnected Then Throw New InvalidOperationException( $"The {ProtonVPN_NetworkInterfaceName} network interface is not connected to a server." & Environment.NewLine & "The reconnection logic requires an active VPN connection to be present.") End If ' Restart the ProtonVPN Windows service. Using sc As New ServiceController(ProtonVPN_WindowsServiceName) Select Case sc.Status Case ServiceControllerStatus.StartPending, ServiceControllerStatus.Running sc.Stop() sc.WaitForStatus(ServiceControllerStatus.StopPending, TimeSpan.FromSeconds(10)) Case ServiceControllerStatus.Stopped sc.Start() Case Else Throw New InvalidOperationException( $"The {ProtonVPN_WindowsServiceName} Windows service is in a unexpected state: {sc.Status}") End Select sc.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(10)) End Using ' Wait for the ProtonVPN network interface to return to 'Up' status and has verified data flow (bytes received). Dim retryTimeout As TimeSpan = TimeSpan.FromSeconds(30) Dim startTime As Date = Date.Now Dim isDataFlowEstablished As Boolean = False Dim initialBytes As Long = -1 Do While (Date.Now - startTime) < retryTimeout Dim protonVpnInterface As NetworkInterface = NetworkInterface.GetAllNetworkInterfaces(). SingleOrDefault(Function(ni) ni.Name.Equals(ProtonVPN_NetworkInterfaceName, StringComparison.OrdinalIgnoreCase)) If (protonVpnInterface IsNot Nothing) AndAlso (protonVpnInterface.OperationalStatus = OperationalStatus.Up) Then Dim stats As IPv4InterfaceStatistics = protonVpnInterface.GetIPv4Statistics() ' On first detection of 'Up' status, capture baseline. If initialBytes = -1 Then initialBytes = stats.BytesReceived End If ' Check if we have received new data since being 'Up'. If stats.BytesReceived > initialBytes Then isDataFlowEstablished = True Exit Do End If End If Thread.Sleep(500) Loop If Not isDataFlowEstablished Then Throw New Exception( $"The {ProtonVPN_WindowsServiceName} Windows service restarted " & Environment.NewLine & $"and {ProtonVPN_NetworkInterfaceName} network interface is UP, " & Environment.NewLine & $"but no data flow (bytes received) was detected within {retryTimeout.TotalSeconds} seconds.") End If Thread.Sleep(1000) ' Additional delay to ensure connection has established with a VPN server before return. End Sub
Simplemente llamar al método ChangeProtonVpnServerViaWindowsService, esperar a que termine su ejecución, y listo.





Autor




En línea




