Browse Source
* Build binary release for each commit and pull request * Codesign macOS releasepull/1718/head
committed by
GitHub
20 changed files with 1923 additions and 4 deletions
@ -0,0 +1,76 @@ |
|||
name: Build binaries and source distribution |
|||
|
|||
on: [push, pull_request] |
|||
|
|||
jobs: |
|||
build_windows: |
|||
name: Build ${{ matrix.name }} binary |
|||
runs-on: ${{ matrix.os }} |
|||
strategy: |
|||
matrix: |
|||
include: |
|||
- name: macOS |
|||
os: macos-latest |
|||
python-version: 3.9 |
|||
- name: Windows |
|||
os: windows-latest |
|||
python-version: 3.9 |
|||
|
|||
steps: |
|||
- uses: actions/checkout@v2 |
|||
- name: Set up Python ${{ matrix.python-version }} |
|||
uses: actions/setup-python@v2 |
|||
with: |
|||
python-version: ${{ matrix.python-version }} |
|||
- name: Install Python dependencies |
|||
run: | |
|||
python --version |
|||
pip install --upgrade pip wheel |
|||
pip install --upgrade -r requirements.txt |
|||
pip install --upgrade -r builder/requirements.txt |
|||
- name: Build source distribution |
|||
if: runner.os == 'Windows' |
|||
run: python builder/package.py source |
|||
- name: Upload source distribution |
|||
if: runner.os == 'Windows' |
|||
uses: actions/upload-artifact@v2 |
|||
with: |
|||
path: "*-src.tar.gz" |
|||
name: Source distribution |
|||
- name: Build Windows standalone binary and installer |
|||
if: runner.os == 'Windows' |
|||
run: python builder/package.py installer |
|||
- name: Upload Windows standalone binary (64bit) |
|||
if: runner.os == 'Windows' |
|||
uses: actions/upload-artifact@v2 |
|||
with: |
|||
path: "*-win64-bin.zip" |
|||
name: Windows Windows standalone binary (64bit) |
|||
- name: Upload Windows installer |
|||
if: runner.os == 'Windows' |
|||
uses: actions/upload-artifact@v2 |
|||
with: |
|||
path: "*-win-setup.exe" |
|||
name: Windows installer |
|||
- name: Import codesign certificates |
|||
uses: apple-actions/import-codesign-certs@v1 |
|||
if: runner.os == 'macOS' |
|||
with: |
|||
p12-file-base64: ${{ secrets.CERTIFICATES_P12 }} |
|||
p12-password: ${{ secrets.CERTIFICATES_P12_PASSWORD }} |
|||
- name: Build macOS binary |
|||
if: runner.os == 'macOS' |
|||
run: | |
|||
python builder/package.py app |
|||
python builder/make_dmg.py |
|||
env: |
|||
SIGNING_AUTH: ${{ secrets.SIGNING_AUTH }} |
|||
- name: Upload macOS binary |
|||
if: runner.os == 'macOS' |
|||
uses: actions/upload-artifact@v2 |
|||
with: |
|||
path: "*-osx.dmg" |
|||
name: macOS binary (not notarized) |
|||
|
|||
|
|||
|
@ -0,0 +1,184 @@ |
|||
# -*- mode: python -*- |
|||
import re |
|||
import sys |
|||
import pkginfo |
|||
|
|||
from PyInstaller.building.api import EXE, COLLECT, PYZ |
|||
from PyInstaller.building.build_main import Analysis |
|||
from PyInstaller.building.osx import BUNDLE |
|||
|
|||
# Add extra files in the PyInstaller-spec |
|||
extra_pyinstaller_files = [] |
|||
|
|||
# Also modify these in "package.py"! |
|||
extra_files = [ |
|||
"README.txt", |
|||
"INSTALL.txt", |
|||
"LICENSE.txt", |
|||
"GPL2.txt", |
|||
"GPL3.txt", |
|||
"COPYRIGHT.txt", |
|||
"ISSUES.txt", |
|||
"PKG-INFO", |
|||
] |
|||
|
|||
extra_folders = [ |
|||
"scripts/", |
|||
"licenses/", |
|||
"locale/", |
|||
"email/", |
|||
"interfaces/Plush/", |
|||
"interfaces/Glitter/", |
|||
"interfaces/wizard/", |
|||
"interfaces/Config/", |
|||
"scripts/", |
|||
"icons/", |
|||
] |
|||
|
|||
# Get the version |
|||
RELEASE_VERSION = pkginfo.Develop(".").version |
|||
|
|||
# Add hidden imports |
|||
extra_hiddenimports = ["Cheetah.DummyTransaction", "cheroot.ssl.builtin", "certifi"] |
|||
|
|||
# Add platform specific stuff |
|||
if sys.platform == "darwin": |
|||
extra_hiddenimports.extend(["pyobjc", "objc", "PyObjCTools"]) |
|||
# macOS folders |
|||
extra_folders += ["osx/par2/", "osx/unrar/", "osx/7zip/"] |
|||
# Add NZB-icon file |
|||
extra_pyinstaller_files.append(("builder/osx/image/nzbfile.icns", ".")) |
|||
# Version information is set differently on macOS |
|||
version_info = None |
|||
else: |
|||
# Build would fail on non-Windows |
|||
from PyInstaller.utils.win32.versioninfo import ( |
|||
VSVersionInfo, |
|||
FixedFileInfo, |
|||
StringFileInfo, |
|||
StringTable, |
|||
StringStruct, |
|||
VarFileInfo, |
|||
VarStruct, |
|||
) |
|||
|
|||
# Windows |
|||
extra_hiddenimports.append("win32timezone") |
|||
extra_folders += ["win/multipar/", "win/unrar/", "win/7zip/"] |
|||
|
|||
# Parse the version info |
|||
version_regexed = re.search(r"(\d+)\.(\d+)\.(\d+)([a-zA-Z]*)(\d*)", RELEASE_VERSION) |
|||
version_tuple = (int(version_regexed.group(1)), int(version_regexed.group(2)), int(version_regexed.group(3)), 0) |
|||
|
|||
# Detailed instructions are in the PyInstaller documentation |
|||
# We don't include the alpha/beta/rc in the counters |
|||
version_info = VSVersionInfo( |
|||
ffi=FixedFileInfo( |
|||
filevers=version_tuple, |
|||
prodvers=version_tuple, |
|||
mask=0x3F, |
|||
flags=0x0, |
|||
OS=0x40004, |
|||
fileType=0x1, |
|||
subtype=0x0, |
|||
date=(0, 0), |
|||
), |
|||
kids=[ |
|||
StringFileInfo( |
|||
[ |
|||
StringTable( |
|||
"040904B0", |
|||
[ |
|||
StringStruct("Comments", f"SABnzbd {RELEASE_VERSION}"), |
|||
StringStruct("CompanyName", "The SABnzbd-Team"), |
|||
StringStruct("FileDescription", f"SABnzbd {RELEASE_VERSION}"), |
|||
StringStruct("FileVersion", RELEASE_VERSION), |
|||
StringStruct("LegalCopyright", "The SABnzbd-Team"), |
|||
StringStruct("ProductName", f"SABnzbd {RELEASE_VERSION}"), |
|||
StringStruct("ProductVersion", RELEASE_VERSION), |
|||
], |
|||
) |
|||
] |
|||
), |
|||
VarFileInfo([VarStruct("Translation", [1033, 1200])]), |
|||
], |
|||
) |
|||
|
|||
# Process the extra-files and folders |
|||
for file_item in extra_files: |
|||
extra_pyinstaller_files.append((file_item, ".")) |
|||
for folder_item in extra_folders: |
|||
extra_pyinstaller_files.append((folder_item, folder_item)) |
|||
|
|||
pyi_analysis = Analysis( |
|||
["SABnzbd.py"], |
|||
datas=extra_pyinstaller_files, |
|||
hiddenimports=extra_hiddenimports, |
|||
excludes=["FixTk", "tcl", "tk", "_tkinter", "tkinter", "Tkinter"], |
|||
) |
|||
|
|||
pyz = PYZ(pyi_analysis.pure, pyi_analysis.zipped_data) |
|||
|
|||
exe = EXE( |
|||
pyz, |
|||
pyi_analysis.scripts, |
|||
[], |
|||
exclude_binaries=True, |
|||
name="SABnzbd", |
|||
upx=True, |
|||
console=False, |
|||
append_pkg=False, |
|||
icon="icons/sabnzbd.ico", |
|||
version=version_info, |
|||
) |
|||
|
|||
coll = COLLECT(exe, pyi_analysis.binaries, pyi_analysis.zipfiles, pyi_analysis.datas, name="SABnzbd") |
|||
|
|||
# We need to run again for the console-app |
|||
if sys.platform == "win32": |
|||
# Enable console=True for this one |
|||
console_exe = EXE( |
|||
pyz, |
|||
pyi_analysis.scripts, |
|||
[], |
|||
exclude_binaries=True, |
|||
name="SABnzbd-console", |
|||
upx=True, |
|||
append_pkg=False, |
|||
icon="icons/sabnzbd.ico", |
|||
version=version_info, |
|||
) |
|||
|
|||
console_coll = COLLECT( |
|||
console_exe, |
|||
pyi_analysis.binaries, |
|||
pyi_analysis.zipfiles, |
|||
pyi_analysis.datas, |
|||
upx=True, |
|||
name="SABnzbd-console", |
|||
) |
|||
|
|||
# Build the APP on macOS |
|||
if sys.platform == "darwin": |
|||
info_plist = { |
|||
"NSUIElement": 1, |
|||
"NSPrincipalClass": "NSApplication", |
|||
"CFBundleShortVersionString": RELEASE_VERSION, |
|||
"NSHumanReadableCopyright": "The SABnzbd-Team", |
|||
"CFBundleIdentifier": "org.sabnzbd.sabnzbd", |
|||
"CFBundleDocumentTypes": [ |
|||
{ |
|||
"CFBundleTypeExtensions": ["nzb"], |
|||
"CFBundleTypeIconFile": "nzbfile.icns", |
|||
"CFBundleTypeMIMETypes": ["text/nzb"], |
|||
"CFBundleTypeName": "NZB File", |
|||
"CFBundleTypeRole": "Viewer", |
|||
"LSTypeIsPackage": 0, |
|||
"NSPersistentStoreTypeKey": "Binary", |
|||
} |
|||
], |
|||
"LSMinimumSystemVersion": "10.9", |
|||
"LSEnvironment": {"LANG": "en_US.UTF-8", "LC_ALL": "en_US.UTF-8"}, |
|||
} |
|||
|
|||
app = BUNDLE(coll, name="SABnzbd.app", icon="builder/osx/image/sabnzbdplus.icns", info_plist=info_plist) |
@ -0,0 +1,206 @@ |
|||
#!/usr/bin/python3 -OO |
|||
# Copyright 2008-2017 The SABnzbd-Team <team@sabnzbd.org> |
|||
# |
|||
# This program is free software; you can redistribute it and/or |
|||
# modify it under the terms of the GNU General Public License |
|||
# as published by the Free Software Foundation; either version 2 |
|||
# of the License, or (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU General Public License |
|||
# along with this program; if not, write to the Free Software |
|||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|||
|
|||
import os |
|||
import pkginfo |
|||
|
|||
|
|||
# We need to call dmgbuild from command-line, so here we can setup how |
|||
if __name__ == "__main__": |
|||
# Check for DMGBuild |
|||
try: |
|||
import dmgbuild |
|||
except: |
|||
print("Requires dmgbuild-module, use pip install dmgbuild") |
|||
exit() |
|||
|
|||
# Make sure we are in the src folder |
|||
if not os.path.exists("builder"): |
|||
raise FileNotFoundError("Run from the main SABnzbd source folder: python builder/package.py") |
|||
|
|||
# Check if signing is possible |
|||
authority = os.environ.get("SIGNING_AUTH") |
|||
|
|||
# Extract version info and set DMG path |
|||
# Create sub-folder to upload later |
|||
release = pkginfo.Develop(".").version |
|||
prod = "SABnzbd-" + release |
|||
fileDmg = prod + "-osx.dmg" |
|||
|
|||
# Path to app file |
|||
apppath = "dist/SABnzbd.app" |
|||
|
|||
# Copy Readme |
|||
readmepath = os.path.join(apppath, "Contents/Resources/README.txt") |
|||
|
|||
# Path to background and the icon |
|||
backgroundpath = "builder/osx/image/sabnzbd_new_bg.png" |
|||
iconpath = "builder/osx/image/sabnzbdplus.icns" |
|||
|
|||
# Make DMG |
|||
print("Building DMG") |
|||
dmgbuild.build_dmg( |
|||
filename=fileDmg, |
|||
volume_name=prod, |
|||
settings_file="builder/make_dmg.py", |
|||
defines={"app": apppath, "readme": readmepath, "background": backgroundpath, "iconpath": iconpath}, |
|||
) |
|||
|
|||
# Resign APP |
|||
if authority: |
|||
print("Siging DMG") |
|||
os.system('codesign --deep -f -i "org.sabnzbd.SABnzbd" -s "%s" "%s"' % (authority, fileDmg)) |
|||
print("Signed!") |
|||
else: |
|||
print("Signing skipped, missing SIGNING_AUTH.") |
|||
exit() |
|||
|
|||
|
|||
### START OF DMGBUILD SETTINGS |
|||
### COPIED AND MODIFIED FROM THE EXAMPLE ONLINE |
|||
application = defines.get("app", "AppName.app") |
|||
readme = defines.get("readme", "ReadMe.rtf") |
|||
appname = os.path.basename(application) |
|||
|
|||
# .. Basics .................................................................... |
|||
|
|||
# Volume format (see hdiutil create -help) |
|||
format = defines.get("format", "UDBZ") |
|||
|
|||
# Volume size (must be large enough for your files) |
|||
size = defines.get("size", "100M") |
|||
|
|||
# Files to include |
|||
files = [application, readme] |
|||
|
|||
# Symlinks to create |
|||
symlinks = {"Applications": "/Applications"} |
|||
|
|||
# Volume icon |
|||
# |
|||
# You can either define icon, in which case that icon file will be copied to the |
|||
# image, *or* you can define badge_icon, in which case the icon file you specify |
|||
# will be used to badge the system's Removable Disk icon |
|||
# |
|||
badge_icon = defines.get("iconpath", "") |
|||
|
|||
# Where to put the icons |
|||
icon_locations = {readme: (70, 160), appname: (295, 220), "Applications": (510, 220)} |
|||
|
|||
# .. Window configuration ...................................................... |
|||
|
|||
# Window position in ((x, y), (w, h)) format |
|||
window_rect = ((100, 100), (660, 360)) |
|||
|
|||
# Background |
|||
# |
|||
# This is a STRING containing any of the following: |
|||
# |
|||
# #3344ff - web-style RGB color |
|||
# #34f - web-style RGB color, short form (#34f == #3344ff) |
|||
# rgb(1,0,0) - RGB color, each value is between 0 and 1 |
|||
# hsl(120,1,.5) - HSL (hue saturation lightness) color |
|||
# hwb(300,0,0) - HWB (hue whiteness blackness) color |
|||
# cmyk(0,1,0,0) - CMYK color |
|||
# goldenrod - X11/SVG named color |
|||
# builtin-arrow - A simple built-in background with a blue arrow |
|||
# /foo/bar/baz.png - The path to an image file |
|||
# |
|||
# Other color components may be expressed either in the range 0 to 1, or |
|||
# as percentages (e.g. 60% is equivalent to 0.6). |
|||
background = defines.get("background", "builtin-arrow") |
|||
|
|||
show_status_bar = False |
|||
show_tab_view = False |
|||
show_toolbar = False |
|||
show_pathbar = False |
|||
show_sidebar = False |
|||
sidebar_width = 0 |
|||
|
|||
# Select the default view; must be one of |
|||
# |
|||
# 'icon-view' |
|||
# 'list-view' |
|||
# 'column-view' |
|||
# 'coverflow' |
|||
# |
|||
default_view = "icon-view" |
|||
|
|||
# General view configuration |
|||
show_icon_preview = False |
|||
|
|||
# Set these to True to force inclusion of icon/list view settings (otherwise |
|||
# we only include settings for the default view) |
|||
include_icon_view_settings = "auto" |
|||
include_list_view_settings = "auto" |
|||
|
|||
# .. Icon view configuration ................................................... |
|||
|
|||
arrange_by = None |
|||
grid_offset = (0, 0) |
|||
grid_spacing = 50 |
|||
scroll_position = (0, 0) |
|||
label_pos = "bottom" # or 'right' |
|||
text_size = 16 |
|||
icon_size = 64 |
|||
|
|||
# .. List view configuration ................................................... |
|||
|
|||
# Column names are as follows: |
|||
# |
|||
# name |
|||
# date-modified |
|||
# date-created |
|||
# date-added |
|||
# date-last-opened |
|||
# size |
|||
# kind |
|||
# label |
|||
# version |
|||
# comments |
|||
# |
|||
list_icon_size = 16 |
|||
list_text_size = 12 |
|||
list_scroll_position = (0, 0) |
|||
list_sort_by = "name" |
|||
list_use_relative_dates = True |
|||
list_calculate_all_sizes = (False,) |
|||
list_columns = ("name", "date-modified", "size", "kind", "date-added") |
|||
list_column_widths = { |
|||
"name": 300, |
|||
"date-modified": 181, |
|||
"date-created": 181, |
|||
"date-added": 181, |
|||
"date-last-opened": 181, |
|||
"size": 97, |
|||
"kind": 115, |
|||
"label": 100, |
|||
"version": 75, |
|||
"comments": 300, |
|||
} |
|||
list_column_sort_directions = { |
|||
"name": "ascending", |
|||
"date-modified": "descending", |
|||
"date-created": "descending", |
|||
"date-added": "descending", |
|||
"date-last-opened": "descending", |
|||
"size": "descending", |
|||
"kind": "ascending", |
|||
"label": "ascending", |
|||
"version": "ascending", |
|||
"comments": "ascending", |
|||
} |
@ -0,0 +1,8 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
|||
<plist version="1.0"> |
|||
<dict> |
|||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key> |
|||
<true/> |
|||
</dict> |
|||
</plist> |
Binary file not shown.
After Width: | Height: | Size: 39 KiB |
Binary file not shown.
Binary file not shown.
@ -0,0 +1,545 @@ |
|||
#!/usr/bin/python3 -OO |
|||
# Copyright 2008-2017 The SABnzbd-Team <team@sabnzbd.org> |
|||
# |
|||
# This program is free software; you can redistribute it and/or |
|||
# modify it under the terms of the GNU General Public License |
|||
# as published by the Free Software Foundation; either version 2 |
|||
# of the License, or (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU General Public License |
|||
# along with this program; if not, write to the Free Software |
|||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|||
|
|||
import glob |
|||
import platform |
|||
import re |
|||
import sys |
|||
import os |
|||
import time |
|||
import shutil |
|||
import subprocess |
|||
import tarfile |
|||
import pkginfo |
|||
import github |
|||
from distutils.dir_util import copy_tree |
|||
|
|||
|
|||
VERSION_FILE = "sabnzbd/version.py" |
|||
SPEC_FILE = "SABnzbd.spec" |
|||
|
|||
# Also modify these in "SABnzbd.spec"! |
|||
extra_files = [ |
|||
"README.mkd", |
|||
"INSTALL.txt", |
|||
"LICENSE.txt", |
|||
"GPL2.txt", |
|||
"GPL3.txt", |
|||
"COPYRIGHT.txt", |
|||
"ISSUES.txt", |
|||
"PKG-INFO", |
|||
] |
|||
|
|||
extra_folders = [ |
|||
"scripts/", |
|||
"licenses/", |
|||
"locale/", |
|||
"email/", |
|||
"interfaces/Plush/", |
|||
"interfaces/Glitter/", |
|||
"interfaces/wizard/", |
|||
"interfaces/Config/", |
|||
"scripts/", |
|||
"icons/", |
|||
] |
|||
|
|||
|
|||
# Support functions |
|||
def safe_remove(path): |
|||
"""Remove file without erros if the file doesn't exist |
|||
Can also handle folders |
|||
""" |
|||
if os.path.exists(path): |
|||
if os.path.isdir(path): |
|||
shutil.rmtree(path) |
|||
else: |
|||
os.remove(path) |
|||
|
|||
|
|||
def delete_files_glob(name): |
|||
""" Delete one file or set of files from wild-card spec """ |
|||
for f in glob.glob(name): |
|||
if os.path.exists(f): |
|||
os.remove(f) |
|||
|
|||
|
|||
def run_external_command(command): |
|||
""" Wrapper to ease the use of calling external programs """ |
|||
process = subprocess.Popen(command, text=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) |
|||
output, _ = process.communicate() |
|||
ret = process.wait() |
|||
if output: |
|||
print(output) |
|||
if ret != 0: |
|||
raise RuntimeError("Command returned non-zero exit code %s!" % ret) |
|||
return output |
|||
|
|||
|
|||
def run_git_command(parms): |
|||
""" Run git command, raise error if it failed """ |
|||
return run_external_command(["git"] + parms) |
|||
|
|||
|
|||
def patch_version_file(release_name): |
|||
"""Patch in the Git commit hash, but only when this is |
|||
an unmodified checkout |
|||
""" |
|||
git_output = run_git_command(["log", "-1"]) |
|||
for line in git_output.split("\n"): |
|||
if "commit " in line: |
|||
commit = line.split(" ")[1].strip() |
|||
break |
|||
else: |
|||
raise TypeError("Commit hash not found") |
|||
|
|||
with open(VERSION_FILE, "r") as ver: |
|||
version_file = ver.read() |
|||
|
|||
version_file = re.sub(r'__baseline__\s*=\s*"[^"]*"', '__baseline__ = "%s"' % commit, version_file) |
|||
version_file = re.sub(r'__version__\s*=\s*"[^"]*"', '__version__ = "%s"' % release_name, version_file) |
|||
|
|||
with open(VERSION_FILE, "w") as ver: |
|||
ver.write(version_file) |
|||
|
|||
|
|||
if __name__ == "__main__": |
|||
# Was any option supplied? |
|||
if len(sys.argv) < 2: |
|||
raise TypeError("Please specify what to do") |
|||
|
|||
# Make sure we are in the src folder |
|||
if not os.path.exists("builder"): |
|||
raise FileNotFoundError("Run from the main SABnzbd source folder: python builder/package.py") |
|||
|
|||
# Extract version info |
|||
RELEASE_VERSION = pkginfo.Develop(".").version |
|||
|
|||
# Check if we have the needed certificates |
|||
try: |
|||
import certifi |
|||
except ImportError: |
|||
raise FileNotFoundError("Need certifi module") |
|||
|
|||
# Define release name |
|||
RELEASE_NAME = "SABnzbd-%s" % RELEASE_VERSION |
|||
RELEASE_TITLE = "SABnzbd %s" % RELEASE_VERSION |
|||
RELEASE_SRC = RELEASE_NAME + "-src.tar.gz" |
|||
RELEASE_BINARY_32 = RELEASE_NAME + "-win32-bin.zip" |
|||
RELEASE_BINARY_64 = RELEASE_NAME + "-win64-bin.zip" |
|||
RELEASE_INSTALLER = RELEASE_NAME + "-win-setup.exe" |
|||
RELEASE_MACOS = RELEASE_NAME + "-osx.dmg" |
|||
RELEASE_README = "README.mkd" |
|||
|
|||
# Patch release file |
|||
patch_version_file(RELEASE_VERSION) |
|||
|
|||
# Rename release notes file |
|||
safe_remove("README.txt") |
|||
shutil.copyfile(RELEASE_README, "README.txt") |
|||
|
|||
# Compile translations |
|||
if not os.path.exists("locale"): |
|||
run_external_command([sys.executable, "tools/make_mo.py"]) |
|||
|
|||
# Check again if translations exist, fail otherwise |
|||
if not os.path.exists("locale"): |
|||
raise FileNotFoundError("Failed to compile language files") |
|||
|
|||
# Make sure we remove any existing build-folders |
|||
safe_remove("build") |
|||
safe_remove("dist") |
|||
safe_remove(RELEASE_NAME) |
|||
|
|||
# Copy the specification |
|||
shutil.copyfile("builder/%s" % SPEC_FILE, SPEC_FILE) |
|||
|
|||
if "binary" in sys.argv or "installer" in sys.argv: |
|||
# Must be run on Windows |
|||
if sys.platform != "win32": |
|||
raise RuntimeError("Binary should be created on Windows") |
|||
|
|||
# Check what architecture we are on |
|||
RELEASE_BINARY = RELEASE_BINARY_32 |
|||
if platform.architecture()[0] == "64bit": |
|||
RELEASE_BINARY = RELEASE_BINARY_64 |
|||
|
|||
# Remove any leftovers |
|||
safe_remove(RELEASE_BINARY) |
|||
|
|||
# Run PyInstaller and check output |
|||
run_external_command([sys.executable, "-O", "-m", "PyInstaller", "SABnzbd.spec"]) |
|||
|
|||
# Use special distutils function to merge the main and console directories |
|||
copy_tree("dist/SABnzbd-console", "dist/SABnzbd") |
|||
safe_remove("dist/SABnzbd-console") |
|||
|
|||
# Remove unwanted DLL's |
|||
delete_files_glob("dist/SABnzbd/api-ms-win*.dll") |
|||
delete_files_glob("dist/SABnzbd/mfc140u.dll") |
|||
delete_files_glob("dist/SABnzbd/ucrtbase.dll") |
|||
|
|||
# Remove other files we don't need |
|||
delete_files_glob("dist/SABnzbd/PKG-INFO") |
|||
delete_files_glob("dist/SABnzbd/win32ui.pyd") |
|||
delete_files_glob("dist/SABnzbd/winxpgui.pyd") |
|||
|
|||
if "installer" in sys.argv: |
|||
# Needs to be run on 64 bit |
|||
if RELEASE_BINARY != RELEASE_BINARY_64: |
|||
raise RuntimeError("Installer should be created on 64bit Python") |
|||
|
|||
# Compile NSIS translations |
|||
safe_remove("NSIS_Installer.nsi") |
|||
safe_remove("NSIS_Installer.nsi.tmp") |
|||
shutil.copyfile("builder/win/NSIS_Installer.nsi", "NSIS_Installer.nsi") |
|||
run_external_command([sys.executable, "tools/make_mo.py", "nsis"]) |
|||
|
|||
# Remove 32bit external executables |
|||
delete_files_glob("dist/SABnzbd/win/par2/multipar/par2j.exe") |
|||
delete_files_glob("dist/SABnzbd/win/unrar/UnRAR.exe") |
|||
|
|||
# Run NSIS to build installer |
|||
run_external_command( |
|||
[ |
|||
"makensis.exe", |
|||
"/V3", |
|||
"/DSAB_PRODUCT=%s" % RELEASE_NAME, |
|||
"/DSAB_VERSION=%s" % RELEASE_VERSION, |
|||
"/DSAB_FILE=%s" % RELEASE_INSTALLER, |
|||
"NSIS_Installer.nsi.tmp", |
|||
] |
|||
) |
|||
|
|||
# Rename the folder |
|||
os.rename("dist/SABnzbd", RELEASE_NAME) |
|||
|
|||
# Create the archive |
|||
run_external_command(["win/7zip/7za.exe", "a", RELEASE_BINARY, RELEASE_NAME]) |
|||
|
|||
if "app" in sys.argv: |
|||
# Must be run on macOS |
|||
if sys.platform != "darwin": |
|||
raise RuntimeError("App should be created on macOS") |
|||
|
|||
# Who will sign and notarize this? |
|||
authority = os.environ.get("SIGNING_AUTH") |
|||
notarization_user = os.environ.get("NOTARIZATION_USER") |
|||
notarization_pass = os.environ.get("NOTARIZATION_PASS") |
|||
|
|||
# Run PyInstaller and check output |
|||
run_external_command([sys.executable, "-O", "-m", "PyInstaller", "SABnzbd.spec"]) |
|||
|
|||
# Only continue if we can sign |
|||
if authority: |
|||
files_to_sign = [ |
|||
"dist/SABnzbd.app/Contents/MacOS/osx/par2/par2-sl64", |
|||
"dist/SABnzbd.app/Contents/MacOS/osx/7zip/7za", |
|||
"dist/SABnzbd.app/Contents/MacOS/osx/unrar/unrar", |
|||
"dist/SABnzbd.app/Contents/MacOS/SABnzbd", |
|||
"dist/SABnzbd.app", |
|||
] |
|||
|
|||
for file_to_sign in files_to_sign: |
|||
print("Signing %s with hardended runtime" % file_to_sign) |
|||
run_external_command( |
|||
[ |
|||
"codesign", |
|||
"--deep", |
|||
"--force", |
|||
"--timestamp", |
|||
"--options", |
|||
"runtime", |
|||
"--entitlements", |
|||
"builder/osx/entitlements.plist", |
|||
"-i", |
|||
"org.sabnzbd.sabnzbd", |
|||
"-s", |
|||
authority, |
|||
file_to_sign, |
|||
], |
|||
) |
|||
print("Signed %s!" % file_to_sign) |
|||
|
|||
# Only notarize for real builds that we want to deploy |
|||
if notarization_user and notarization_pass and "release" in os.environ.get("TRAVIS_TAG", ""): |
|||
# Prepare zip to upload to notarization service |
|||
print("Creating zip to send to Apple notarization service") |
|||
# We need to use ditto, otherwise the signature gets lost! |
|||
notarization_zip = RELEASE_NAME + ".zip" |
|||
run_external_command( |
|||
["ditto", "-c", "-k", "--sequesterRsrc", "--keepParent", "dist/SABnzbd.app", notarization_zip] |
|||
) |
|||
|
|||
# Upload to Apple |
|||
print("Sending zip to Apple notarization service") |
|||
upload_process = run_external_command( |
|||
[ |
|||
"xcrun", |
|||
"altool", |
|||
"--notarize-app", |
|||
"-t", |
|||
"osx", |
|||
"-f", |
|||
notarization_zip, |
|||
"--primary-bundle-id", |
|||
"org.sabnzbd.sabnzbd", |
|||
"-u", |
|||
notarization_user, |
|||
"-p", |
|||
notarization_pass, |
|||
], |
|||
) |
|||
|
|||
# Extract the notarization ID |
|||
m = re.match(".*RequestUUID = (.*?)\n", upload_process, re.S) |
|||
if not m: |
|||
raise RuntimeError("No UUID created") |
|||
uuid = m.group(1) |
|||
|
|||
print("Checking notarization of UUID: %s (every 30 seconds)" % uuid) |
|||
notarization_in_progress = True |
|||
while notarization_in_progress: |
|||
time.sleep(30) |
|||
check_status = run_external_command( |
|||
[ |
|||
"xcrun", |
|||
"altool", |
|||
"--notarization-info", |
|||
uuid, |
|||
"-u", |
|||
notarization_user, |
|||
"-p", |
|||
notarization_pass, |
|||
], |
|||
) |
|||
notarization_in_progress = "Status: in progress" in check_status |
|||
|
|||
# Check if success |
|||
if "Status: success" not in check_status: |
|||
raise RuntimeError("Failed to notarize..") |
|||
|
|||
# Staple the notarization! |
|||
print("Approved! Stapling the result to the app") |
|||
run_external_command(["xcrun", "stapler", "staple", "dist/SABnzbd.app"]) |
|||
elif notarization_user and notarization_pass: |
|||
print("Notarization skipped, include 'release' in the name of the tag to trigger notarization!") |
|||
else: |
|||
print("Notarization skipped, NOTARIZATION_USER or NOTARIZATION_PASS missing.") |
|||
else: |
|||
print("Signing skipped, missing SIGNING_AUTH.") |
|||
|
|||
if "source" in sys.argv: |
|||
# Prepare Source distribution package. |
|||
# We assume the sources are freshly cloned from the repo |
|||
# Make sure all source files are Unix format |
|||
src_folder = "srcdist" |
|||
safe_remove(src_folder) |
|||
os.mkdir(src_folder) |
|||
|
|||
# Remove any leftovers |
|||
safe_remove(RELEASE_SRC) |
|||
|
|||
# Add extra files and folders need for source dist |
|||
extra_folders.extend(["sabnzbd/", "po/", "linux/", "tools/", "tests/"]) |
|||
extra_files.extend(["SABnzbd.py", "requirements.txt"]) |
|||
|
|||
# Copy all folders and files to the new folder |
|||
for source_folder in extra_folders: |
|||
copy_tree(source_folder, os.path.join(src_folder, source_folder)) |
|||
|
|||
# Copy all files |
|||
for source_file in extra_files: |
|||
shutil.copyfile(source_file, os.path.join(src_folder, source_file)) |
|||
|
|||
# Make sure all line-endings are correct |
|||
for input_filename in glob.glob("%s/**/*.*" % src_folder, recursive=True): |
|||
base, ext = os.path.splitext(input_filename) |
|||
if ext.lower() not in (".py", ".txt", ".css", ".js", ".tmpl", ".sh", ".cmd"): |
|||
continue |
|||
print(input_filename) |
|||
|
|||
with open(input_filename, "rb") as input_data: |
|||
data = input_data.read() |
|||
data = data.replace(b"\r", b"") |
|||
with open(input_filename, "wb") as output_data: |
|||
output_data.write(data) |
|||
|
|||
# Create tar.gz file for source distro |
|||
with tarfile.open(RELEASE_SRC, "w:gz") as tar_output: |
|||
for root, dirs, files in os.walk(src_folder): |
|||
for _file in files: |
|||
input_path = os.path.join(root, _file) |
|||
if sys.platform == "win32": |
|||
tar_path = input_path.replace("srcdist\\", RELEASE_NAME + "/").replace("\\", "/") |
|||
else: |
|||
tar_path = input_path.replace("srcdist/", RELEASE_NAME + "/") |
|||
tarinfo = tar_output.gettarinfo(input_path, tar_path) |
|||
tarinfo.uid = 0 |
|||
tarinfo.gid = 0 |
|||
if _file in ("SABnzbd.py", "Sample-PostProc.sh", "make_mo.py", "msgfmt.py"): |
|||
# Force Linux/OSX scripts as executable |
|||
tarinfo.mode = 0o755 |
|||
else: |
|||
tarinfo.mode = 0o644 |
|||
|
|||
with open(input_path, "rb") as f: |
|||
tar_output.addfile(tarinfo, f) |
|||
|
|||
# Remove source folder |
|||
safe_remove(src_folder) |
|||
|
|||
# Release to github |
|||
if "release" in sys.argv: |
|||
# Check if tagged as release |
|||
if "release" in os.environ.get("TRAVIS_TAG", "") + os.environ.get("APPVEYOR_REPO_TAG_NAME", ""): |
|||
# Check for token |
|||
gh_token = os.environ.get("GITHUB_TOKEN", "") |
|||
if gh_token: |
|||
gh_obj = github.Github(gh_token) |
|||
gh_repo = gh_obj.get_repo("sabnzbd/sabnzbd") |
|||
|
|||
# Read the release notes |
|||
with open(RELEASE_README, "r") as readme_file: |
|||
readme_data = readme_file.read() |
|||
|
|||
# Pre-releases are longer than 6 characters (e.g. 3.1.0Beta1 vs 3.1.0, but also 3.0.11) |
|||
prerelease = len(RELEASE_VERSION) > 5 |
|||
|
|||
# We have to manually check if we already created this release |
|||
for release in gh_repo.get_releases(): |
|||
if release.tag_name == RELEASE_VERSION: |
|||
gh_release = release |
|||
print("Found existing release %s" % gh_release.title) |
|||
break |
|||
else: |
|||
# Did not find it, so create the release |
|||
print("Creating GitHub release SABnzbd %s" % RELEASE_VERSION) |
|||
gh_release = gh_repo.create_git_release( |
|||
tag=RELEASE_VERSION, name=RELEASE_TITLE, message=readme_data, draft=True, prerelease=prerelease |
|||
) |
|||
|
|||
# Fetch existing assets, as overwriting is not allowed by GitHub |
|||
gh_assets = gh_release.get_assets() |
|||
|
|||
# Upload the assets |
|||
files_to_check = ( |
|||
RELEASE_SRC, |
|||
RELEASE_BINARY_32, |
|||
RELEASE_BINARY_64, |
|||
RELEASE_INSTALLER, |
|||
RELEASE_MACOS, |
|||
RELEASE_README, |
|||
) |
|||
for file_to_check in files_to_check: |
|||
if os.path.exists(file_to_check): |
|||
# Check if this file was previously uploaded |
|||
for gh_asset in gh_assets: |
|||
if gh_asset.name == file_to_check: |
|||
print("Removing existing asset %s for release %s" % (gh_asset.name, gh_release.title)) |
|||
gh_asset.delete_asset() |
|||
# Upload the new one |
|||
print("Uploading %s to release %s" % (file_to_check, gh_release.title)) |
|||
gh_release.upload_asset(file_to_check) |
|||
|
|||
# Update the website |
|||
gh_repo_web = gh_obj.get_repo("sabnzbd/sabnzbd.github.io") |
|||
# Check if the branch already exists, only create one if it doesn't |
|||
skip_website_update = False |
|||
try: |
|||
gh_repo_web.get_branch(RELEASE_VERSION) |
|||
print("Branch %s on sabnzbd/sabnzbd.github.io already exists, skipping update" % RELEASE_VERSION) |
|||
skip_website_update = True |
|||
except github.GithubException: |
|||
# Create a new branch to have the changes |
|||
sb = gh_repo_web.get_branch("master") |
|||
print("Creating branch %s on sabnzbd/sabnzbd.github.io" % RELEASE_VERSION) |
|||
new_branch = gh_repo_web.create_git_ref(ref="refs/heads/" + RELEASE_VERSION, sha=sb.commit.sha) |
|||
|
|||
# Update the files |
|||
if not skip_website_update: |
|||
# We need bytes version to interact with GitHub |
|||
RELEASE_VERSION_BYTES = RELEASE_VERSION.encode() |
|||
|
|||
# Get all the version files |
|||
latest_txt = gh_repo_web.get_contents("latest.txt") |
|||
latest_txt_items = latest_txt.decoded_content.split() |
|||
new_latest_txt_items = latest_txt_items[:2] |
|||
config_yml = gh_repo_web.get_contents("_config.yml") |
|||
if prerelease: |
|||
# If it's a pre-release, we append to current version in latest.txt |
|||
new_latest_txt_items.extend([RELEASE_VERSION_BYTES, latest_txt_items[1]]) |
|||
# And replace in _config.yml |
|||
new_config_yml = re.sub( |
|||
b"latest_testing: '[^']*'", |
|||
b"latest_testing: '%s'" % RELEASE_VERSION_BYTES, |
|||
config_yml.decoded_content, |
|||
) |
|||
else: |
|||
# New stable release, replace the version |
|||
new_latest_txt_items[0] = RELEASE_VERSION_BYTES |
|||
# And replace in _config.yml |
|||
new_config_yml = re.sub( |
|||
b"latest_testing: '[^']*'", |
|||
b"latest_testing: ''", |
|||
config_yml.decoded_content, |
|||
) |
|||
new_config_yml = re.sub( |
|||
b"latest_stable: '[^']*'", |
|||
b"latest_stable: '%s'" % RELEASE_VERSION_BYTES, |
|||
new_config_yml, |
|||
) |
|||
# Also update the wiki-settings, these only use x.x notation |
|||
new_config_yml = re.sub( |
|||
b"wiki_version: '[^']*'", |
|||
b"wiki_version: '%s'" % RELEASE_VERSION_BYTES[:3], |
|||
new_config_yml, |
|||
) |
|||
|
|||
# Update the files |
|||
print("Updating latest.txt") |
|||
gh_repo_web.update_file( |
|||
"latest.txt", |
|||
"Release %s: latest.txt" % RELEASE_VERSION, |
|||
b"\n".join(new_latest_txt_items), |
|||
latest_txt.sha, |
|||
RELEASE_VERSION, |
|||
) |
|||
print("Updating _config.yml") |
|||
gh_repo_web.update_file( |
|||
"_config.yml", |
|||
"Release %s: _config.yml" % RELEASE_VERSION, |
|||
new_config_yml, |
|||
config_yml.sha, |
|||
RELEASE_VERSION, |
|||
) |
|||
|
|||
# Create pull-request |
|||
print("Creating pull request in sabnzbd/sabnzbd.github.io for the update") |
|||
gh_repo_web.create_pull( |
|||
title=RELEASE_VERSION, |
|||
base="master", |
|||
body="Automated update of release files", |
|||
head=RELEASE_VERSION, |
|||
) |
|||
else: |
|||
print("Missing GITHUB_TOKEN, cannot push to GitHub!") |
|||
else: |
|||
print("To push release to GitHub, include 'release' in the name of the tag") |
|||
|
|||
# Reset! |
|||
run_git_command(["reset", "--hard"]) |
|||
run_git_command(["clean", "-f"]) |
@ -0,0 +1,9 @@ |
|||
# Basic build requirements |
|||
pyinstaller |
|||
setuptools |
|||
pkginfo |
|||
certifi |
|||
pygithub |
|||
|
|||
# For the OSX build specific |
|||
dmgbuild; sys_platform == 'darwin' |
@ -0,0 +1,396 @@ |
|||
; -*- coding: utf-8 -*- |
|||
; |
|||
; Copyright 2008-2015 The SABnzbd-Team <team@sabnzbd.org> |
|||
; |
|||
; This program is free software; you can redistribute it and/or |
|||
; modify it under the terms of the GNU General Public License |
|||
; as published by the Free Software Foundation; either version 2 |
|||
; of the License, or (at your option) any later version. |
|||
; |
|||
; This program is distributed in the hope that it will be useful, |
|||
; but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
; GNU General Public License for more details. |
|||
; |
|||
; You should have received a copy of the GNU General Public License |
|||
; along with this program; if not, write to the Free Software |
|||
; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|||
|
|||
Unicode true |
|||
|
|||
!addplugindir builder\win\nsis\Plugins |
|||
!addincludedir builder\win\nsis\Include |
|||
|
|||
!include "MUI2.nsh" |
|||
!include "registerExtension.nsh" |
|||
!include "FileFunc.nsh" |
|||
!include "LogicLib.nsh" |
|||
!include "WinVer.nsh" |
|||
!include "nsProcess.nsh" |
|||
!include "x64.nsh" |
|||
!include "servicelib.nsh" |
|||
|
|||
;------------------------------------------------------------------ |
|||
; |
|||
; Marco for removing existing and the current installation |
|||
; It shared by the installer and the uninstaller. |
|||
; |
|||
!define RemovePrev "!insertmacro RemovePrev" |
|||
!macro RemovePrev idir |
|||
; Remove the whole dir |
|||
; Users should not be putting stuff here! |
|||
RMDir /r "${idir}" |
|||
!macroend |
|||
|
|||
;------------------------------------------------------------------ |
|||
; Define names of the product |
|||
Name "${SAB_PRODUCT}" |
|||
OutFile "${SAB_FILE}" |
|||
InstallDir "$PROGRAMFILES\SABnzbd" |
|||
|
|||
|
|||
;------------------------------------------------------------------ |
|||
; Some default compiler settings (uncomment and change at will): |
|||
SetCompress auto ; (can be off or force) |
|||
SetDatablockOptimize on ; (can be off) |
|||
CRCCheck on ; (can be off) |
|||
AutoCloseWindow false ; (can be true for the window go away automatically at end) |
|||
ShowInstDetails hide ; (can be show to have them shown, or nevershow to disable) |
|||
SetDateSave off ; (can be on to have files restored to their orginal date) |
|||
WindowIcon on |
|||
SpaceTexts none |
|||
|
|||
|
|||
;------------------------------------------------------------------ |
|||
; Vista/Win7 redirects $SMPROGRAMS to all users without this |
|||
RequestExecutionLevel admin |
|||
FileErrorText "If you have no admin rights, try to install into a user directory." |
|||
|
|||
|
|||
;------------------------------------------------------------------ |
|||
;Variables |
|||
Var MUI_TEMP |
|||
Var STARTMENU_FOLDER |
|||
Var PREV_INST_DIR |
|||
|
|||
;------------------------------------------------------------------ |
|||
;Interface Settings |
|||
|
|||
!define MUI_ABORTWARNING |
|||
|
|||
;Show all languages, despite user's codepage |
|||
!define MUI_LANGDLL_ALLLANGUAGES |
|||
|
|||
!define MUI_ICON "dist\SABnzbd\icons\sabnzbd.ico" |
|||
|
|||
|
|||
;-------------------------------- |
|||
;Pages |
|||
|
|||
!insertmacro MUI_PAGE_LICENSE "dist\SABnzbd\LICENSE.txt" |
|||
!define MUI_COMPONENTSPAGE_NODESC |
|||
!insertmacro MUI_PAGE_COMPONENTS |
|||
|
|||
!insertmacro MUI_PAGE_DIRECTORY |
|||
|
|||
;Start Menu Folder Page Configuration |
|||
!define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKCU" |
|||
!define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\SABnzbd" |
|||
!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder" |
|||
!define MUI_STARTMENUPAGE_DEFAULTFOLDER "SABnzbd" |
|||
;Remember the installer language |
|||
!define MUI_LANGDLL_REGISTRY_ROOT "HKCU" |
|||
!define MUI_LANGDLL_REGISTRY_KEY "Software\SABnzbd" |
|||
!define MUI_LANGDLL_REGISTRY_VALUENAME "Installer Language" |
|||
|
|||
!insertmacro MUI_PAGE_STARTMENU Application $STARTMENU_FOLDER |
|||
|
|||
!insertmacro MUI_PAGE_INSTFILES |
|||
; !define MUI_FINISHPAGE_RUN |
|||
; !define MUI_FINISHPAGE_RUN_FUNCTION PageFinishRun |
|||
; !define MUI_FINISHPAGE_RUN_TEXT $(MsgRunSAB) |
|||
!define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\README.txt" |
|||
!define MUI_FINISHPAGE_SHOWREADME_TEXT $(MsgShowRelNote) |
|||
!define MUI_FINISHPAGE_LINK $(MsgSupportUs) |
|||
!define MUI_FINISHPAGE_LINK_LOCATION "https://sabnzbd.org/donate" |
|||
|
|||
!insertmacro MUI_PAGE_FINISH |
|||
|
|||
!insertmacro MUI_UNPAGE_CONFIRM |
|||
!define MUI_UNPAGE_COMPONENTSPAGE_NODESC |
|||
!insertmacro MUI_UNPAGE_COMPONENTS |
|||
!insertmacro MUI_UNPAGE_INSTFILES |
|||
|
|||
;------------------------------------------------------------------ |
|||
; Run as user-level at end of install |
|||
; DOES NOT WORK |
|||
; Function PageFinishRun |
|||
; !insertmacro UAC_AsUser_ExecShell "" "$INSTDIR\SABnzbd.exe" "" "" "" |
|||
; FunctionEnd |
|||
|
|||
|
|||
;------------------------------------------------------------------ |
|||
; Set supported languages |
|||
; |
|||
; If you edit this list you also need to edit apireg.py in SABnzbd! |
|||
; |
|||
!insertmacro MUI_LANGUAGE "English" ;first language is the default language |
|||
!insertmacro MUI_LANGUAGE "French" |
|||
!insertmacro MUI_LANGUAGE "German" |
|||
!insertmacro MUI_LANGUAGE "Dutch" |
|||
!insertmacro MUI_LANGUAGE "Finnish" |
|||
!insertmacro MUI_LANGUAGE "Polish" |
|||
!insertmacro MUI_LANGUAGE "Swedish" |
|||
!insertmacro MUI_LANGUAGE "Danish" |
|||
!insertmacro MUI_LANGUAGE "Norwegian" |
|||
!insertmacro MUI_LANGUAGE "Romanian" |
|||
!insertmacro MUI_LANGUAGE "Spanish" |
|||
!insertmacro MUI_LANGUAGE "PortugueseBR" |
|||
!insertmacro MUI_LANGUAGE "Serbian" |
|||
!insertmacro MUI_LANGUAGE "Hebrew" |
|||
!insertmacro MUI_LANGUAGE "Russian" |
|||
!insertmacro MUI_LANGUAGE "Czech" |
|||
!insertmacro MUI_LANGUAGE "SimpChinese" |
|||
|
|||
|
|||
|
|||
;------------------------------------------------------------------ |
|||
;Reserve Files |
|||
;If you are using solid compression, files that are required before |
|||
;the actual installation should be stored first in the data block, |
|||
;because this will make your installer start faster. |
|||
|
|||
!insertmacro MUI_RESERVEFILE_LANGDLL |
|||
|
|||
|
|||
;------------------------------------------------------------------ |
|||
; SECTION main program |
|||
; |
|||
Section "SABnzbd" SecDummy |
|||
|
|||
SetOutPath "$INSTDIR" |
|||
|
|||
;------------------------------------------------------------------ |
|||
; Make sure old versions are gone (reg-key already read in onInt) |
|||
StrCmp $PREV_INST_DIR "" noPrevInstallRemove |
|||
${RemovePrev} "$PREV_INST_DIR" |
|||
noPrevInstallRemove: |
|||
|
|||
; add files / whatever that need to be installed here. |
|||
File /r "dist\SABnzbd\*" |
|||
|
|||
;------------------------------------------------------------------ |
|||
; Add firewall rules |
|||
liteFirewallW::AddRule "$INSTDIR\SABnzbd.exe" "SABnzbd" |
|||
liteFirewallW::AddRule "$INSTDIR\SABnzbd-console.exe" "SABnzbd-console" |
|||
|
|||
;------------------------------------------------------------------ |
|||
; Add to registery |
|||
WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\SABnzbd" "" "$INSTDIR" |
|||
WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\SABnzbd" "Installer Language" "$(MsgLangCode)" |
|||
WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\SABnzbd" "DisplayName" "SABnzbd ${SAB_VERSION}" |
|||
WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\SABnzbd" "UninstallString" '"$INSTDIR\uninstall.exe"' |
|||
WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\SABnzbd" "DisplayVersion" '${SAB_VERSION}' |
|||
WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\SABnzbd" "Publisher" 'The SABnzbd Team' |
|||
WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\SABnzbd" "HelpLink" 'https://forums.sabnzbd.org/' |
|||
WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\SABnzbd" "URLInfoAbout" 'https://sabnzbd.org/wiki/' |
|||
WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\SABnzbd" "URLUpdateInfo" 'https://sabnzbd.org/' |
|||
WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\SABnzbd" "Comments" 'The automated Usenet download tool' |
|||
WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\SABnzbd" "DisplayIcon" '$INSTDIR\icons\sabnzbd.ico' |
|||
WriteRegDWORD HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\SABnzbd" "EstimatedSize" 25674 |
|||
WriteRegDWORD HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\SABnzbd" "NoRepair" -1 |
|||
WriteRegDWORD HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\SABnzbd" "NoModify" -1 |
|||
; write out uninstaller |
|||
WriteUninstaller "$INSTDIR\Uninstall.exe" |
|||
|
|||
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application |
|||
;Create shortcuts |
|||
CreateDirectory "$SMPROGRAMS\$STARTMENU_FOLDER" |
|||
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\SABnzbd.lnk" "$INSTDIR\SABnzbd.exe" |
|||
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\SABnzbd - SafeMode.lnk" "$INSTDIR\SABnzbd.exe" "--server 127.0.0.1:8080 -b1 --no-login" |
|||
WriteINIStr "$SMPROGRAMS\$STARTMENU_FOLDER\SABnzbd - Documentation.url" "InternetShortcut" "URL" "https://sabnzbd.org/wiki/" |
|||
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Uninstall.lnk" "$INSTDIR\Uninstall.exe" |
|||
!insertmacro MUI_STARTMENU_WRITE_END |
|||
SectionEnd ; end of default section |
|||
|
|||
Section $(MsgIcon) desktop |
|||
CreateShortCut "$DESKTOP\SABnzbd.lnk" "$INSTDIR\SABnzbd.exe" |
|||
SectionEnd ; end of desktop icon section |
|||
|
|||
Section $(MsgAssoc) assoc |
|||
${registerExtension} "$INSTDIR\icons\nzb.ico" "$INSTDIR\SABnzbd.exe" ".nzb" "NZB File" |
|||
${RefreshShellIcons} |
|||
SectionEnd ; end of file association section |
|||
|
|||
Section /o $(MsgRunAtStart) startup |
|||
CreateShortCut "$SMPROGRAMS\Startup\SABnzbd.lnk" "$INSTDIR\SABnzbd.exe" "-b0" |
|||
SectionEnd ; |
|||
|
|||
;------------------------------------------------------------------ |
|||
Function .onInit |
|||
; We need to modify the dir here for X64 |
|||
${If} ${RunningX64} |
|||
StrCpy $INSTDIR "$PROGRAMFILES64\SABnzbd" |
|||
${Else} |
|||
MessageBox MB_OK $(MsgOnly64bit) |
|||
ExecShell "open" "https://sabnzbd.org/downloads" |
|||
Abort |
|||
${EndIf} |
|||
|
|||
;------------------------------------------------------------------ |
|||
; Change settings based on if SAB was already installed |
|||
ReadRegStr $PREV_INST_DIR HKEY_LOCAL_MACHINE "SOFTWARE\SABnzbd" "" |
|||
StrCmp $PREV_INST_DIR "" noPrevInstall |
|||
; We want to use the user's costom dir if he used one |
|||
StrCmp $PREV_INST_DIR "$PROGRAMFILES\SABnzbd" noSpecialDir |
|||
StrCmp $PREV_INST_DIR "$PROGRAMFILES64\SABnzbd" noSpecialDir |
|||
; Set what the user had before |
|||
StrCpy $INSTDIR "$PREV_INST_DIR" |
|||
noSpecialDir: |
|||
|
|||
;------------------------------------------------------------------ |
|||
; Check what the user has currently set for install options |
|||
IfFileExists "$SMPROGRAMS\Startup\SABnzbd.lnk" 0 endCheckStartup |
|||
SectionSetFlags ${startup} 1 |
|||
endCheckStartup: |
|||
|
|||
IfFileExists "$DESKTOP\SABnzbd.lnk" endCheckDesktop 0 |
|||
SectionSetFlags ${desktop} 0 ; SAB is installed but desktop-icon not, so uncheck it |
|||
endCheckDesktop: |
|||
|
|||
Push $1 |
|||
ReadRegStr $1 HKCR ".nzb" "" ; read current file association |
|||
StrCmp "$1" "NZB File" noPrevInstall 0 |
|||
SectionSetFlags ${assoc} 0 ; Uncheck it when it wasn't checked before |
|||
noPrevInstall: |
|||
|
|||
;-------------------------------- |
|||
; Display language chooser |
|||
!insertmacro MUI_LANGDLL_DISPLAY |
|||
|
|||
;------------------------------------------------------------------ |
|||
; make sure user terminates sabnzbd.exe or else abort |
|||
; |
|||
loop: |
|||
${nsProcess::FindProcess} "SABnzbd.exe" $R0 |
|||
StrCmp $R0 0 0 endcheck |
|||
MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION $(MsgCloseSab) IDOK loop IDCANCEL exitinstall |
|||
exitinstall: |
|||
${nsProcess::Unload} |
|||
Abort |
|||
endcheck: |
|||
|
|||
;------------------------------------------------------------------ |
|||
; make sure both services aren't running |
|||
; |
|||
!insertmacro SERVICE "running" "SABnzbd" "" |
|||
Pop $0 ;response |
|||
!insertmacro SERVICE "running" "SABHelper" "" |
|||
Pop $1 |
|||
${If} $0 == true |
|||
${OrIf} $1 == true |
|||
MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION $(MsgCloseSab) IDOK loop IDCANCEL exitinstall |
|||
; exitinstall already defined above |
|||
${EndIf} |
|||
|
|||
;------------------------------------------------------------------ |
|||
; Tell users about the service change |
|||
; |
|||
!insertmacro SERVICE "installed" "SABHelper" "" |
|||
Pop $0 ;response |
|||
${If} $0 == true |
|||
MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION $(MsgServChange) IDOK removeservices IDCANCEL exitinstall |
|||
; exitinstall already defined above |
|||
removeservices: |
|||
!insertmacro SERVICE "delete" "SABHelper" "" |
|||
!insertmacro SERVICE "delete" "SABnzbd" "" |
|||
${EndIf} |
|||
|
|||
FunctionEnd |
|||
|
|||
;------------------------------------------------------------------ |
|||
; Show the shortcuts at end of install so user can start SABnzbd |
|||
; This is instead of us trying to run SAB from the installer |
|||
; |
|||
Function .onInstSuccess |
|||
ExecShell "open" "$SMPROGRAMS\$STARTMENU_FOLDER" |
|||
FunctionEnd |
|||
|
|||
;-------------------------------- |
|||
; begin uninstall settings/section |
|||
UninstallText $(MsgUninstall) |
|||
|
|||
Section "un.$(MsgDelProgram)" Uninstall |
|||
;make sure sabnzbd.exe isnt running..if so shut it down |
|||
${nsProcess::KillProcess} "SABnzbd.exe" $R0 |
|||
${nsProcess::Unload} |
|||
DetailPrint "Process Killed" |
|||
|
|||
|
|||
; add delete commands to delete whatever files/registry keys/etc you installed here. |
|||
Delete "$INSTDIR\uninstall.exe" |
|||
DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\SABnzbd" |
|||
DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\SABnzbd" |
|||
|
|||
${RemovePrev} "$INSTDIR" |
|||
|
|||
!insertmacro MUI_STARTMENU_GETFOLDER Application $MUI_TEMP |
|||
|
|||
Delete "$SMPROGRAMS\$MUI_TEMP\SABnzbd.lnk" |
|||
Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk" |
|||
Delete "$SMPROGRAMS\$MUI_TEMP\SABnzbd - SafeMode.lnk" |
|||
Delete "$SMPROGRAMS\$MUI_TEMP\SABnzbd - Documentation.url" |
|||
RMDir "$SMPROGRAMS\$MUI_TEMP" |
|||
|
|||
Delete "$SMPROGRAMS\Startup\SABnzbd.lnk" |
|||
|
|||
Delete "$DESKTOP\SABnzbd.lnk" |
|||
|
|||
DeleteRegKey HKEY_CURRENT_USER "Software\SABnzbd" |
|||
|
|||
${unregisterExtension} ".nzb" "NZB File" |
|||
${RefreshShellIcons} |
|||
|
|||
SectionEnd ; end of uninstall section |
|||
|
|||
Section /o "un.$(MsgDelSettings)" DelSettings |
|||
DetailPrint "Uninstall settings $LOCALAPPDATA" |
|||
Delete "$LOCALAPPDATA\sabnzbd\sabnzbd.ini" |
|||
RMDir /r "$LOCALAPPDATA\sabnzbd" |
|||
SectionEnd |
|||
|
|||
; eof |
|||
|
|||
;-------------------------------- |
|||
;Language strings |
|||
LangString MsgShowRelNote ${LANG_ENGLISH} "Show Release Notes" |
|||
|
|||
LangString MsgSupportUs ${LANG_ENGLISH} "Support the project, Donate!" |
|||
|
|||
LangString MsgCloseSab ${LANG_ENGLISH} "Please close $\"SABnzbd.exe$\" first" |
|||
|
|||
LangString MsgServChange ${LANG_ENGLISH} "The SABnzbd Windows Service changed in SABnzbd 3.0.0. $\nYou will need to reinstall the SABnzbd service. $\n$\nClick `OK` to remove the existing services or `Cancel` to cancel this upgrade." |
|||
|
|||
LangString MsgOnly64bit ${LANG_ENGLISH} "The installer only supports 64-bit Windows, use the standalone version to run on 32-bit Windows." |
|||
|
|||
LangString MsgUninstall ${LANG_ENGLISH} "This will uninstall SABnzbd from your system" |
|||
|
|||
LangString MsgRunAtStart ${LANG_ENGLISH} "Run at startup" |
|||
|
|||
LangString MsgIcon ${LANG_ENGLISH} "Desktop Icon" |
|||
|
|||
LangString MsgAssoc ${LANG_ENGLISH} "NZB File association" |
|||
|
|||
LangString MsgDelProgram ${LANG_ENGLISH} "Delete Program" |
|||
|
|||
LangString MsgDelSettings ${LANG_ENGLISH} "Delete Settings" |
|||
|
|||
LangString MsgRemoveOld ${LANG_ENGLISH} "You cannot overwrite an existing installation. $\n$\nClick `OK` to remove the previous version or `Cancel` to cancel this upgrade." |
|||
|
|||
LangString MsgRemoveOld2 ${LANG_ENGLISH} "Your settings and data will be preserved." |
|||
|
|||
LangString MsgLangCode ${LANG_ENGLISH} "en" |
|||
|
|||
Function un.onInit |
|||
!insertmacro MUI_UNGETLANGUAGE |
|||
FunctionEnd |
@ -0,0 +1,28 @@ |
|||
!define nsProcess::FindProcess `!insertmacro nsProcess::FindProcess` |
|||
|
|||
!macro nsProcess::FindProcess _FILE _ERR |
|||
nsProcess::_FindProcess /NOUNLOAD `${_FILE}` |
|||
Pop ${_ERR} |
|||
!macroend |
|||
|
|||
|
|||
!define nsProcess::KillProcess `!insertmacro nsProcess::KillProcess` |
|||
|
|||
!macro nsProcess::KillProcess _FILE _ERR |
|||
nsProcess::_KillProcess /NOUNLOAD `${_FILE}` |
|||
Pop ${_ERR} |
|||
!macroend |
|||
|
|||
!define nsProcess::CloseProcess `!insertmacro nsProcess::CloseProcess` |
|||
|
|||
!macro nsProcess::CloseProcess _FILE _ERR |
|||
nsProcess::_CloseProcess /NOUNLOAD `${_FILE}` |
|||
Pop ${_ERR} |
|||
!macroend |
|||
|
|||
|
|||
!define nsProcess::Unload `!insertmacro nsProcess::Unload` |
|||
|
|||
!macro nsProcess::Unload |
|||
nsProcess::_Unload |
|||
!macroend |
@ -0,0 +1,53 @@ |
|||
!define registerExtension "!insertmacro registerExtension" |
|||
!define unregisterExtension "!insertmacro unregisterExtension" |
|||
!define SHCNE_ASSOCCHANGED 0x8000000 |
|||
!define SHCNF_IDLIST 0 |
|||
|
|||
; Source = http://nsis.sourceforge.net/File_Association |
|||
; Patched for SABnzbd by swi-tch |
|||
|
|||
!macro registerExtension icon executable extension description |
|||
Push "${icon}" ; "full path to icon.ico" |
|||
Push "${executable}" ; "full path to my.exe" |
|||
Push "${extension}" ; ".mkv" |
|||
Push "${description}" ; "MKV File" |
|||
Call registerExtension |
|||
!macroend |
|||
|
|||
; back up old value of .opt |
|||
Function registerExtension |
|||
!define Index "Line${__LINE__}" |
|||
pop $R0 ; ext name |
|||
pop $R1 |
|||
pop $R2 |
|||
pop $R3 |
|||
push $1 |
|||
push $0 |
|||
DeleteRegKey HKEY_CURRENT_USER "Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$R1" |
|||
WriteRegStr HKCR $R1 "" $R0 |
|||
WriteRegStr HKCR $R0 "" $R0 |
|||
WriteRegStr HKCR "$R0\shell" "" "open" |
|||
WriteRegStr HKCR "$R0\DefaultIcon" "" "$R3,0" |
|||
WriteRegStr HKCR "$R0\shell\open\command" "" '"$R2" "%1"' |
|||
WriteRegStr HKCR "$R0\shell\edit" "" "Edit $R0" |
|||
WriteRegStr HKCR "$R0\shell\edit\command" "" '"$R2" "%1"' |
|||
pop $0 |
|||
pop $1 |
|||
!undef Index |
|||
System::Call 'Shell32::SHChangeNotify(i ${SHCNE_ASSOCCHANGED}, i ${SHCNF_IDLIST}, i 0, i 0)' |
|||
FunctionEnd |
|||
|
|||
!macro unregisterExtension extension description |
|||
Push "${extension}" ; ".mkv" |
|||
Push "${description}" ; "MKV File" |
|||
Call un.unregisterExtension |
|||
!macroend |
|||
|
|||
Function un.unregisterExtension |
|||
pop $R1 ; description |
|||
pop $R0 ; extension |
|||
!define Index "Line${__LINE__}" |
|||
DeleteRegKey HKCR $R0 |
|||
!undef Index |
|||
System::Call 'Shell32::SHChangeNotify(i ${SHCNE_ASSOCCHANGED}, i ${SHCNF_IDLIST}, i 0, i 0)' |
|||
FunctionEnd |
@ -0,0 +1,411 @@ |
|||
; NSIS SERVICE LIBRARY - servicelib.nsh |
|||
; Version 1.8.1 - Jun 21th, 2013 |
|||
; Questions/Comments - dselkirk@hotmail.com |
|||
; |
|||
; Description: |
|||
; Provides an interface to window services |
|||
; |
|||
; Inputs: |
|||
; action - systemlib action ie. create, delete, start, stop, pause, |
|||
; continue, installed, running, status |
|||
; name - name of service to manipulate |
|||
; param - action parameters; usage: var1=value1;var2=value2;...etc. |
|||
; (don't forget to add a ';' after the last value!) |
|||
; |
|||
; Actions: |
|||
; create - creates a new windows service |
|||
; Parameters: |
|||
; path - path to service executable |
|||
; autostart - automatically start with system ie. 1|0 |
|||
; interact - interact with the desktop ie. 1|0 |
|||
; depend - service dependencies |
|||
; user - user that runs the service |
|||
; password - password of the above user |
|||
; display - display name in service's console |
|||
; description - Description of service |
|||
; starttype - start type (supersedes autostart) |
|||
; servicetype - service type (supersedes interact) |
|||
; |
|||
; delete - deletes a windows service |
|||
; start - start a stopped windows service |
|||
; stop - stops a running windows service |
|||
; pause - pauses a running windows service |
|||
; continue - continues a paused windows service |
|||
; installed - is the provided service installed |
|||
; Parameters: |
|||
; action - if true then invokes the specified action |
|||
; running - is the provided service running |
|||
; Parameters: |
|||
; action - if true then invokes the specified action |
|||
; status - check the status of the provided service |
|||
; |
|||
; Usage: |
|||
; Method 1: |
|||
; Push "action" |
|||
; Push "name" |
|||
; Push "param" |
|||
; Call Service |
|||
; Pop $0 ;response |
|||
; |
|||
; Method 2: |
|||
; !insertmacro SERVICE "action" "name" "param" |
|||
; |
|||
; History: |
|||
; 1.0 - 09/15/2003 - Initial release |
|||
; 1.1 - 09/16/2003 - Changed &l to i, thx brainsucker |
|||
; 1.2 - 02/29/2004 - Fixed documentation. |
|||
; 1.3 - 01/05/2006 - Fixed interactive flag and pop order (Kichik) |
|||
; 1.4 - 12/07/2006 - Added display and depend, fixed datatypes (Vitoco) |
|||
; 1.5 - 06/25/2008 - Added description of service.(DeSafe.com/liuqixing#gmail.com) |
|||
; 1.5.1 - 06/12/2009 - Added use of __UNINSTALL__ |
|||
; 1.6 - 08/02/2010 - Fixed description implementation (Anders) |
|||
; 1.7 - 04/11/2010 - Added get running service process id (Nico) |
|||
; 1.8 - 24/03/2011 - Added starttype and servicetype (Sergius) |
|||
; 1.8.1 - 21/06/2013 - Added dynamic ASCII & Unicode support (Zinthose) |
|||
|
|||
!ifndef SERVICELIB |
|||
!define SERVICELIB |
|||
|
|||
!define SC_MANAGER_ALL_ACCESS 0x3F |
|||
!define SC_STATUS_PROCESS_INFO 0x0 |
|||
!define SERVICE_ALL_ACCESS 0xF01FF |
|||
|
|||
!define SERVICE_CONTROL_STOP 1 |
|||
!define SERVICE_CONTROL_PAUSE 2 |
|||
!define SERVICE_CONTROL_CONTINUE 3 |
|||
|
|||
!define SERVICE_STOPPED 0x1 |
|||
!define SERVICE_START_PENDING 0x2 |
|||
!define SERVICE_STOP_PENDING 0x3 |
|||
!define SERVICE_RUNNING 0x4 |
|||
!define SERVICE_CONTINUE_PENDING 0x5 |
|||
!define SERVICE_PAUSE_PENDING 0x6 |
|||
!define SERVICE_PAUSED 0x7 |
|||
|
|||
!define SERVICE_KERNEL_DRIVER 0x00000001 |
|||
!define SERVICE_FILE_SYSTEM_DRIVER 0x00000002 |
|||
!define SERVICE_WIN32_OWN_PROCESS 0x00000010 |
|||
!define SERVICE_WIN32_SHARE_PROCESS 0x00000020 |
|||
!define SERVICE_INTERACTIVE_PROCESS 0x00000100 |
|||
|
|||
|
|||
!define SERVICE_BOOT_START 0x00000000 |
|||
!define SERVICE_SYSTEM_START 0x00000001 |
|||
!define SERVICE_AUTO_START 0x00000002 |
|||
!define SERVICE_DEMAND_START 0x00000003 |
|||
!define SERVICE_DISABLED 0x00000004 |
|||
|
|||
## Added by Zinthose for Native Unicode Support |
|||
!ifdef NSIS_UNICODE |
|||
!define APITAG "W" |
|||
!else |
|||
!define APITAG "A" |
|||
!endif |
|||
|
|||
!macro SERVICE ACTION NAME PARAM |
|||
Push '${ACTION}' |
|||
Push '${NAME}' |
|||
Push '${PARAM}' |
|||
!ifdef __UNINSTALL__ |
|||
Call un.Service |
|||
!else |
|||
Call Service |
|||
!endif |
|||
!macroend |
|||
|
|||
!macro FUNC_GETPARAM |
|||
Push $0 |
|||
Push $1 |
|||
Push $2 |
|||
Push $3 |
|||
Push $4 |
|||
Push $5 |
|||
Push $6 |
|||
Push $7 |
|||
Exch 8 |
|||
Pop $1 ;name |
|||
Exch 8 |
|||
Pop $2 ;source |
|||
StrCpy $0 "" |
|||
StrLen $7 $2 |
|||
StrCpy $3 0 |
|||
lbl_loop: |
|||
IntCmp $3 $7 0 0 lbl_done |
|||
StrLen $4 "$1=" |
|||
StrCpy $5 $2 $4 $3 |
|||
StrCmp $5 "$1=" 0 lbl_next |
|||
IntOp $5 $3 + $4 |
|||
StrCpy $3 $5 |
|||
lbl_loop2: |
|||
IntCmp $3 $7 0 0 lbl_done |
|||
StrCpy $6 $2 1 $3 |
|||
StrCmp $6 ";" 0 lbl_next2 |
|||
IntOp $6 $3 - $5 |
|||
StrCpy $0 $2 $6 $5 |
|||
Goto lbl_done |
|||
lbl_next2: |
|||
IntOp $3 $3 + 1 |
|||
Goto lbl_loop2 |
|||
lbl_next: |
|||
IntOp $3 $3 + 1 |
|||
Goto lbl_loop |
|||
lbl_done: |
|||
Pop $5 |
|||
Pop $4 |
|||
Pop $3 |
|||
Pop $2 |
|||
Pop $1 |
|||
Exch 2 |
|||
Pop $6 |
|||
Pop $7 |
|||
Exch $0 |
|||
!macroend |
|||
|
|||
!macro CALL_GETPARAM VAR NAME DEFAULT LABEL |
|||
Push $1 |
|||
Push ${NAME} |
|||
Call ${UN}GETPARAM |
|||
Pop $6 |
|||
StrCpy ${VAR} "${DEFAULT}" |
|||
StrCmp $6 "" "${LABEL}" 0 |
|||
StrCpy ${VAR} $6 |
|||
!macroend |
|||
|
|||
!macro FUNC_SERVICE UN |
|||
Push $0 |
|||
Push $1 |
|||
Push $2 |
|||
Push $3 |
|||
Push $4 |
|||
Push $5 |
|||
Push $6 |
|||
Push $7 |
|||
Exch 8 |
|||
Pop $1 ;param |
|||
Exch 8 |
|||
Pop $2 ;name |
|||
Exch 8 |
|||
Pop $3 ;action |
|||
;$0 return |
|||
;$4 OpenSCManager |
|||
;$5 OpenService |
|||
|
|||
StrCpy $0 "false" |
|||
System::Call 'advapi32::OpenSCManager${APITAG}(n, n, i ${SC_MANAGER_ALL_ACCESS}) i.r4' |
|||
IntCmp $4 0 lbl_done |
|||
StrCmp $3 "create" lbl_create |
|||
System::Call 'advapi32::OpenService${APITAG}(i r4, t r2, i ${SERVICE_ALL_ACCESS}) i.r5' |
|||
IntCmp $5 0 lbl_done |
|||
|
|||
lbl_select: |
|||
StrCmp $3 "delete" lbl_delete |
|||
StrCmp $3 "start" lbl_start |
|||
StrCmp $3 "stop" lbl_stop |
|||
StrCmp $3 "pause" lbl_pause |
|||
StrCmp $3 "continue" lbl_continue |
|||
StrCmp $3 "installed" lbl_installed |
|||
StrCmp $3 "running" lbl_running |
|||
StrCmp $3 "status" lbl_status |
|||
StrCmp $3 "processid" lbl_processid |
|||
Goto lbl_done |
|||
|
|||
; create service |
|||
lbl_create: |
|||
Push $R1 ;depend |
|||
Push $R2 ;user |
|||
Push $R3 ;password |
|||
Push $R4 ;servicetype/interact |
|||
Push $R5 ;starttype/autostart |
|||
Push $R6 ;path |
|||
Push $R7 ;display |
|||
Push $R8 ;description |
|||
|
|||
!insertmacro CALL_GETPARAM $R1 "depend" "n" "lbl_depend" |
|||
StrCpy $R1 't "$R1"' |
|||
lbl_depend: |
|||
StrCmp $R1 "n" 0 lbl_machine ;old name of depend param |
|||
!insertmacro CALL_GETPARAM $R1 "machine" "n" "lbl_machine" |
|||
StrCpy $R1 't "$R1"' |
|||
lbl_machine: |
|||
|
|||
!insertmacro CALL_GETPARAM $R2 "user" "n" "lbl_user" |
|||
StrCpy $R2 't "$R2"' |
|||
lbl_user: |
|||
|
|||
!insertmacro CALL_GETPARAM $R3 "password" "n" "lbl_password" |
|||
StrCpy $R3 't "$R3"' |
|||
lbl_password: |
|||
|
|||
!insertmacro CALL_GETPARAM $R4 "interact" "${SERVICE_WIN32_OWN_PROCESS}" "lbl_interact" |
|||
StrCpy $6 ${SERVICE_WIN32_OWN_PROCESS} |
|||
IntCmp $R4 0 +2 |
|||
IntOp $6 $6 | ${SERVICE_INTERACTIVE_PROCESS} |
|||
StrCpy $R4 $6 |
|||
lbl_interact: |
|||
|
|||
!insertmacro CALL_GETPARAM $R4 "servicetype" "$R4" "lbl_servicetype" |
|||
lbl_servicetype: |
|||
|
|||
!insertmacro CALL_GETPARAM $R5 "autostart" "${SERVICE_DEMAND_START}" "lbl_autostart" |
|||
StrCpy $6 ${SERVICE_DEMAND_START} |
|||
IntCmp $R5 0 +2 |
|||
StrCpy $6 ${SERVICE_AUTO_START} |
|||
StrCpy $R5 $6 |
|||
lbl_autostart: |
|||
|
|||
!insertmacro CALL_GETPARAM $R5 "starttype" "$R5" "lbl_starttype" |
|||
lbl_starttype: |
|||
|
|||
!insertmacro CALL_GETPARAM $R6 "path" "n" "lbl_path" |
|||
lbl_path: |
|||
|
|||
!insertmacro CALL_GETPARAM $R7 "display" "$2" "lbl_display" |
|||
lbl_display: |
|||
|
|||
!insertmacro CALL_GETPARAM $R8 "description" "$2" "lbl_description" |
|||
lbl_description: |
|||
|
|||
System::Call 'advapi32::CreateService${APITAG}(i r4, t r2, t R7, i ${SERVICE_ALL_ACCESS}, \ |
|||
i R4, i R5, i 0, t R6, n, n, $R1, $R2, $R3) i.r6' |
|||
|
|||
; write description of service (SERVICE_CONFIG_DESCRIPTION) |
|||
System::Call 'advapi32::ChangeServiceConfig2${APITAG}(ir6,i1,*t "$R8")i.R7' |
|||
strcmp $R7 "error" 0 lbl_descriptioncomplete |
|||
WriteRegStr HKLM "SYSTEM\CurrentControlSet\Services\$2" "Description" $R8 |
|||
lbl_descriptioncomplete: |
|||
|
|||
Pop $R8 |
|||
Pop $R7 |
|||
Pop $R6 |
|||
Pop $R5 |
|||
Pop $R4 |
|||
Pop $R3 |
|||
Pop $R2 |
|||
Pop $R1 |
|||
StrCmp $6 0 lbl_done lbl_good |
|||
|
|||
; delete service |
|||
lbl_delete: |
|||
System::Call 'advapi32::DeleteService(i r5) i.r6' |
|||
StrCmp $6 0 lbl_done lbl_good |
|||
|
|||
; start service |
|||
lbl_start: |
|||
System::Call 'advapi32::StartService${APITAG}(i r5, i 0, i 0) i.r6' |
|||
StrCmp $6 0 lbl_done lbl_good |
|||
|
|||
; stop service |
|||
lbl_stop: |
|||
Push $R1 |
|||
System::Call '*(i,i,i,i,i,i,i) i.R1' |
|||
System::Call 'advapi32::ControlService(i r5, i ${SERVICE_CONTROL_STOP}, i $R1) i' |
|||
System::Free $R1 |
|||
Pop $R1 |
|||
StrCmp $6 0 lbl_done lbl_good |
|||
|
|||
; pause service |
|||
lbl_pause: |
|||
Push $R1 |
|||
System::Call '*(i,i,i,i,i,i,i) i.R1' |
|||
System::Call 'advapi32::ControlService(i r5, i ${SERVICE_CONTROL_PAUSE}, i $R1) i' |
|||
System::Free $R1 |
|||
Pop $R1 |
|||
StrCmp $6 0 lbl_done lbl_good |
|||
|
|||
; continue service |
|||
lbl_continue: |
|||
Push $R1 |
|||
System::Call '*(i,i,i,i,i,i,i) i.R1' |
|||
System::Call 'advapi32::ControlService(i r5, i ${SERVICE_CONTROL_CONTINUE}, i $R1) i' |
|||
System::Free $R1 |
|||
Pop $R1 |
|||
StrCmp $6 0 lbl_done lbl_good |
|||
|
|||
; is installed |
|||
lbl_installed: |
|||
!insertmacro CALL_GETPARAM $7 "action" "" "lbl_good" |
|||
StrCpy $3 $7 |
|||
Goto lbl_select |
|||
|
|||
; is service running |
|||
lbl_running: |
|||
Push $R1 |
|||
System::Call '*(i,i,i,i,i,i,i) i.R1' |
|||
System::Call 'advapi32::QueryServiceStatus(i r5, i $R1) i' |
|||
System::Call '*$R1(i, i.r6)' |
|||
System::Free $R1 |
|||
Pop $R1 |
|||
IntFmt $6 "0x%X" $6 |
|||
StrCmp $6 ${SERVICE_RUNNING} 0 lbl_done |
|||
!insertmacro CALL_GETPARAM $7 "action" "" "lbl_good" |
|||
StrCpy $3 $7 |
|||
Goto lbl_select |
|||
|
|||
lbl_status: |
|||
Push $R1 |
|||
System::Call '*(i,i,i,i,i,i,i) i.R1' |
|||
System::Call 'advapi32::QueryServiceStatus(i r5, i $R1) i' |
|||
System::Call '*$R1(i, i .r6)' |
|||
System::Free $R1 |
|||
Pop $R1 |
|||
IntFmt $6 "0x%X" $6 |
|||
StrCpy $0 "running" |
|||
IntCmp $6 ${SERVICE_RUNNING} lbl_done |
|||
StrCpy $0 "stopped" |
|||
IntCmp $6 ${SERVICE_STOPPED} lbl_done |
|||
StrCpy $0 "start_pending" |
|||
IntCmp $6 ${SERVICE_START_PENDING} lbl_done |
|||
StrCpy $0 "stop_pending" |
|||
IntCmp $6 ${SERVICE_STOP_PENDING} lbl_done |
|||
StrCpy $0 "running" |
|||
IntCmp $6 ${SERVICE_RUNNING} lbl_done |
|||
StrCpy $0 "continue_pending" |
|||
IntCmp $6 ${SERVICE_CONTINUE_PENDING} lbl_done |
|||
StrCpy $0 "pause_pending" |
|||
IntCmp $6 ${SERVICE_PAUSE_PENDING} lbl_done |
|||
StrCpy $0 "paused" |
|||
IntCmp $6 ${SERVICE_PAUSED} lbl_done |
|||
StrCpy $0 "unknown" |
|||
Goto lbl_done |
|||
|
|||
lbl_processid: |
|||
Push $R1 |
|||
Push $R2 |
|||
System::Call '*(i,i,i,i,i,i,i,i,i) i.R1' |
|||
System::Call '*(i 0) i.R2' |
|||
System::Call "advapi32::QueryServiceStatusEx(i r5, i ${SC_STATUS_PROCESS_INFO}, i $R1, i 36, i $R2) i" |
|||
System::Call "*$R1(i,i,i,i,i,i,i, i .r0)" |
|||
System::Free $R2 |
|||
System::Free $R1 |
|||
Pop $R2 |
|||
Pop $R1 |
|||
Goto lbl_done |
|||
|
|||
lbl_good: |
|||
StrCpy $0 "true" |
|||
lbl_done: |
|||
IntCmp $5 0 +2 |
|||
System::Call 'advapi32::CloseServiceHandle(i r5) n' |
|||
IntCmp $4 0 +2 |
|||
System::Call 'advapi32::CloseServiceHandle(i r4) n' |
|||
Pop $4 |
|||
Pop $3 |
|||
Pop $2 |
|||
Pop $1 |
|||
Exch 3 |
|||
Pop $5 |
|||
Pop $7 |
|||
Pop $6 |
|||
Exch $0 |
|||
!macroend |
|||
|
|||
Function Service |
|||
!insertmacro FUNC_SERVICE "" |
|||
FunctionEnd |
|||
|
|||
Function GetParam |
|||
!insertmacro FUNC_GETPARAM |
|||
FunctionEnd |
|||
|
|||
!undef APITAG |
|||
!endif |
Binary file not shown.
Binary file not shown.
Loading…
Reference in new issue