From 512e17969e8e2ba3cf0e8f78940a59a35e355770 Mon Sep 17 00:00:00 2001
From: chiihero <853879993@qq.com>
Date: Fri, 28 Dec 2018 16:18:33 +0800
Subject: [PATCH 1/8] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=8E=B7=E5=8F=96?=
=?UTF-8?q?=E8=B7=AF=E5=BE=84=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Frame.py | 5 +++--
login.py | 1 -
ver_code.py | 1 -
zqu_auto_login.py | 4 ++--
4 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/Frame.py b/Frame.py
index 7d0e0a4..a5028b6 100644
--- a/Frame.py
+++ b/Frame.py
@@ -1,7 +1,7 @@
import wx # 引入wx模块
import os
from configparser import ConfigParser
-
+import sys
class MyFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, id=wx.ID_ANY, title="肇庆学院校园网自动登录", pos=wx.DefaultPosition,
@@ -27,7 +27,7 @@ def __init__(self, parent):
self.Layout()
self.Centre(wx.BOTH)
- file = "conf.ini"
+ file = os.path.dirname(os.path.abspath(sys.argv[0]))+"/conf.ini"
conf = ConfigParser()
conf.read(file , encoding='utf-8')
# 获取数据
@@ -35,6 +35,7 @@ def __init__(self, parent):
userid = conf.get('user', 'userid')
password = conf.get('user', 'password')
check=conf.get('user','check')
+
self.userid.SetValue(userid)
self.password.SetValue(password)
if check=="True":
diff --git a/login.py b/login.py
index c7d5910..3ccceff 100644
--- a/login.py
+++ b/login.py
@@ -1,7 +1,6 @@
import requests
import json
import os
-
import logging
from time import sleep
from datetime import datetime
diff --git a/ver_code.py b/ver_code.py
index 583e495..950d94c 100644
--- a/ver_code.py
+++ b/ver_code.py
@@ -1,6 +1,5 @@
from PIL import Image
import imagehash
-import os
def validation_code_recognition(v_code_image):
diff --git a/zqu_auto_login.py b/zqu_auto_login.py
index ba0c014..f86a68a 100644
--- a/zqu_auto_login.py
+++ b/zqu_auto_login.py
@@ -16,7 +16,7 @@ def __init__(self,userid, password, check): # 线程实例化时立即启动
self.userid =userid
self.password = password
self.check = check
- self.config_file = os.getcwd()+"/conf.ini"
+ self.config_file = os.path.dirname(os.path.abspath(sys.argv[0]))+"\conf.ini"
self.conf = ConfigParser()
self.log_level = logging.INFO
self.begin_time = ""
@@ -102,7 +102,7 @@ def hideFile(filePath):
def autostart(self):
name = 'AutoLogin' # 要添加的项值名称
# filePath = os.path.realpath(__file__) # 测试使用
- filePath = os.getcwd()+"\zqu_auto_login.exe"#正式版使用
+ filePath = os.path.abspath(sys.argv[0])#正式版使用
if 'Windows' in platform.system():
try:
if self.check:
From 2bd5d51b562df1cdbefa8957962ff22c6d989a08 Mon Sep 17 00:00:00 2001
From: chiihero <853879993@qq.com>
Date: Sun, 3 Mar 2019 23:41:57 +0800
Subject: [PATCH 2/8] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E4=B8=80=E4=BA=9B?=
=?UTF-8?q?=E5=B0=8F=E7=BB=86=E8=8A=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
1.log文件位置修复
2.窗口大小固定
---
Frame.py | 14 ++++++++++----
zqu_auto_login.py | 8 ++++++--
2 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/Frame.py b/Frame.py
index a5028b6..6fca0a0 100644
--- a/Frame.py
+++ b/Frame.py
@@ -5,8 +5,12 @@
class MyFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, id=wx.ID_ANY, title="肇庆学院校园网自动登录", pos=wx.DefaultPosition,
- size=wx.Size(320, 174), style=wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL)
+ size=wx.Size(320, 174),
+ style=wx.DEFAULT_FRAME_STYLE |
+ wx.TAB_TRAVERSAL)
self.SetSizeHints(wx.DefaultSize, wx.DefaultSize)
+ self.SetMaxSize((320, 174))#固定窗口
+ self.SetMinSize((320, 174))
gSizer = wx.GridSizer(0, 2, 0, 0)
self.m_staticText2 = wx.StaticText(self, wx.ID_ANY, u"学号", wx.DefaultPosition, wx.DefaultSize, 0)
self.m_staticText2.Wrap(-1)
@@ -27,11 +31,13 @@ def __init__(self, parent):
self.Layout()
self.Centre(wx.BOTH)
- file = os.path.dirname(os.path.abspath(sys.argv[0]))+"/conf.ini"
+
+
+ self.config_file = os.path.dirname(os.path.abspath(sys.argv[0]))+"/conf.ini"
conf = ConfigParser()
- conf.read(file , encoding='utf-8')
+ conf.read(self.config_file , encoding='utf-8')
# 获取数据
- if os.path.exists(file):
+ if os.path.exists(self.config_file):
userid = conf.get('user', 'userid')
password = conf.get('user', 'password')
check=conf.get('user','check')
diff --git a/zqu_auto_login.py b/zqu_auto_login.py
index f86a68a..0b73939 100644
--- a/zqu_auto_login.py
+++ b/zqu_auto_login.py
@@ -10,13 +10,17 @@
import logging
import sys
+
+location = os.path.dirname(os.path.abspath(sys.argv[0]))
+
+
class TestThread(threading.Thread):
def __init__(self,userid, password, check): # 线程实例化时立即启动
threading.Thread.__init__(self)
self.userid =userid
self.password = password
self.check = check
- self.config_file = os.path.dirname(os.path.abspath(sys.argv[0]))+"\conf.ini"
+ self.config_file = location+"\conf.ini"
self.conf = ConfigParser()
self.log_level = logging.INFO
self.begin_time = ""
@@ -89,7 +93,7 @@ def readConfig(self):
format='[%(asctime)s] - %(levelname)s - %(module)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S',
level=self.log_level,
- handlers=[logging.FileHandler("run.log"), logging.StreamHandler()]
+ handlers=[logging.FileHandler(location+"\\run.log"), logging.StreamHandler()]
)
# 隐藏配置文件
From a5173feb69f6fed8d2372ee518c15516bf7a1d8e Mon Sep 17 00:00:00 2001
From: chiihero <853879993@qq.com>
Date: Sun, 3 Mar 2019 23:45:20 +0800
Subject: [PATCH 3/8] =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E5=8C=96=E4=BB=A3?=
=?UTF-8?q?=E7=A0=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Frame.py | 16 ++++++++--------
zqu_auto_login.py | 27 ++++++++++++++++-----------
2 files changed, 24 insertions(+), 19 deletions(-)
diff --git a/Frame.py b/Frame.py
index 6fca0a0..83b1e68 100644
--- a/Frame.py
+++ b/Frame.py
@@ -2,6 +2,8 @@
import os
from configparser import ConfigParser
import sys
+
+
class MyFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, id=wx.ID_ANY, title="肇庆学院校园网自动登录", pos=wx.DefaultPosition,
@@ -9,7 +11,7 @@ def __init__(self, parent):
style=wx.DEFAULT_FRAME_STYLE |
wx.TAB_TRAVERSAL)
self.SetSizeHints(wx.DefaultSize, wx.DefaultSize)
- self.SetMaxSize((320, 174))#固定窗口
+ self.SetMaxSize((320, 174)) # 固定窗口
self.SetMinSize((320, 174))
gSizer = wx.GridSizer(0, 2, 0, 0)
self.m_staticText2 = wx.StaticText(self, wx.ID_ANY, u"学号", wx.DefaultPosition, wx.DefaultSize, 0)
@@ -31,20 +33,18 @@ def __init__(self, parent):
self.Layout()
self.Centre(wx.BOTH)
-
-
- self.config_file = os.path.dirname(os.path.abspath(sys.argv[0]))+"/conf.ini"
+ self.config_file = os.path.dirname(os.path.abspath(sys.argv[0])) + "/conf.ini"
conf = ConfigParser()
- conf.read(self.config_file , encoding='utf-8')
+ conf.read(self.config_file, encoding='utf-8')
# 获取数据
if os.path.exists(self.config_file):
userid = conf.get('user', 'userid')
password = conf.get('user', 'password')
- check=conf.get('user','check')
+ check = conf.get('user', 'check')
self.userid.SetValue(userid)
self.password.SetValue(password)
- if check=="True":
+ if check == "True":
self.check_start.SetValue(True)
# 绑定按钮的单击事件
@@ -53,5 +53,5 @@ def __init__(self, parent):
def __del__(self):
pass
- def open(self, event ):
+ def open(self, event):
event.Skip()
diff --git a/zqu_auto_login.py b/zqu_auto_login.py
index 0b73939..8ce6c43 100644
--- a/zqu_auto_login.py
+++ b/zqu_auto_login.py
@@ -10,29 +10,29 @@
import logging
import sys
-
location = os.path.dirname(os.path.abspath(sys.argv[0]))
class TestThread(threading.Thread):
- def __init__(self,userid, password, check): # 线程实例化时立即启动
+ def __init__(self, userid, password, check): # 线程实例化时立即启动
threading.Thread.__init__(self)
- self.userid =userid
+ self.userid = userid
self.password = password
self.check = check
- self.config_file = location+"\conf.ini"
+ self.config_file = location + "\conf.ini"
self.conf = ConfigParser()
self.log_level = logging.INFO
self.begin_time = ""
self.end_time = ""
def run(self): # 线程执行的代码
- writeConfig(self)#写入数据到配置文件
+ writeConfig(self) # 写入数据到配置文件
readConfig(self)
autostart(self)
logging.info('学号:' + self.userid + ' 密码:' + self.password)
loginstart(self)
+
# 创建mainWin类并传入my_win.MyFrame
class mainWin(Frame.MyFrame):
def GetValue(self, event):
@@ -50,6 +50,7 @@ def open(self, event):
else:
os._exit(0)
+
# 写入配置文件
def writeConfig(self):
if not os.path.exists(self.config_file):
@@ -74,9 +75,10 @@ def writeConfig(self):
with open(self.config_file, 'w') as fw: # 循环写入
self.conf.write(fw)
+
def readConfig(self):
self.conf.read(self.config_file, encoding='utf-8')
- #获取开始时间和结束时间
+ # 获取开始时间和结束时间
self.begin_time = self.conf.get('run', 'begin_time')
self.end_time = self.conf.get('run', 'end_time')
@@ -93,20 +95,22 @@ def readConfig(self):
format='[%(asctime)s] - %(levelname)s - %(module)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S',
level=self.log_level,
- handlers=[logging.FileHandler(location+"\\run.log"), logging.StreamHandler()]
+ handlers=[logging.FileHandler(location + "\\run.log"), logging.StreamHandler()]
)
+
# 隐藏配置文件
def hideFile(filePath):
if 'Windows' in platform.system():
cmd = 'attrib +h "' + filePath + '"'
os.system(cmd)
+
# 开机自启
def autostart(self):
name = 'AutoLogin' # 要添加的项值名称
# filePath = os.path.realpath(__file__) # 测试使用
- filePath = os.path.abspath(sys.argv[0])#正式版使用
+ filePath = os.path.abspath(sys.argv[0]) # 正式版使用
if 'Windows' in platform.system():
try:
if self.check:
@@ -118,22 +122,23 @@ def autostart(self):
except:
logging.error('修改开机项失败')
+
# 子线程要执行的代码
def loginstart(self):
logging.debug("第一次运行测试")
- login.test(self)#第一次启动
+ login.test(self) # 第一次启动
sleep(5)
if self.conf.get('run', 'time_unit') == 'minutes':
schedule.every(self.conf.getint('run', 'every_time')).minutes.do(login.test, self)
elif self.conf.get('run', 'time_unit') == 'seconds':
- schedule.every(self.conf.getint('run', 'every_time')).seconds.do(login.test, self)#测试
+ schedule.every(self.conf.getint('run', 'every_time')).seconds.do(login.test, self) # 测试
else:
logging.critical('conf.ini配置错误:{}'.format(
self.conf.getint('run', 'every_time'),
self.conf.get('run', 'time_unit')
))
sys.exit(1)
- while (1):
+ while 1:
schedule.run_pending()
sleep(1)
From f9384a5ba12fc5dcb022f511a7342deb7d176e05 Mon Sep 17 00:00:00 2001
From: chiihero <853879993@qq.com>
Date: Mon, 4 Mar 2019 01:05:34 +0800
Subject: [PATCH 4/8] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=9C=80=E5=B0=8F?=
=?UTF-8?q?=E5=8C=96=E6=A8=A1=E5=BC=8F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Frame.py | 66 ++++++++++++++++++++++++++++++++++++++++++----
icon.ico | Bin 0 -> 185153 bytes
zqu_auto_login.py | 4 +--
3 files changed, 63 insertions(+), 7 deletions(-)
create mode 100644 icon.ico
diff --git a/Frame.py b/Frame.py
index 83b1e68..0154bba 100644
--- a/Frame.py
+++ b/Frame.py
@@ -2,15 +2,59 @@
import os
from configparser import ConfigParser
import sys
+import wx.adv
+
+TITLE = "肇庆学院校园网自动登录"
+ICON = "icon.ico" # 图标地址
+
+class MyTaskBarIcon(wx.adv.TaskBarIcon):
+ ID_EXIT = wx.NewId() # 菜单选项“退出”的ID
+ ID_SHOW_WEB = wx.NewId() # 菜单选项“显示页面”的ID
+
+ def __init__(self,frame):
+ wx.adv.TaskBarIcon.__init__(self)
+ self.frame = frame
+ # self.TITLE = "肇庆学院校园网自动登录"
+ self.SetIcon(wx.Icon(ICON), TITLE) # 设置图标和标题
+ self.Bind(wx.EVT_MENU, self.onExit, id=self.ID_EXIT) # 绑定“退出”选项的点击事件
+ self.Bind(wx.EVT_MENU, self.onShow, id=self.ID_SHOW_WEB) # 绑定“显示页面”选项的点击事件
+ # self.Bind(wx.EVT_COMMAND_LEFT_DCLICK, self.OnTaskBarLeftDClick) # 绑定“显示页面”选项的点击事件
+
+ # “退出”选项的事件处理器
+ def onExit(self, event):
+ wx.Exit()
+
+ # “显示页面”选项的事件处理器
+ def onShow(self, event):
+ self.frame.Show(True)
+ self.frame.Raise()
+
+ # 双击显示选项的事件处理器
+ def OnTaskBarLeftDClick(self, event):
+ pass
+ # if self.frame.IsIconized():
+ # self.frame.Iconize(False)
+ # if not self.frame.IsShown():
+ # self.frame.Show(True)
+ # self.frame.Raise()
+
+ # 创建菜单选项
+ def CreatePopupMenu(self):
+ menu = wx.Menu()
+ menu.Append(self.ID_SHOW_WEB, '进入程序')
+ menu.Append(self.ID_EXIT, '退出')
+ return menu
+
class MyFrame(wx.Frame):
def __init__(self, parent):
- wx.Frame.__init__(self, parent, id=wx.ID_ANY, title="肇庆学院校园网自动登录", pos=wx.DefaultPosition,
+ wx.Frame.__init__(self, parent, id=wx.ID_ANY, title=TITLE, pos=wx.DefaultPosition,
size=wx.Size(320, 174),
style=wx.DEFAULT_FRAME_STYLE |
wx.TAB_TRAVERSAL)
self.SetSizeHints(wx.DefaultSize, wx.DefaultSize)
+ self.taskBarIcon=MyTaskBarIcon(self)#显示系统托盘图标
self.SetMaxSize((320, 174)) # 固定窗口
self.SetMinSize((320, 174))
gSizer = wx.GridSizer(0, 2, 0, 0)
@@ -19,7 +63,7 @@ def __init__(self, parent):
gSizer.Add(self.m_staticText2, 0, wx.ALL, 5)
self.userid = wx.TextCtrl(self, wx.ID_ANY, u"2016241314xx", wx.DefaultPosition, wx.DefaultSize, 0)
gSizer.Add(self.userid, 0, wx.ALL, 5)
- self.m_staticText1 = wx.StaticText(self, wx.ID_ANY, u"密码(8位)", wx.DefaultPosition, wx.DefaultSize, 0)
+ self.m_staticText1 = wx.StaticText(self, wx.ID_ANY, u"密码(电信8位;移动6位)", wx.DefaultPosition, wx.DefaultSize, 0)
self.m_staticText1.Wrap(-1)
gSizer.Add(self.m_staticText1, 0, wx.ALL, 5)
self.password = wx.TextCtrl(self, wx.ID_ANY, u"xxxxxxxx", wx.DefaultPosition, wx.DefaultSize, 0)
@@ -47,11 +91,23 @@ def __init__(self, parent):
if check == "True":
self.check_start.SetValue(True)
- # 绑定按钮的单击事件
+
+ # 绑定按钮的单击事件
self.Bind(wx.EVT_BUTTON, self.open, self.btn_open)
+ self.Bind(wx.EVT_ICONIZE, self.OnIconfiy) # 窗口最小化时,调用OnIconfiy,注意Wx窗体上的最小化按钮,触发的事件是 wx.EVT_ICONIZE,而根本就没有定义什么wx.EVT_MINIMIZE,但是最大化,有个wx.EVT_MAXIMIZE。
+ self.Bind(wx.EVT_CLOSE, self.OnClose)
+
+ def open(self, event):
+ event.Skip()
+
+ def OnIconfiy(self, event):
+ self.Hide()
+ self.Iconize(False)
+
+ def OnClose(self, event):
+ self.taskBarIcon.Destroy()
+ self.Destroy()
def __del__(self):
pass
- def open(self, event):
- event.Skip()
diff --git a/icon.ico b/icon.ico
new file mode 100644
index 0000000000000000000000000000000000000000..465ef254844ee6bb65f78ab1bea92bc74d0f66ea
GIT binary patch
literal 185153
zcmX_n2RNH=)P7=bTASKMmDb*3)@l{4wkVA~T6+^Kwwgst%|vO@YD3LdV$WJZ3AK0Z
zm1yjL`uo1`@49lu8+pC&d!BRd^PKyf8vp
F`M=-S1^}jvNB~k&|NDJm;(Iy?fS><=
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