Das Aktualisieren von PowerShell unter Windows ist ein manueller Vorgang, der jedoch langweilig geworden ist. Halbautomatisiert.
Wenn Sie pshupdate.py, den Hauptteil des Skripts, in Python ausführen, wird die Version automatisch überprüft und bei Bedarf aktualisiert (geplant).
Ich mache das nicht aufwendig, weil ich es nur so geschrieben habe, wie ich es tun soll, aber ich werde es schreiben.
Da es sich bei der Version um eine Zeichenfolge mit der Form "v3.2.1" handelt, wird der Rest nach dem Entfernen nur des ersten zusätzlichen Zeichens in ein Triplett von Zeichenfolgen umgewandelt, um daraus einen Versionstyp zu machen. Wenn Sie (Get-Host) .Version | Format-List *
mit pwsh ausführen, erhalten Sie 6 Schlüssel, aber ich habe die letzten 3 nicht verwendet. 3 und 3 sind genug! Yoshi!
In der zweiten Hälfte wird ein großer und kleiner Vergleich durchgeführt. Aus Gründen der Flexibilität habe ich beschlossen, None, 0 und -1 als Werte für "Minor" und "Build" zu behandeln, was das Ergebnis ärgerlich machte.
import re
from typing import NamedTuple
class Version(NamedTuple):
"""A triplet (Major, Minor, Build) of strings.
Note that every element can have the None value.
"""
Major: str
Minor: str = '-1'
Build: str = '-1'
def formatVersion(self) ->str:
"""Return a string "<Major>.<Minor>.<Build>".\n
Note that this function returns None if Version is None.
"""
if (self.Major is None):
return None
else:
ls = [self.Major]
if (self.Minor != None) and (self.Minor != '-1'):
ls.append(self.Minor)
if (self.Build != None) and (self.Build != '-1'):
ls.append(self.Build)
return '.'.join(ls)
def __eq__(self,other) -> bool:
if(not isinstance(other,Version)):
raise TypeError("Version data cannot compare to other type data.")
if(self.Major != other.Major):
return False
elif(not self.Major):
return True
elif(self.Minor != other.Minor):
if (self.Minor != None) and (self.Minor != '0') and (self.Minor != '-1'):
return False
elif (other.Minor != None) and (other.Minor != '0') and (other.Minor != '-1'):
return False
elif(self.Build != other.Build):
if (self.Build != None) and (self.Build != '0') and (self.Build != '-1'):
return False
elif (other.Build != None) and (other.Build != '0') and (other.Build != '-1'):
return False
else:
return True
def __le__(self,other) -> bool:
if(not isinstance(other,Version)):
raise TypeError("Version data cannot compare to other type data.")
if(self.Major.isdecimal()) and (other.Major.isdecimal()):
if(int(self.Major) < int(other.Major)):
return True
else:
pass
elif(not self.Major.isdecimal()) and (not other.Major.isdecimal()):
a, b = self.Major, other.Major
mslf = re.search(r'^\d*',a)
if mslf:
anum, atxt = a[:mslf.end()], a[mslf.end():]
else:
anum, atxt = None, a
moth = re.search(r'^\d*',b)
if moth:
bnum, btxt = b[:moth.end()], b[moth.end():]
else:
bnum, btxt = None, b
if(int(anum) < int(bnum)):
return True
elif(int(anum)==int(bnum)):
if(atxt < btxt):
return True
elif(atxt == btxt):
pass
else:
return False
else:
return False
else:
raise ValueError("two Version data are not compareable.")
if(self.Minor.isdecimal()) and (other.Minor.isdecimal()):
if(int(self.Minor) < int(other.Minor)):
return True
else:
pass
elif(not self.Minor.isdecimal()) and (not other.Minor.isdecimal()):
a, b = self.Minor, other.Minor
mslf = re.search(r'^\d*',a)
if mslf:
anum, atxt = a[:mslf.end()], a[mslf.end():]
else:
anum, atxt = None, a
moth = re.search(r'^\d*',b)
if moth:
bnum, btxt = b[:moth.end()], b[moth.end():]
else:
bnum, btxt = None, b
if(int(anum) < int(bnum)):
return True
elif(int(anum)==int(bnum)):
if(atxt < btxt):
return True
elif(atxt == btxt):
pass
else:
return False
else:
return False
else:
raise ValueError("two Version data are not compareable.")
if(self.Build.isdecimal()) and (other.Build.isdecimal()):
if(int(self.Build) < int(other.Build)):
return True
else:
return False
elif(not self.Build.isdecimal()) and (other.Build.isdecimal()):
a, b = self.Build, other.Build
mslf = re.search(r'^\d*',a)
if mslf:
anum, atxt = a[:mslf.end()], a[mslf.end():]
else:
anum, atxt = None, a
moth = re.search(r'^\d*',b)
if moth:
bnum, btxt = b[:moth.end()], b[moth.end():]
else:
bnum, btxt = None, b
if(int(anum) < int(bnum)):
return True
elif(int(anum)==int(bnum)):
if(atxt < btxt):
return True
else:
return False
else:
return False
else:
raise ValueError("two Version data are not compareable.")
Ich habe auch eine Funktion erstellt, die eine Zeichenfolge in einen Versionstyp analysiert.
def parseVersion(s) ->Version:
"""input: a string or a list of strings
Parse a string like "v1.0.4"
"""
if(isinstance(s,bytes)):
s = s.decode()
if(isinstance(s,str)):
match = re.search(r'\d*\.\d*\.?',s)
if match:
token = s[match.start():].split('.',2)
if (len(token)==3):
return Version(token[0],token[1],token[2])
elif (len(token)==2):
return Version(token[0],token[1],None)
else:
return Version(token[0],None,None)
else:
match = re.search(r'[0-9]*',s)
if match:
return Version(s[match.start():],None,None)
else:
raise ValueError("function parseVersion didn't parse argument.")
elif(isinstance(s,list)):
for x in s[0:3]:
if(not isinstance(x,str)):
raise TypeError("function parseVersion(s) takes a string or a list of strings as the argument.")
try:
(major,minor,build) = s[0:3]
except ValueError:
raise
except:
print("Unexpected error in function 'parseVersion'")
raise
return Version(major,minor,build)
else:
raise TypeError("function parseVersion(s) takes a string or a list of strings as the argument.")
Klicken Sie auf die Github-API, um Informationen zur neuesten Version zu erhalten. ``
import ssl, urllib.request
import json
head_accept = "application/vnd.github.v3+json"
host = "api.github.com"
key_release = "repos/PowerShell/PowerShell/releases/latest"
print("Latest version of pwsh ... ", end='', flush=True)
context = ssl.create_default_context()
url = ''.join(["https://",host,"/",key_release])
try:
q = urllib.request.Request(url,headers={'accept':head_accept},method='GET')
with urllib.request.urlopen(q, context=context) as res:
content = json.load(res)
except urllib.error.HTTPError as err:
print(err.code)
except urllib.error.URLError as err:
print(err.reason)
except json.JSONDecodeError as err:
print(err.msg)
v_latest = parseVersion(content['tag_name'])
print(v.formatVersion())
Holen Sie sich Versionsinformationen mit pwsh -v
. Da "Zeit" nur für die Gewichtsverarbeitung importiert wird, kann nichts gesagt werden, wenn gesagt wird, dass sie tatsächlich nicht benötigt wird.
import time
import subprocess
print("Current version of pwsh ... ", end='', flush=True)
time.sleep(0.5)
cpl_pwsh = subprocess.run("pwsh -v",capture_output=True)
v_local = parseVersion(cpl_pwsh.stdout.strip())
print(v_local.formatVersion())
Ich habe nicht viel ausgearbeitet.
import ssl, urllib.request
import json
directory_download = R"path\to\directoryof\installer"
if(v_local < v_latest):
print("Later version available.")
print("Please wait...")
aslist = content['assets']
vlatest = attr_latest.getstr_version()
targetname = '-'.join(["PowerShell",vlatest,"win-x64.msi"])
targeturl = None
for asset in aslist:
if(asset['name'] == targetname):
targeturl = asset['browser_download_url']
break
if targeturl:
try:
print("Downloading installer... ",end='',flush=True)
with urllib.request.urlopen(targeturl,context=context) as res:
dat_pack = res.read()
except urllib.error.HTTPError as err:
print(err.code)
except urllib.error.URLError as err:
print(err.reason)
except json.JSONDecodeError as err:
print(err.msg)
try:
path = '\\'.join([directory_download,targetname])
f_installer = open(path,mode='xb')
f_installer.write(dat_pack)
f_installer.close()
except OSError:
print()
raise
except:
print("Unexpected error occurred.")
raise
subprocess.run(path, stderr=subprocess.STDOUT)
else:
raise Exception("lost download url.")
elif(attr_pwsh.version == attr_latest.version):
print("Your pwsh is latest version.\n")
else:
raise Exception("unidentified exception occurred.")
Ich habe am Anfang und am Ende eine kleine Dekoration hinzugefügt, also sieht es so aus, wenn ich es laufen lasse. Natürlich ist es jetzt die neueste Version, also lasse ich es bis zum nächsten pwsh-Update, um zu testen, ob das Update ordnungsgemäß durchgeführt werden kann.
================================================
Powershell updater version 0.5.201114
by Lat.S (@merliborn)
Latest version of pwsh ... 7.1.0
Current version of pwsh ... 7.1.0
Your pwsh is latest version.
Push return key to quit:
================================================
Ich bin froh, dass ich lange Zeit alles tun konnte, was ich wollte, z. B. HTTPS verwenden, die API drücken, um Informationen zu erhalten, und überhaupt etwas mit Python machen. Die Tatsache, dass Typanmerkungen aufgrund der Dekorationen in Ausdrücken geschrieben werden können, war für mich als Person, die normalerweise ein typisiertes Leben führt, sehr schockierend.
Recommended Posts