# Copyright Matthew Kindy # July 16, 2008 # # You are free to use and modify this program so long as the following terms are met: # # - credit to Matthew Kindy with email address matthew@kindy.net is documented in the source code # - source code is distributed with the program and is editable as an ASCII text file # # # netshgui # v 0.2 # # from Tkinter import * from os import * import tkMessageBox import re window_title = "netsh GUI v0.2, by Matthew Kindy" # ================================================== def valid_data(quartet): L=re.findall("[0-9]+.[0-9]+.[0-9]+.[0-9]+", quartet) if (len(L)==1 ): return True else: return False # ================================================== def SetValues(o, w, d, dd, f): # The "f" flag indicates whether the change button has been # pressed (f==1), or this is being called by the revert button (f==0) answer1=0 ModifyValues=0 # ------------------------- # Change button was pressed # ------------------------- if (f): info = "You can use the Revert button to retrieve \n" info = info + "and set back the original values, but\n" info = info + "setting these values IS immediate.\n\n" info = info + "Do you still want to modify these values?" ModifyValues = tkMessageBox.askyesno("Reverseable", info) # --------------------------------------------------------------------------------------- # Change the values if the user is sure, or this function was called from SetOrigValues() # --------------------------------------------------------------------------------------- if (ModifyValues or (not f)): # ------------------------- # Prevent changing the name # ------------------------- # These first two lines are just until the # command to change the name is worked out... # # Clear out the field w[0].delete(0, END) # # Put in the original name w[0].insert(0, o[0]) # ----------------------- # Get the values to use # ----------------------- # This one will stay, regardless name = w[0].get() dhcpval = d.get() ip = w[2].get() sn = w[3].get() gw = w[4].get() # ----------------------- # VALIDATE IP ADDRESSES # ----------------------- if (valid_data(ip)): if (dhcpval==1): dhcp = "Enabled" else: dhcp = "Disabled" cmd = "netsh interface ipv4 set address name=\"" + name + "\"" if dhcpval: cmd = cmd + " source=dhcp " # -------------------------------------------------------------------------------------------- # TO DO: Make this not only check for DISABLED, but also that it is a valid IP address format # -------------------------------------------------------------------------------------------- if (gw != "DISABLED"): cmd = cmd + " gateway=" + gw else: msg = "\"" + name + "\" is unavailable but has been " msg = msg + "set to use DHCP when it becomes available." answer1 = tkMessageBox.showinfo("Dsiabled Interface", msg) # Execute this whether or not the gateway field is correct strfile = popen(cmd) else: # Can't set a static IP address without the proper info... # --------------------------------------------------------------------------------------------- # TO DO: Make this not only check for DISABLED, but also that it is a valid IP address format # --------------------------------------------------------------------------------------------- if (ip == "DISABLED" or sn == "DISABLED" or gw == "DISABLED"): msg = "One or more of the IP Address, Subnet Mask, and Default Gateway " msg = msg + "fields does not have an IP address" answer1 = tkMessageBox.showinfo("ERROR", msg) else: cmd = cmd + " source=static " cmd = cmd + " addr=" + ip cmd = cmd + " mask=" + sn cmd = cmd + " gateway=" + gw strfile = popen(cmd) # end of if valid_data() else: info = "IP, subnet, or gateway are not in the" info = info + "correct format: xxx.xxx.xxx.xxx" tkMessageBox.showinfo("Nothing Changed", info) # ================================================== def SetOrigValues(o, w, d, dd): # ------------------------- # Revert button was pressed #-------------------------- info = "Are you SURE you want to lose these values\n" info = info + "and replace them with the original values?\n" RestoreOriginals = tkMessageBox.askyesno("Restore Originals?", info) if (RestoreOriginals): # ---------------------------------------------- # Remove the values currently in the GUI fields # ---------------------------------------------- # o = list of original values w[0].delete(0, END) w[2].delete(0, END) w[3].delete(0, END) w[4].delete(0, END) # ---------------------------------------------- # Insert the original values in the GUI fields # ---------------------------------------------- w[0].insert(0, o[0]) d.set(o[1]) w[2].insert(0, o[2]) w[3].insert(0, o[3]) w[4].insert(0, o[4]) # ----------------------------------- # Call the function to do the work # ----------------------------------- # The 0 tells the function not to verify with the user again SetValues(o, w, d, dd, 0) # ================================================== def DHCP_change(v): print # ================================================== def DNS_DHCP_change(v): print # ================================================== def getIPinfo(ifaces): # (iface name, DHCP enabled?, IP, subnet mask, gateway) ipinfo = []; i = 0; # For each enabled interface, grab the return of: # netsh interface ipv4 show addresses + name="" # and parse from the IP Address line for aif in ifaces: t = [] # aif[0] = name, aif[1] = state cmd = "netsh interface ipv4 show addresses name=\"" + aif[0] + "\"" strfile = popen(cmd) line = strfile.readline() while len(line) < 5: line = strfile.readline() # If this is the line we want... tpl = line.rpartition("interface ") iface = tpl[2].strip("\"\n ") if (iface == aif[0]): # Append the state t.append(aif[1]) # Append the name t.append(aif[0]) # Find the line for DHCP enabled line = strfile.readline() tpl = line.rpartition(" ") t.append(tpl[2].strip("\n ")) if (aif[1] == "Enabled"): # Find the line for IP Address line = strfile.readline() tpl = line.rpartition(" ") t.append(tpl[2].strip("\n ")) # Get the subnet mask line = strfile.readline() tpl = line.rpartition(" ") tpl = tpl[2].rpartition("mask ") t.append(tpl[2].strip("\n) ")) # note the paren in the strip arg # This is to delete the trailing paren # Get the gateway line = strfile.readline() tpl = line.rpartition(" ") t.append(tpl[2].strip("\n ")) else: t.append("DISABLED") t.append("DISABLED") t.append("DISABLED") ipinfo.append(t) # Get the DNS info and append to ipinfo ## ipinfo.append("0.0.0.0") # Holding text - DNS Primary ## ipinfo.append("0.0.0.0") # Holding text - DNS Secondary ## ipinfo.append("Yes") # Holding text - DNS DHCP? return ipinfo # ================================================== # ================================================== def getDNS(ifaces): # ifaces = [(iface_name, state), ... ] dnsinfo = []; # All interfaces' info combined into one list to return i = 0; # For each enabled interface, grab the return of: # netsh interface ipv4 show dnsserver name="" # and parse to extract: # 1. If it is statically configured or DHCP # 2. All DNS Server IP addresses for aif in ifaces: a = [] # The list of information obtained for this interface # aif[0] = name, aif[1] = state cmd = "netsh interface ipv4 show dnsserver name=\"" + aif[0] + "\"" # This assumes we'll find the interface on the netsh call a.append(aif[0]) # Execute the system command strfile = popen(cmd) # Read a line, but we will ignore it (blank) line = strfile.readline() # Read the next line - and ignore it (title line of results from the command executed) line = strfile.readline() # This line should be the one we want line = strfile.readline() # Does the line end with "DHCP:"? tpl = line.rpartition("DHCP:") if (tpl[1].strip() == "DHCP:"): a.append("DHCP") primary = tpl[2].strip() # Primary DNS IP address # Get the secondary DNS IP address from the next line line = strfile.readline(); tpl = line.rpartition(".") if (tpl[1] != ""): secondary = tpl[0].strip() + "." + tpl[2].strip() else: secondary = "UNDEFINED" a.append(primary) a.append(secondary) else: a.append("STATIC") tpl = line.rpartition("Servers:") primary = tpl[2].strip() a.append(primary) # The primary DNS IP address # ------------------ # TO DO - Setup secondary static DNS servers to see how the output is configured # ------------------ a.append("") # Not sure how the secondary address shows up # Append all of this interface's info onto the list to return dnsinfo.append(a) return dnsinfo # ================================================== def getInterfaces(): words = []; ifaces = []; # Grab the return of: # netsh int show interface # and parse for the words at the end of each line # cmd = "netsh int show interface" strfile = popen(cmd) line = strfile.readline() while line: line = strfile.readline() # Get the first word of the line tpl = line.partition(" ") word = tpl[0] # Is this a line we care about? if (word=="Disabled" or word=="Enabled"): state = word # Get the last words in the line # Algorithm: Append words found to list. Remove all words # in the queue when two or more spaces are next to # each other. words.append(word) if (tpl[2][0] == " "): words=[]; tpl = tpl[2].rpartition(" ") iface = tpl[2].strip() ifaces.append((iface, state)) return ifaces # ================================================== # ================================================== def isVista(): rval = False cmd = "ver" strfile = popen(cmd) line = strfile.readline() while len(line) < 5: line = strfile.readline() tpl = line.partition("Version ") vnum = tpl[2][0] # Character 0 of the con of the tuple if (vnum == "6"): rval = True return rval # ================================================== # ================================================== def main(): enabled_ifaces = []; ORIGINALS = []; # Run this program only on Vista if (isVista()): # ---------------- # Data extraction # ---------------- # Get the state of all the network interfaces ifaces = getInterfaces(); # Get the DNS settings for the network interfaces dnsinfo = getDNS(ifaces); # Find the enabled interfaces # for i in ifaces: # if (i[1] == "Enabled"): # enabled_ifaces.append(i[0]); # ipinfo = getIPinfo(enabled_ifaces) ipinfo = getIPinfo(ifaces) # Send all ifaces, including the state # ipinfo = [(iface_enabled? iface name, DHCP enabled?, IP, subnet mask, gateway), ... ] # ---------------- # Prepare the GUI # ---------------- L_T = [] # Labels for titles L_F = [] # Labels for data fields dhcpstate = [] dnsdhcpstate = [] WIDGETS = [] chbut=[] app = Tk() app.title(window_title) str1 = "This GUI allows you to set networking parameters in Vista. " x = Label(app, text=str1, justify="left") L_T.append(x) L_T[0].grid(row=0, column=0, rowspan=1, columnspan=11, padx=1, pady=10) # Place the column headers x = Label(app, text="Available?") L_T.append(x) L_T[1].grid(row=2, column=0, rowspan=1, columnspan=1, padx=1, pady=1) x = Label(app, text="Interface Name") L_T.append(x) L_T[2].grid(row=2, column=1, rowspan=1, columnspan=1, padx=1, pady=1) x = Label(app, text="Use DHCP?") L_T.append(x) L_T[3].grid(row=2, column=2, rowspan=1, columnspan=1, padx=1, pady=1) x = Label(app, text="IP Address") L_T.append(x) L_T[4].grid(row=2, column=3, rowspan=1, columnspan=1, padx=1, pady=1) x = Label(app, text="Subnet Mask") L_T.append(x) L_T[5].grid(row=2, column=4, rowspan=1, columnspan=1, padx=1, pady=1) x = Label(app, text="Default Gateway") L_T.append(x) L_T[6].grid(row=2, column=5, rowspan=1, columnspan=1, padx=1, pady=1) x = Label(app, text="DNS Primary") L_T.append(x) L_T[7].grid(row=2, column=6, rowspan=1, columnspan=1, padx=1, pady=1) x = Label(app, text="DNS Secondary") L_T.append(x) L_T[8].grid(row=2, column=7, rowspan=1, columnspan=1, padx=1, pady=1) x = Label(app, text="DHCP DNS?") L_T.append(x) L_T[9].grid(row=2, column=8, rowspan=1, columnspan=1, padx=1, pady=1) j = -1 ifacenum = -1 rownum = 4 for i in ipinfo: ifacenum = ifacenum + 1 j=j+1 rownum = rownum + 1 x = IntVar() dhcpstate.append(x) y = IntVar() dnsdhcpstate.append(y) vals = [] orig = [] # The state of the interface if (i[0]=="Disabled"): x = Label(app, text="No") else: x = Label(app, text="Yes") L_F.append(x) L_F[j].grid(row=rownum, column=0, rowspan=1, columnspan=1, padx=1, pady=1) # The name of the interface j=j+1 x = Entry(app, width=30, relief="sunken") x.insert(0, i[1]) L_F.append(x) L_F[j].grid(row=rownum, column=1, rowspan=1, columnspan=1, padx=1, pady=1) vals.append(x) orig.append(i[1]) # DHCP? j=j+1 x = Checkbutton(app, variable=dhcpstate[ifacenum], command=(lambda v=dhcpstate[ifacenum]: DHCP_change(v))) if (i[2]=="Yes"): x.select() orig.append(1) else: x.deselect() orig.append(0) L_F.append(x) L_F[j].grid(row=rownum, column=2, rowspan=1, columnspan=1, padx=1, pady=1) vals.append(x) # IP Address j=j+1 x = Entry(app, width=15, relief="sunken") x.insert(0, i[3]) L_F.append(x) L_F[j].grid(row=rownum, column=3, rowspan=1, columnspan=1, padx=1, pady=1) vals.append(x) orig.append(i[3]) # Subnet mask j=j+1 x = Entry(app, width=15, relief="sunken") x.insert(0, i[4]) L_F.append(x) L_F[j].grid(row=rownum, column=4, rowspan=1, columnspan=1, padx=1, pady=1) vals.append(x) orig.append(i[4]) # Gateway j=j+1 x = Entry(app, width=15, relief="sunken") x.insert(0, i[5]) L_F.append(x) L_F[j].grid(row=rownum, column=5, rowspan=1, columnspan=1, padx=1, pady=1) vals.append(x) orig.append(i[5]) # DNS Primary Address j=j+1 x = Entry(app, width=15, relief="sunken") x.insert(0, dnsinfo[ifacenum][2]) L_F.append(x) L_F[j].grid(row=rownum, column=6, rowspan=1, columnspan=1, padx=1, pady=1) vals.append(x) orig.append(dnsinfo[ifacenum][3]) # Just Testing valid_data(dnsinfo[ifacenum][2]) # DNS Secondary Address j=j+1 x = Entry(app, width=15, relief="sunken") x.insert(0, dnsinfo[ifacenum][3]) L_F.append(x) L_F[j].grid(row=rownum, column=7, rowspan=1, columnspan=1, padx=1, pady=1) vals.append(x) orig.append(dnsinfo[ifacenum][3]) # DNS DHCP? j=j+1 x = Checkbutton(app, variable=dnsdhcpstate[ifacenum], command=(lambda v=dnsdhcpstate[ifacenum]: DNS_DHCP_change(v))) if (dnsinfo[ifacenum][1]=="DHCP"): x.select() orig.append(1) else: x.deselect() orig.append(0) L_F.append(x) L_F[j].grid(row=rownum, column=8, rowspan=1, columnspan=1, padx=1, pady=1) vals.append(x) # A list of all the widgets in the window WIDGETS.append(vals) # A list of the original values of the widgets ORIGINALS.append(orig) # The change button j=j+1 x = Button(app, relief="raised", text="Set these values", command=(lambda O=ORIGINALS[ifacenum], W=WIDGETS[ifacenum], d=dhcpstate[ifacenum], dd=dnsdhcpstate[ifacenum]: SetValues(O, W, d, dd, 1))) L_F.append(x) L_F[j].grid(row=rownum, column=9, rowspan=1, columnspan=1, padx=5, pady=5) chbut.append(x) # The revert button j=j+1 x = Button(app, relief="raised", text="Revert to original values", command=(lambda O=ORIGINALS[ifacenum], W=WIDGETS[ifacenum], d=dhcpstate[ifacenum], dd=dnsdhcpstate[ifacenum]: SetOrigValues(O, W, d, dd))) L_F.append(x) L_F[j].grid(row=rownum, column=10, rowspan=1, columnspan=1, padx=5, pady=5) # -------------------------------- # Run the message-processing loop # -------------------------------- app.mainloop() # ---------------------------------------- # Message loop is done - kill the process # ---------------------------------------- app.destroy() else: print("I'm sorry - this version only for Vista...") #system("pause") # ================================================== main()