Closed pocc closed 6 years ago
Use WMI to get that data
PowerShell has a cmdlet called Get-NetConnectionProfile that should work; getting that data does involve using subprocess to get the output though, so it could get a bit gross with insufficient permissions to run it.
Will do some more looking myself, but if you can find a library that lets Python interface with PowerShell more cleanly, that could also work =)
Here's a rough start to get this going:
#! /usr/bin/python
import subprocess
import re
process = subprocess.Popen(["powershell", "Get-NetConnectionProfile"],
stdout=subprocess.PIPE)
# resultant data is a tuple of bytes, so just decode to a string
result = process.communicate()[0].decode("utf-8")
connection_data = {}
for line in result.split("\r\n"):
if line:
squeezed = re.sub('\s+', '', line)
connection_data.update([squeezed.split(':')])
for key, value in connection_data.items():
print("%s : %s" % (key, value))
From there, checking whether Windows thinks it has a working Inet connection is just a matter of checking if the "IPv4Connectivity"
key has a value of "Internet"
(see here for reference: https://docs.microsoft.com/en-us/powershell/module/netconnection/get-netconnectionprofile?view=win10-ps)
This has some obvious concerns about error handling that I didn't get a chance to look into yet, but I can do some more digging on what subprocess might raise if it runs into a permissions issue if you think this is a viable route to take.
I think part of this is my fault for not being clearer for the issue description. I'm going to edit my initial comment to be more detailed.
A sidenote is that QNetworkConfigurationManager has a public function isOnline() that may be more appropriate here so that we don't need to rewrite code for more platforms as they become supported. We haven't hit MVP though, so whatever works.
It really comes down to whether you want OS independence or not - I think this'll do the job for Windows if you just return a boolean true/false based on whether IPV4Connectivity
's value is Internet
or not and raise the appropriate alert if it's not
I created code snippets with the Powershell cmdlet, the Qt function, and python + ping to see which one was fastest by timing them.
Of these three, the Qt version just fails to notice that the connection has died. Code is included below for completeness, but I am not collecting speed data for it.
Below, each cell value consists of 10 tries in that scenario. The testing connection was wireless and an 'offline' state was produced by disconnecting from the SSID.
Py + ICMP | Py + PS | |
---|---|---|
Avg online (s) | 0.18 | 2.22 |
Avg offline (s) | 1.76 | 2.19 |
Python + Powershell is more consistent at around ~2.2s, but Python + ICMP is faster. As ICMP is both faster and cross-platform, I plan on using this code snippet.
import subprocess, time
result = ''
i = 0
starttime = time.time()
# We may want to ignore a time out in case the next ping is successful
# 300ms timeout because a 300ms+ connection is a bad connection
while 'unreachable' not in result and 'failure' not in result and i < 4:
result = subprocess.Popen(['ping','-n','1','-w','300','8.8.8.8'], \
stdout = subprocess.PIPE).communicate()[0].decode('utf-8')
i += 1
online = 'unreachable' not in result and 'timed out' not in result and 'failure' not in result
print("Device is online:", online, "\nTook " + str(time.time()-starttime)+ " seconds")
import subprocess, time
starttime = time.time()
# This gets a network connection profile (if it exists) and then parses it
# If we detect "Internet" in the PS response, then we have a working connection
connections = subprocess.Popen(["powershell", "$Connectivity = Get-NetConnectionProfile \
| select -expandProperty IPv4Connectivity; if ($Connectivity -like \"Internet\") \
{return \"True\"} else {return \"False\"}"],stdout=subprocess.PIPE)
online = connections.communicate()[0].decode("utf-8").strip()
print("Device is online:", online, "\nTook " + str(time.time()-starttime)+ " seconds")
import time
starttime = time.time()
from PyQt5.QtNetwork import QNetworkConfigurationManager
connections = QNetworkConfigurationManager()
online = connections.isOnline()
print("Device is online:", online, "\nTook " + str(time.time()-starttime)+ " seconds")
Immediately fail if device is not online
Problem
If users don't have a working internet connection, they're wasting time by trying to use this program as this is a requirement for VPN.
Proposed Solution
Version info
Notes