TBD - when I got time. The templates are in the library, and all functions are mostly properly documented. This will only be done for completion's sake, and only once I got time to do so.
Last active
August 9, 2022 05:55
-
-
Save Gewerd-Strauss/05087cb4772d45d6581fa628dbaccc7c to your computer and use it in GitHub Desktop.
ScriptObj - Class for handling various script-related tasks - updating, printing error to debug/file with some filters, setting autostart etc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
launch.json | |
.vscode/ | |
.git/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; from RaptorX https://github.com/RaptorX/ScriptObj/blob/master/ScriptObj.ahk | |
/** | |
* ============================================================================ * | |
* @Author : RaptorX <[email protected]> | |
* @Script Name : Script Object | |
* @Script Version : 0.21.3 | |
* @Homepage : | |
* | |
* @Creation Date : November 09, 2020 | |
* @Modification Date: July 02, 2021 | |
* @Modification G.S.: 07.2022 | |
; @Description Modification G.S.: added field for GitHub-link, a Forum-link | |
and a credits-field, as well as a template | |
to quickly copy out into new scripts | |
Contains methods for saving and loading | |
config-files containing an array - | |
basically an integration of Wolf_II's | |
WriteIni/ReadIni with some adjustments | |
added Update()-functionality for non-zipped | |
remote files so that one can update a | |
A_ScriptFullPath-contained script from | |
f.e. GH. | |
Reworked the Update()-Method with help of | |
u/anonymous1184. | |
* | |
* @Description : | |
* ------------------- | |
* This is an object used to have a few common functions between scripts | |
* Those are functions and variables related to basic script information, | |
* upgrade and configuration. | |
* | |
* ============================================================================ * | |
*/ | |
; scriptName (opt) - Name of the script which will be | |
; shown as the title of the window and the main header | |
; version (opt) - Script Version in SimVer format, a "v" | |
; will be added automatically to this value | |
; author (opt) - Name of the author of the script | |
; credits (opt) - Name of credited people | |
; creditslink (opt) - Link to credited file, if any | |
; crtdate (opt) - Date of creation | |
; moddate (opt) - Date of modification | |
; homepagetext (opt) - Display text for the script website | |
; homepagelink (opt) - Href link to that points to the scripts | |
; website (for pretty links and utm campaing codes) | |
; ghlink (opt) - GitHubLink | |
; ghtext (opt) - GitHubtext | |
; forumlink (opt) - forumlink to the scripts forum page | |
; forumtext (opt) - forumtext | |
; donateLink (opt) - Link to a donation site | |
; email (opt) - Developer email | |
; Template | |
; FileGetTime, ModDate,%A_ScriptFullPath%,M | |
; FileGetTime, CrtDate,%A_ScriptFullPath%,C | |
; CrtDate:=SubStr(CrtDate,7, 2) "." SubStr(CrtDate,5,2) "." SubStr(CrtDate,1,4) | |
; ModDate:=SubStr(ModDate,7, 2) "." SubStr(ModDate,5,2) "." SubStr(ModDate,1,4) | |
; global script := { base : script | |
; ,name : regexreplace(A_ScriptName, "\.\w+") | |
; ,version : FileOpen(A_ScriptDir "\version.ini","r").Read() | |
; ,author : "Gewerd Strauss" | |
; ,authorID : "Laptop-C" | |
; ,authorlink : "" | |
; ,email : "" | |
; ,credits : "" | |
; ,creditslink : "" | |
; ,crtdate : CrtDate | |
; ,moddate : ModDate | |
; ,homepagetext : "" | |
; ,homepagelink : "" | |
; ,ghtext : "GH-Repo" | |
; ,ghlink : "https://github.com/Gewerd-Strauss/REPOSITORY_NAME" | |
; ,doctext : "" | |
; ,doclink : "" | |
; ,forumtext : "" | |
; ,forumlink : "" | |
; ,donateLink : "" | |
; ,resfolder : A_ScriptDir "\res" | |
; ,iconfile : "" | |
; ,rfile : "https://github.com/Gewerd-Strauss/REPOSITORY_NAME/archive/refs/heads/BRANCH_NAME.zip" | |
; ,vfile_raw : "https://raw.githubusercontent.com/Gewerd-Strauss/REPOSITORY_NAME/BRANCH_NAME/version.ini" | |
; ,vfile : "https://raw.githubusercontent.com/Gewerd-Strauss/REPOSITORY_NAME/BRANCH_NAME/version.ini" | |
; ,vfile_local : A_ScriptDir "\version.ini" | |
; ,config: [] | |
; ,configfile : A_ScriptDir "\INI-Files\" regexreplace(A_ScriptName, "\.\w+") ".ini" | |
; ,configfolder : A_ScriptDir "\INI-Files"} | |
/* | |
; For throwing errors via script.debug | |
script.Error:={ Level :"" | |
,Label :"" | |
,Message :"" | |
,Error :"" | |
,Vars: :[] | |
,AddInfo: :""} | |
if script.error | |
script.Debug(script.error.Level,script.error.Label,script.error.Message,script.error.AddInfo,script.error.Vars) | |
*/ | |
; script.Load() | |
; , script.Update(,,) ;; DO NOT ACTIVATE THISLINE UNTIL YOU DUMBO HAS FIXED THE DAMN METHOD. God damn it. | |
; Template End | |
class script | |
{ | |
static DBG_NONE := 0 | |
,DBG_ERRORS := 1 | |
,DBG_WARNINGS := 2 | |
,DBG_VERBOSE := 3 | |
static name := "" | |
,version := "" | |
,author := "" | |
,authorID := "" | |
,authorlink := "" | |
,email := "" | |
,credits := "" | |
,creditslink := "" | |
,crtdate := "" | |
,moddate := "" | |
,homepagetext := "" | |
,homepagelink := "" | |
,ghtext := "" | |
,ghlink := "" | |
,doctext := "" | |
,doclink := "" | |
,forumtext := "" | |
,forumlink := "" | |
,donateLink := "" | |
,resfolder := "" | |
,iconfile := "" | |
,vfile_local := "" | |
,vfile_remote := "" | |
,config := "" | |
,configfile := "" | |
,configfolder := "" | |
,icon := "" | |
,systemID := "" | |
,dbgFile := "" | |
,rfile := "" | |
,vfile := "" | |
,dbgLevel := this.DBG_NONE | |
,versionScObj := "0.21.3" | |
/** | |
Function: Update | |
Checks for the current script version | |
Downloads the remote version information | |
Compares and automatically downloads the new script file and reloads the script. | |
Parameters: | |
vfile - Version File | |
Remote version file to be validated against. | |
rfile - Remote File | |
Script file to be downloaded and installed if a new version is found. | |
Should be a zip file that will be unzipped by the function | |
Notes: | |
The versioning file should only contain a version string and nothing else. | |
The matching will be performed against a SemVer format and only the three | |
major components will be taken into account. | |
e.g. '1.0.0' | |
For more information about SemVer and its specs click here: <https://semver.org/> | |
*/ | |
Update(vfile:="", rfile:="",bSilentCheck:=true,Backup:=true) | |
{ | |
; Error Codes | |
static ERR_INVALIDVFILE := 1 | |
,ERR_INVALIDRFILE := 2 | |
,ERR_NOCONNECT := 3 | |
,ERR_NORESPONSE := 4 | |
,ERR_INVALIDVER := 5 | |
,ERR_CURRENTVER := 6 | |
,ERR_MSGTIMEOUT := 7 | |
,ERR_USRCANCEL := 8 | |
vfile:=(vfile=="")?this.vfile:vfile | |
,rfile:=(rfile=="")?this.rfile:rfile | |
{ | |
if RegexMatch(vfile,"\d+") || RegexMatch(rfile,"\d+") ;; allow skipping of the routine by simply returning here | |
return | |
; Error Codes | |
if (!regexmatch(vfile, "^((?:http(?:s)?|ftp):\/\/)?((?:[a-z0-9_\-]+\.)+.*$)")) | |
exception({code: ERR_INVALIDVFILE, msg: "Invalid URL`n`nThe version file parameter must point to a valid URL."}) | |
; This function expects a ZIP file | |
if (!regexmatch(rfile, "\.zip")) | |
exception({code: ERR_INVALIDRFILE, msg: "Invalid Zip`n`nThe remote file parameter must point to a zip file."}) | |
; Check if we are connected to the internet | |
http := comobjcreate("WinHttp.WinHttpRequest.5.1") | |
, http.Open("GET", "https://www.google.com", true) | |
, http.Send() | |
try | |
http.WaitForResponse(1) | |
catch e | |
throw {code: ERR_NOCONNECT, msg: e.message} | |
if (!bSilentCheck) | |
Progress, 50, 50/100, % "Checking for updates", % "Updating" | |
; Download remote version file | |
http.Open("GET", vfile, true) | |
http.Send(), http.WaitForResponse() | |
if !(http.responseText) | |
{ | |
Progress, OFF | |
try | |
throw exception("There was an error trying to download the ZIP file for the update.`n","script.Update()","The server did not respond.") | |
Catch, e | |
msgbox, 8240,% this.Name " - No response from server", % e.Message "`n`nCheck again later`, or contact the author/provider. Script will resume normal operation." | |
} | |
regexmatch(this.version, "\d+\.\d+\.\d+", loVersion) ;; as this.version is not updated automatically, instead read the local version file | |
; FileRead, loVersion,% A_ScriptDir "\version.ini" | |
d:=http.responseText | |
regexmatch(http.responseText, "\d+\.\d+\.\d+", remVersion) | |
if (!bSilentCheck) | |
{ | |
Progress, 100, 100/100, % "Checking for updates", % "Updating" | |
sleep 500 ; allow progress to update | |
} | |
Progress, OFF | |
; Make sure SemVer is used | |
if (!loVersion || !remVersion) | |
{ | |
try | |
throw exception("Invalid version.`n The update-routine of this script works with SemVer.","script.Update()","For more information refer to the documentation in the file`n" ) | |
catch, e | |
msgbox, 8240,% "Invalid Version", % e.What ":" e.Message "`n`n" e.Extra "'" e.File "'." | |
} | |
; Compare against current stated version | |
ver1 := strsplit(loVersion, ".") | |
, ver2 := strsplit(remVersion, ".") | |
, bRemoteIsGreater:=[0,0,0] | |
, newversion:=false | |
for i1,num1 in ver1 | |
{ | |
for i2,num2 in ver2 | |
{ | |
if (i1 == i2) | |
{ | |
if (num2 > num1) | |
{ | |
bRemoteIsGreater[i1]:=true | |
break | |
} | |
else if (num2 = num1) | |
bRemoteIsGreater[i1]:=false | |
else if (num2 < num1) | |
bRemoteIsGreater[i1]:=-1 | |
} | |
} | |
} | |
if (!bRemoteIsGreater[1] && !bRemoteIsGreater[2]) ;; denotes in which position (remVersion>loVersion) → 1, (remVersion=loVersion) → 0, (remVersion<loVersion) → -1 | |
if (bRemoteIsGreater[3] && bRemoteIsGreater[3]!=-1) | |
newversion:=true | |
if (bRemoteIsGreater[1] || bRemoteIsGreater[2]) | |
newversion:=true | |
if (bRemoteIsGreater[1]=-1) | |
newversion:=false | |
if (bRemoteIsGreater[2]=-1) && (bRemoteIsGreater[1]!=1) | |
newversion:=false | |
if (!newversion) | |
{ | |
if (!bSilentCheck) | |
msgbox, 8256, No new version available, You are using the latest version.`n`nScript will continue running. | |
return | |
} | |
else | |
{ | |
; If new version ask user what to do "C:\Users\CLAUDI~1\AppData\Local\Temp\AHK_LibraryGUI | |
; Yes/No | Icon Question | System Modal | |
msgbox % 0x4 + 0x20 + 0x1000 | |
, % "New Update Available" | |
, % "There is a new update available for this application.`n" | |
. "Do you wish to upgrade to v" remVersion "?" | |
, 10 ; timeout | |
ifmsgbox timeout | |
{ | |
try | |
throw exception("The message box timed out.","script.Update()","Script will not be updated.") | |
Catch, e | |
msgbox, 4144,% this.Name " - " "New Update Available" , % e.Message "`nNo user-input received.`n`n" e.Extra "`nResuming normal operation now.`n" | |
return | |
} | |
ifmsgbox no | |
{ ;; decide if you want to have this or not. | |
; try | |
; throw exception("The user pressed the cancel button.","script.Update()","Script will not be updated.") ;{code: ERR_USRCANCEL, msg: "The user pressed the cancel button."} | |
; catch, e | |
; msgbox, 4144,% this.Name " - " "New Update Available" , % e.Message "`n`n" e.Extra "`nResuming normal operation now.`n" | |
return | |
} | |
; Create temporal dirs | |
ghubname := (InStr(rfile, "github") ? regexreplace(a_scriptname, "\..*$") "-latest\" : "") | |
filecreatedir % Update_Temp := a_temp "\" regexreplace(a_scriptname, "\..*$") | |
filecreatedir % zipDir := Update_Temp "\uzip" | |
; ; Create lock file | |
; fileappend % a_now, % lockFile := Update_Temp "\lock" | |
; Download zip file | |
urldownloadtofile % rfile, % file:=Update_Temp "\temp.zip" | |
; Extract zip file to temporal folder | |
shell := ComObjCreate("Shell.Application") | |
; Make backup of current folder | |
if !Instr(FileExist(Backup_Temp:= A_Temp "\Backup " regexreplace(a_scriptname, "\..*$") " - " StrReplace(loVersion,".","_")),"D") | |
FileCreateDir, % Backup_Temp | |
else | |
{ | |
FileDelete, % Backup_Temp | |
FileCreateDir, % Backup_Temp | |
} | |
; Gui +OwnDialogs | |
MsgBox 0x34, `% this.Name " - " "New Update Available", Last Chance to abort Update.`n`n(also remove this once you're done debugging the updater)`nDo you want to continue the Update? | |
IfMsgBox Yes | |
{ | |
Err:=CopyFilesAndFolders(A_ScriptDir, Backup_Temp,1) | |
, Err2:=CopyFilesAndFolders(Backup_Temp ,A_ScriptDir ,0) | |
, items1 := shell.Namespace(file).Items | |
for item_ in items1 | |
{ | |
root := item_.Path | |
, items:=shell.Namespace(root).Items | |
for item in items | |
shell.NameSpace(A_ScriptDir).CopyHere(item, 0x14) | |
} | |
MsgBox, 0x40040,,Update Finished | |
FileRemoveDir, % Backup_Temp,1 | |
FileRemoveDir, % Update_Temp,1 | |
reload | |
} | |
Else IfMsgBox No | |
{ ; no update, cleanup the previously downloaded files from the tmp | |
MsgBox, 0x40040,,Update Aborted | |
FileRemoveDir, % Backup_Temp,1 | |
FileRemoveDir, % Update_Temp,1 | |
} | |
} | |
} | |
} | |
Autostart(status,UseRegistry:=0) | |
{ | |
/** | |
Function: Autostart | |
This Adds the current script to the autorun section for the current | |
user. | |
Parameters: | |
status - Autostart status | |
It can be either true or false. | |
Setting it to true would add the registry value. | |
Setting it to false would delete an existing registry value. | |
*/ | |
if (UseRegistry) | |
{ | |
if (status) | |
{ | |
RegWrite, REG_SZ | |
, HKCU\SOFTWARE\microsoft\windows\currentversion\run | |
, %a_scriptname% | |
, %a_scriptfullpath% | |
} | |
else | |
regdelete, HKCU\SOFTWARE\microsoft\windows\currentversion\run | |
, %a_scriptname% | |
} | |
else | |
{ | |
startUpDir:=(A_Startup "\" A_ScriptName " - Shortcut.lnk") | |
if (status) ; add to startup | |
FileCreateShortcut, % A_ScriptFullPath, % startUpDir | |
else | |
FileDelete, % startUpDir | |
} | |
} | |
Splash(img:="", speed:=10, pause:=2) | |
{ | |
/** | |
Function: Splash | |
Shows a custom image as a splash screen with a simple fading animation | |
Parameters: | |
img (opt) - file to be displayed | |
speed (opt) - fast the fading animation will be. Higher value is faster. | |
pause (opt) - long in seconds the image will be paused after fully displayed. | |
*/ | |
global | |
gui, splash: -caption +lastfound +border +alwaysontop +owner | |
$hwnd := winexist(), alpha := 0 | |
winset, transparent, 0 | |
gui, splash: add, picture, x0 y0 vpicimage, % img | |
guicontrolget, picimage, splash:pos | |
gui, splash: show, w%picimagew% h%picimageh% | |
setbatchlines 3 | |
loop, 255 | |
{ | |
if (alpha >= 255) | |
break | |
alpha += speed | |
winset, transparent, %alpha% | |
} | |
; pause duration in seconds | |
sleep pause * 1000 | |
loop, 255 | |
{ | |
if (alpha <= 0) | |
break | |
alpha -= speed | |
winset, transparent, %alpha% | |
} | |
setbatchlines -1 | |
gui, splash:destroy | |
return | |
} | |
Debug(level:=1, label:=">", msg:="", AddInfo:="",InvocationLine:="", vars*) | |
{ | |
/** | |
Funtion: Debug | |
Allows sending conditional debug messages to the debugger and a log file filtered | |
by the current debug level set on the object. | |
Parameters: | |
level - Debug Level, which can be: | |
* this.DBG_NONE | |
* this.DBG_ERRORS | |
* this.DBG_WARNINGS | |
* this.DBG_VERBOSE | |
If you set the level for a particular message to *this.DBG_VERBOSE* this message | |
wont be shown when the class debug level is set to lower than that (e.g. *this.DBG_WARNINGS*). | |
label - Message label, mainly used to show the name of the function or label that triggered the message | |
msg - Arbitrary message that will be displayed on the debugger or logged to the log file | |
vars* - Aditional parameters that whill be shown as passed. Useful to show variable contents to the debugger. | |
Notes: | |
The point of this function is to have all your debug messages added to your script and filter them out | |
by just setting the object's dbgLevel variable once, which in turn would disable some types of messages. | |
*/ | |
if !this.dbglevel | |
return | |
if (InvocationLine!="") | |
DebugInvokedOn:="Source Code: Function invoked on line " RegexReplace(InvocationLine,"\D") "`nError invoked in function body of " " on line " Exception("",-1).Line | |
for i,var in vars | |
{ | |
if IsObject(var) | |
var:=RegExReplace(Obj2Str(var),"\.\d* = ","") | |
varline .= "`n" var | |
} | |
dbgMessage := label " [invoked on " RegexReplace(InvocationLine,"\D") "]" "`n" DebugInvokedOn "`n>" msg "`n" varline | |
if (level <= this.dbglevel) | |
outputdebug % dbgMessage | |
else if this.dbgFile | |
FileAppend, % dbgMessage, % this.dbgFile | |
else | |
MsgBox 0x10, % this.Name " - " "Error encountered: " this.Error.Error , % Clipboard:=dbgmessage | |
; script.Error:={ Level :"" | |
; ,Label :"" | |
; ,Message :"" | |
; ,Error :"" | |
; ,Vars :[] | |
; ,AddInfo :""} | |
script.ErrorCache[A_Now]:=script.Error | |
} | |
About(scriptName:="", version:="", author:="",credits:="", homepagetext:="", homepagelink:="", donateLink:="", email:="") | |
{ | |
/** | |
Function: About | |
Shows a quick HTML Window based on the object's variable information | |
Parameters: | |
scriptName (opt) - Name of the script which will be | |
shown as the title of the window and the main header | |
version (opt) - Script Version in SimVer format, a "v" | |
will be added automatically to this value | |
author (opt) - Name of the author of the script | |
credits (opt) - Name of credited people | |
ghlink (opt) - GitHubLink | |
ghtext (opt) - GitHubtext | |
doclink (opt) - DocumentationLink | |
doctext (opt) - Documentationtext | |
forumlink (opt) - forumlink | |
forumtext (opt) - forumtext | |
homepagetext (opt) - Display text for the script website | |
homepagelink (opt) - Href link to that points to the scripts | |
website (for pretty links and utm campaing codes) | |
donateLink (opt) - Link to a donation site | |
email (opt) - Developer email | |
Notes: | |
The function will try to infer the paramters if they are blank by checking | |
the class variables if provided. This allows you to set all information once | |
when instatiating the class, and the about GUI will be filled out automatically. | |
*/ | |
static doc | |
scriptName := scriptName ? scriptName : this.name | |
, version := version ? version : this.version | |
, author := author ? author : this.author | |
, credits := credits ? credits : this.credits | |
, creditslink := creditslink ? creditslink : RegExReplace(this.creditslink, "http(s)?:\/\/") | |
, ghtext := ghtext ? ghtext : RegExReplace(this.ghtext, "http(s)?:\/\/") | |
, ghlink := ghlink ? ghlink : RegExReplace(this.ghlink, "http(s)?:\/\/") | |
, doctext := doctext ? doctext : RegExReplace(this.doctext, "http(s)?:\/\/") | |
, doclink := doclink ? doclink : RegExReplace(this.doclink, "http(s)?:\/\/") | |
, forumtext := forumtext ? forumtext : RegExReplace(this.forumtext, "http(s)?:\/\/") | |
, forumlink := forumlink ? forumlink : RegExReplace(this.forumlink, "http(s)?:\/\/") | |
, homepagetext := homepagetext ? homepagetext : RegExReplace(this.homepagetext, "http(s)?:\/\/") | |
, homepagelink := homepagelink ? homepagelink : RegExReplace(this.homepagelink, "http(s)?:\/\/") | |
, donateLink := donateLink ? donateLink : RegExReplace(this.donateLink, "http(s)?:\/\/") | |
, email := email ? email : this.email | |
if (donateLink) | |
{ | |
donateSection = | |
( | |
<div class="donate"> | |
<p>If you like this tool please consider <a href="https://%donateLink%">donating</a>.</p> | |
</div> | |
<hr> | |
) | |
} | |
html = | |
( | |
<!DOCTYPE html> | |
<html lang="en" dir="ltr"> | |
<head> | |
<meta charset="utf-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<style media="screen"> | |
.top { | |
text-align:center; | |
} | |
.top h2 { | |
color:#2274A5; | |
margin-bottom: 5px; | |
} | |
.donate { | |
color:#E83F6F; | |
text-align:center; | |
font-weight:bold; | |
font-size:small; | |
margin: 20px; | |
} | |
p { | |
margin: 0px; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="top"> | |
<h2>%scriptName%</h2> | |
<p>v%version%</p> | |
<hr> | |
<p>by %author%</p> | |
) | |
if ghlink and ghtext | |
{ | |
sTmp= | |
( | |
<p><a href="https://%ghlink%" target="_blank">%ghtext%</a></p> | |
) | |
html.=sTmp | |
} | |
if doclink and doctext | |
{ | |
sTmp= | |
( | |
<p><a href="https://%doclink%" target="_blank">%doctext%</a></p> | |
) | |
html.=sTmp | |
} | |
if creditslink and credits | |
{ | |
; Clipboard:=html | |
sTmp= | |
( | |
<p>credits: <a href="https://%creditslink%" target="_blank">%credits%</a></p> | |
<hr> | |
) | |
html.=sTmp | |
} | |
if forumlink and forumtext | |
{ | |
sTmp= | |
( | |
<p><a href="https://%forumlink%" target="_blank">%forumtext%</a></p> | |
) | |
html.=sTmp | |
} | |
if homepagelink and homepagetext | |
{ | |
sTmp= | |
( | |
<p><a href="https://%homepagelink%" target="_blank">%homepagetext%</a></p> | |
) | |
html.=sTmp | |
} | |
sTmp= | |
( | |
</div> | |
%donateSection% | |
</body> | |
</html> | |
) | |
html.=sTmp | |
; Clipboard:=html | |
; html.= "`n | |
; ( | |
; HEllo World | |
; )" | |
; Clipboard:=html | |
btnxPos := 300/2 - 75/2 | |
, axHight:=12 | |
, donateHeight := donateLink ? 6 : 0 | |
, forumHeight := forumlink ? 1 : 0 | |
, ghHeight := ghlink ? 1 : 0 | |
, creditsHeight := creditslink ? 1 : 0 | |
, homepageHeight := homepagelink ? 1 : 0 | |
, docHeight := doclink ? 1 : 0 | |
, axHight+=donateHeight | |
, axHight+=forumHeight | |
, axHight+=ghHeight | |
, axHight+=creditsHeight | |
, axHight+=homepageHeight | |
, axHight+=docHeight | |
gui aboutScript:new, +alwaysontop +toolwindow, % "About " this.name | |
gui margin, 2 | |
gui color, white | |
gui add, activex, w300 r%axHight% vdoc, htmlFile | |
gui add, button, w75 x%btnxPos% gaboutClose, % "&Close" | |
doc.write(html) | |
gui show, AutoSize | |
return | |
aboutClose: | |
gui aboutScript:destroy | |
return | |
} | |
GetLicense() | |
{ | |
/* | |
Function: GetLicense | |
Parameters: | |
Notes: | |
*/ | |
global | |
this.systemID := this.GetSystemID() | |
cleanName := RegexReplace(A_ScriptName, "\..*$") | |
for i,value in ["Type", "License"] | |
RegRead, %value%, % "HKCU\SOFTWARE\" cleanName, % value | |
if (!License) | |
{ | |
MsgBox, % 0x4 + 0x20 | |
, % "No license" | |
, % "Seems like there is no license activated on this computer.`n" | |
. "Do you have a license that you want to activate now?" | |
IfMsgBox, Yes | |
{ | |
Gui, license:new | |
Gui, add, Text, w160, % "Paste the License Code here" | |
Gui, add, Edit, w160 vLicenseNumber | |
Gui, add, Button, w75 vTest, % "Save" | |
Gui, add, Button, w75 x+10, % "Cancel" | |
Gui, show | |
saveFunction := Func("licenseButtonSave").bind(this) | |
GuiControl, +g, test, % saveFunction | |
Exit | |
} | |
MsgBox, % 0x30 | |
, % "Unable to Run" | |
, % "This program cannot run without a license." | |
ExitApp, 1 | |
} | |
return {"type" : Type | |
,"number" : License} | |
} | |
SaveLicense(licenseType, licenseNumber) | |
{ | |
/* | |
Function: SaveLicense | |
Parameters: | |
Notes: | |
*/ | |
cleanName := RegexReplace(A_ScriptName, "\..*$") | |
Try | |
{ | |
RegWrite, % "REG_SZ" | |
, % "HKCU\SOFTWARE\" cleanName | |
, % "Type", % licenseType | |
RegWrite, % "REG_SZ" | |
, % "HKCU\SOFTWARE\" cleanName | |
, % "License", % licenseNumber | |
return true | |
} | |
catch | |
return false | |
} | |
IsLicenceValid(licenseType, licenseNumber, URL) | |
{ | |
/* | |
Function: IsLicenceValid | |
Parameters: | |
Notes: | |
*/ | |
res := this.EDDRequest(URL, "check_license", licenseType ,licenseNumber) | |
if InStr(res, """license"":""inactive""") | |
res := this.EDDRequest(URL, "activate_license", licenseType ,licenseNumber) | |
if InStr(res, """license"":""valid""") | |
return true | |
else | |
return false | |
} | |
GetSystemID() | |
{ | |
wmi := ComObjGet("winmgmts:{impersonationLevel=impersonate}!\\" A_ComputerName "\root\cimv2") | |
(wmi.ExecQuery("Select * from Win32_BaseBoard")._newEnum)[Computer] | |
return Computer.SerialNumber | |
} | |
EDDRequest(URL, Action, licenseType, licenseNumber) | |
{ | |
/* | |
Function: EDDRequest | |
Parameters: | |
Notes: | |
*/ | |
strQuery := url "?edd_action=" Action | |
. "&item_id=" licenseType | |
. "&license=" licenseNumber | |
. (this.systemID ? "&url=" this.systemID : "") | |
try | |
{ | |
http := ComObjCreate("WinHttp.WinHttpRequest.5.1") | |
, http.Open("GET", strQuery) | |
, http.SetRequestHeader("Pragma", "no-cache") | |
, http.SetRequestHeader("Cache-Control", "no-cache, no-store") | |
, http.SetRequestHeader("User-Agent", "Mozilla/4.0 (compatible; Win32)") | |
, http.Send() | |
, http.WaitForResponse() | |
return http.responseText | |
} | |
catch err | |
return err.what ":`n" err.message | |
} | |
/* | |
; Activate() | |
; { | |
; strQuery := this.strEddRootUrl . "?edd_action=activate_license&item_id=" . this.strRequestedProductId . "&license=" . this.strEddLicense . "&url=" . this.strUniqueSystemId | |
; strJSON := Url2Var(strQuery) | |
; Diag(A_ThisFunc . " strQuery", strQuery, "") | |
; Diag(A_ThisFunc . " strJSON", strJSON, "") | |
; return JSON.parse(strJSON) | |
; } | |
; Deactivate() | |
; { | |
; Loop, Parse, % "/|", | | |
; { | |
; strQuery := this.strEddRootUrl . "?edd_action=deactivate_license&item_id=" . this.strRequestedProductId . "&license=" . this.strEddLicense . "&url=" . this.strUniqueSystemId . A_LoopField | |
; strJSON := Url2Var(strQuery) | |
; Diag(A_ThisFunc . " strQuery", strQuery, "") | |
; Diag(A_ThisFunc . " strJSON", strJSON, "") | |
; this.oLicense := JSON.parse(strJSON) | |
; if (this.oLicense.success) | |
; break | |
; } | |
; } | |
; GetVersion() | |
; { | |
; strQuery := this.strEddRootUrl . "?edd_action=get_version&item_id=" . this.oLicense.item_id . "&license=" . this.strEddLicense . "&url=" . this.strUniqueSystemId | |
; strJSON := Url2Var(strQuery) | |
; Diag(A_ThisFunc . " strQuery", strQuery, "") | |
; Diag(A_ThisFunc . " strJSON", strJSON, "") | |
; return JSON.parse(strJSON) | |
; } | |
; RenewLink() | |
; { | |
; strUrl := this.strEddRootUrl . "checkout/?edd_license_key=" . this.strEddLicense . "&download_id=" . this.oLicense.item_id | |
; Diag(A_ThisFunc . " strUrl", strUrl, "") | |
; return strUrl | |
; } | |
*/ | |
Load(INI_File:="") | |
{ | |
if (INI_File="") | |
INI_File:=this.configfile | |
Result := [] | |
, OrigWorkDir:=A_WorkingDir | |
if (d_fWriteINI_st_count(INI_File,".ini")>0) | |
{ | |
INI_File:=d_fWriteINI_st_removeDuplicates(INI_File,".ini") ;. ".ini" ; reduce number of ".ini"-patterns to 1 | |
if (d_fWriteINI_st_count(INI_File,".ini")>0) | |
INI_File:=SubStr(INI_File,1,StrLen(INI_File)-4) ; and remove the last instance | |
} | |
if !FileExist(INI_File) ;; create new INI_File if not existing | |
{ | |
SplitPath, INI_File, INI_File_File, INI_File_Dir, INI_File_Ext, INI_File_NNE, INI_File_Drive | |
if !Instr(d:=FileExist(INI_File_Dir),"D:") | |
FileCreateDir, % INI_File_Dir | |
if !FileExist(INI_File_File ".ini") ; check for ini-file file ending | |
FileAppend,, % INI_File ".ini" | |
} | |
SetWorkingDir, INI-Files | |
IniRead, SectionNames, % INI_File ".ini" | |
for each, Section in StrSplit(SectionNames, "`n") { | |
IniRead, OutputVar_Section, % INI_File ".ini", %Section% | |
for each, Haystack in StrSplit(OutputVar_Section, "`n") | |
{ | |
If (Instr(Haystack,"=")) | |
{ | |
RegExMatch(Haystack, "(.*?)=(.*)", $) | |
, Result[Section, $1] := $2 | |
} | |
else | |
Result[Section, Result[Section].MaxIndex()+1]:=Haystack | |
} | |
} | |
if A_WorkingDir!=OrigWorkDir | |
SetWorkingDir, %OrigWorkDir% | |
this.config:=Result | |
} | |
Save(INI_File:="") | |
{ | |
if (INI_File="") | |
INI_File:=this.configfile | |
SplitPath, INI_File, INI_File_File, INI_File_Dir, INI_File_Ext, INI_File_NNE, INI_File_Drive | |
if (d_fWriteINI_st_count(INI_File,".ini")>0) | |
{ | |
INI_File:=d_fWriteINI_st_removeDuplicates(INI_File,".ini") ;. ".ini" ; reduce number of ".ini"-patterns to 1 | |
if (d_fWriteINI_st_count(INI_File,".ini")>0) | |
INI_File:=SubStr(INI_File,1,StrLen(INI_File)-4) ; and remove the last instance | |
} | |
if !Instr(d:=FileExist(INI_File_Dir),"D:") | |
FileCreateDir, % INI_File_Dir | |
if !FileExist(INI_File_File ".ini") ; check for ini-file file ending | |
FileAppend,, % INI_File ".ini" | |
for SectionName, Entry in this.config | |
{ | |
Pairs := "" | |
for Key, Value in Entry | |
{ | |
if !Instr(Pairs, "=" Value "`n") | |
Pairs .= Key "=" Value "`n" | |
} | |
IniWrite, %Pairs%, % INI_File ".ini", %SectionName% | |
} | |
} | |
} | |
d_fWriteINI_st_removeDuplicates(string, delim="`n") | |
{ ; remove all but the first instance of 'delim' in 'string' | |
; from StringThings-library by tidbit, Version 2.6 (Fri May 30, 2014) | |
/* | |
RemoveDuplicates | |
Remove any and all consecutive lines. A "line" can be determined by | |
the delimiter parameter. Not necessarily just a `r or `n. But perhaps | |
you want a | as your "line". | |
string = The text or symbols you want to search for and remove. | |
delim = The string which defines a "line". | |
example: st_removeDuplicates("aaa|bbb|||ccc||ddd", "|") | |
output: aaa|bbb|ccc|ddd | |
*/ | |
delim:=RegExReplace(delim, "([\\.*?+\[\{|\()^$])", "\$1") | |
Return RegExReplace(string, "(" delim ")+", "$1") | |
} | |
d_fWriteINI_st_count(string, searchFor="`n") | |
{ ; count number of occurences of 'searchFor' in 'string' | |
; copy of the normal function to avoid conflicts. | |
; from StringThings-library by tidbit, Version 2.6 (Fri May 30, 2014) | |
/* | |
Count | |
Counts the number of times a tolken exists in the specified string. | |
string = The string which contains the content you want to count. | |
searchFor = What you want to search for and count. | |
note: If you're counting lines, you may need to add 1 to the results. | |
example: st_count("aaa`nbbb`nccc`nddd", "`n")+1 ; add one to count the last line | |
output: 4 | |
*/ | |
StringReplace, string, string, %searchFor%, %searchFor%, UseErrorLevel | |
return ErrorLevel | |
} | |
licenseButtonSave(this, CtrlHwnd, GuiEvent, EventInfo, ErrLevel:="") | |
{ | |
GuiControlGet, LicenseNumber | |
if this.IsLicenceValid(this.eddID, licenseNumber, "https://www.the-automator.com") | |
{ | |
this.SaveLicense(this.eddID, LicenseNumber) | |
MsgBox, % 0x30 | |
, % "License Saved" | |
, % "The license was applied correctly!`n" | |
. "The program will start now." | |
Reload | |
} | |
else | |
{ | |
MsgBox, % 0x10 | |
, % "Invalid License" | |
, % "The license you entered is invalid and cannot be activated." | |
ExitApp, 1 | |
} | |
} | |
licenseButtonCancel(CtrlHwnd, GuiEvent, EventInfo, ErrLevel:="") | |
{ | |
MsgBox, % 0x30 | |
, % "Unable to Run" | |
, % "This program cannot run without a license." | |
ExitApp, 1 | |
} | |
CopyFilesAndFolders(SourcePattern, DestinationFolder, DoOverwrite = false) | |
{ | |
; Copies all files and folders matching SourcePattern into the folder named DestinationFolder and | |
; returns the number of files/folders that could not be copied. | |
; First copy all the files (but not the folders): | |
; FileCopy, %SourcePattern%, %DestinationFolder%, %DoOverwrite% | |
; ErrorCount := ErrorLevel | |
; Now copy all the folders: | |
Loop, %SourcePattern%, 2 ; 2 means "retrieve folders only". | |
{ | |
FileCopyDir, % A_LoopFileFullPath, % DestinationFolder "\" A_LoopFileName , % DoOverwrite | |
ErrorCount += ErrorLevel | |
if ErrorLevel ; Report each problem folder by name. | |
MsgBox,% "Could not copy " A_LoopFileFullPath " into %DestinationFolder." | |
} | |
return ErrorCount | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment