Browse Source

Allow SABnzbd to be run as a Windows Service.

Implemented:
- Full service-enabled, install/update/start/stop
- Command-line parameters are stored in Service's reg-entry

To be done:
- Requires better Win logging
- Restart doesn't work from UI
- Support in installer
- Translated texts

Addresses #12 for trunk.
tags/0.6.0
shypike 16 years ago
parent
commit
c860d9f4cb
  1. 359
      main/SABnzbd.py
  2. 74
      main/package.py
  3. 1
      main/sabnzbd/__init__.py
  4. 42
      main/sabnzbd/misc.py

359
main/SABnzbd.py

@ -67,25 +67,35 @@ import sabnzbd.newsunpack
from sabnzbd.misc import get_user_shellfolders, launch_a_browser, real_path, \ from sabnzbd.misc import get_user_shellfolders, launch_a_browser, real_path, \
check_latest_version, panic_tmpl, panic_port, panic_fwall, panic, exit_sab, \ check_latest_version, panic_tmpl, panic_port, panic_fwall, panic, exit_sab, \
panic_xport, notify, split_host, convert_version, get_ext, create_https_certificates, \ panic_xport, notify, split_host, convert_version, get_ext, create_https_certificates, \
windows_variant, ip_extract windows_variant, ip_extract, set_serv_parms, get_serv_parms
import sabnzbd.scheduler as scheduler import sabnzbd.scheduler as scheduler
import sabnzbd.config as config import sabnzbd.config as config
import sabnzbd.cfg import sabnzbd.cfg
import sabnzbd.downloader as downloader import sabnzbd.downloader as downloader
from sabnzbd.codecs import unicoder
from sabnzbd.lang import T, Ta from sabnzbd.lang import T, Ta
from sabnzbd.utils import osx from sabnzbd.utils import osx
from threading import Thread from threading import Thread
LOG_FLAG = False # Global for this module, signalling loglevel change LOG_FLAG = False # Global for this module, signalling loglevel change
_first_log = True
def FORCELOG(txt):
global _first_log
if _first_log:
os.remove('d:/temp/debug.txt')
_first_log = False
ff = open('d:/temp/debug.txt', 'a+')
ff.write(txt)
ff.write('\n')
ff.close()
#------------------------------------------------------------------------------
signal.signal(signal.SIGINT, sabnzbd.sig_handler)
signal.signal(signal.SIGTERM, sabnzbd.sig_handler)
#------------------------------------------------------------------------------
try: try:
import win32api import win32api
import win32serviceutil, win32evtlogutil, win32event, win32service, pywintypes
win32api.SetConsoleCtrlHandler(sabnzbd.sig_handler, True) win32api.SetConsoleCtrlHandler(sabnzbd.sig_handler, True)
except ImportError: except ImportError:
if sabnzbd.WIN32: if sabnzbd.WIN32:
@ -641,77 +651,86 @@ def cherrypy_logging(log_path):
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
def main(): def commandline_handler(frozen=True):
global LOG_FLAG """ Split win32-service commands are true parameters
Returns:
AUTOBROWSER = None service, sab_opts, serv_opts, upload_nzbs
autorestarted = False """
service = ''
sab_opts = []
serv_inst = False
serv_opts = [os.path.normpath(os.path.abspath(sys.argv[0]))]
upload_nzbs = []
sabnzbd.MY_FULLNAME = os.path.normpath(os.path.abspath(sys.argv[0])) # Ugly hack to remove the extra "SABnzbd*" parameter the Windows binary
sabnzbd.MY_NAME = os.path.basename(sabnzbd.MY_FULLNAME) # gets when it's restarted
sabnzbd.DIR_PROG = os.path.dirname(sabnzbd.MY_FULLNAME) if len(sys.argv) > 1 and \
sabnzbd.DIR_INTERFACES = real_path(sabnzbd.DIR_PROG, DEF_INTERFACES) 'sabnzbd' in sys.argv[1].lower() and \
sabnzbd.DIR_LANGUAGE = real_path(sabnzbd.DIR_PROG, DEF_LANGUAGE) not sys.argv[1].startswith('-'):
org_dir = os.getcwd() slice = 2
else:
slice = 1
if getattr(sys, 'frozen', None) == 'macosx_app': # Prepend options from env-variable to options
# Correct path if frozen with py2app (OSX) info = os.environ.get('SABnzbd', '').split()
sabnzbd.MY_FULLNAME = sabnzbd.MY_FULLNAME.replace("/Resources/SABnzbd.py","/MacOS/SABnzbd") info.extend(sys.argv[slice:])
# Need console logging for SABnzbd.py and SABnzbd-console.exe try:
consoleLogging = (not hasattr(sys, "frozen")) or (sabnzbd.MY_NAME.lower().find('-console') > 0) opts, args = getopt.getopt(info, "phdvncw:l:s:f:t:b:2:",
['pause', 'help', 'daemon', 'nobrowser', 'clean', 'logging=',
'weblogging=', 'server=', 'templates',
'template2', 'browser=', 'config-file=', 'delay=', 'force',
'version', 'https=', 'autorestarted',
# Below Win32 Service options
'password=', 'username=', 'startup=', 'perfmonini=', 'perfmondll=',
'interactive', 'wait=',
])
except getopt.GetoptError:
print_help()
exit_sab(2)
# No console logging needed for OSX app # Check for Win32 service commands
noConsoleLoggingOSX = (sabnzbd.DIR_PROG.find('.app/Contents/Resources') > 0) if args and args[0] in ('install', 'update', 'remove', 'start', 'stop', 'restart', 'debug'):
if noConsoleLoggingOSX: service = args[0]
consoleLogging = 1 serv_opts.extend(args)
LOGLEVELS = (logging.WARNING, logging.INFO, logging.DEBUG) if not service:
# Get and remove any NZB file names
for entry in args:
if get_ext(entry) in ('.nzb', '.zip','.rar', '.nzb.gz'):
upload_nzbs.append(entry)
# Setup primary logging to prevent default console logging for opt, arg in opts:
gui_log = guiHandler(MAX_WARNINGS) if opt in ('password','username','startup','perfmonini', 'perfmondll', 'interactive', 'wait'):
gui_log.setLevel(logging.WARNING) # Service option, just collect
format_gui = '%(asctime)s\n%(levelname)s\n%(message)s' if service:
gui_log.setFormatter(logging.Formatter(format_gui)) serv_opts.append(opt)
sabnzbd.GUIHANDLER = gui_log if arg:
serv_opts.append(arg)
# Create logger else:
logger = logging.getLogger('') if opt == '-f':
logger.setLevel(logging.WARNING) arg = os.path.normpath(os.path.abspath(arg))
logger.addHandler(gui_log) sab_opts.append((opt, arg))
# Create a list of passed files to load on startup return service, sab_opts, serv_opts, upload_nzbs
# or pass to an already running instance of sabnzbd
upload_nzbs = []
for entry in sys.argv:
if get_ext(entry) in ('.nzb','.zip','.rar', '.nzb.gz'):
upload_nzbs.append(entry)
sys.argv.remove(entry)
try: def get_f_option(opts):
# Ugly hack to remove the extra "SABnzbd*" parameter the Windows binary """ Return value of the -f option """
# gets when it's restarted for opt, arg in opts:
if len(sys.argv) > 1 and \ if opt == '-f':
'sabnzbd' in sys.argv[1].lower() and \ return arg
not sys.argv[1].startswith('-'): else:
slice = 2 return None
else:
slice = 1
# Prepend options from env-variable to options
args = os.environ.get('SABnzbd', '').split()
args.extend(sys.argv[slice:])
opts, args = getopt.getopt(args, "phdvncw:l:s:f:t:b:2:", #------------------------------------------------------------------------------
['pause', 'help', 'daemon', 'nobrowser', 'clean', 'logging=', def main():
'weblogging=', 'server=', 'templates', global LOG_FLAG
'template2', 'browser=', 'config-file=', 'delay=', 'force',
'version', 'https=', 'autorestarted'])
except getopt.GetoptError:
print_help()
exit_sab(2)
AUTOBROWSER = None
autorestarted = False
sabnzbd.MY_FULLNAME = sys.argv[0]
fork = False fork = False
pause = False pause = False
inifile = None inifile = None
@ -729,21 +748,25 @@ def main():
force_web = False force_web = False
re_argv = [sys.argv[0]] re_argv = [sys.argv[0]]
for opt, arg in opts: service, sab_opts, serv_opts, upload_nzbs = commandline_handler()
if (opt in ('-d', '--daemon')):
for opt, arg in sab_opts:
if opt == '--servicecall':
sabnzbd.MY_FULLNAME = arg
elif opt in ('-d', '--daemon'):
if not sabnzbd.WIN32: if not sabnzbd.WIN32:
fork = True fork = True
AUTOBROWSER = False AUTOBROWSER = False
sabnzbd.DAEMON = True sabnzbd.DAEMON = True
consoleLogging = False consoleLogging = False
re_argv.append(opt) re_argv.append(opt)
elif opt in ('-h', '--help'):
print_help()
exit_sab(0)
elif opt in ('-f', '--config-file'): elif opt in ('-f', '--config-file'):
inifile = arg inifile = arg
re_argv.append(opt) re_argv.append(opt)
re_argv.append(arg) re_argv.append(arg)
elif opt in ('-h', '--help'):
print_help()
exit_sab(0)
elif opt in ('-t', '--templates'): elif opt in ('-t', '--templates'):
web_dir = arg web_dir = arg
elif opt in ('-2', '--template2'): elif opt in ('-2', '--template2'):
@ -760,7 +783,7 @@ def main():
elif opt in ('--autorestarted'): elif opt in ('--autorestarted'):
autorestarted = True autorestarted = True
elif opt in ('-c', '--clean'): elif opt in ('-c', '--clean'):
clean_up= True clean_up = True
elif opt in ('-w', '--weblogging'): elif opt in ('-w', '--weblogging'):
try: try:
cherrypylogging = int(arg) cherrypylogging = int(arg)
@ -782,20 +805,53 @@ def main():
exit_sab(0) exit_sab(0)
elif opt in ('-p', '--pause'): elif opt in ('-p', '--pause'):
pause = True pause = True
elif opt in ('--delay'): elif opt in ('--delay',):
# For debugging of memory leak only!! # For debugging of memory leak only!!
try: try:
delay = float(arg) delay = float(arg)
except: except:
pass pass
elif opt in ('--force'): elif opt in ('--force',):
force_web = True force_web = True
re_argv.append(opt) re_argv.append(opt)
elif opt in ('--https'): elif opt in ('--https',):
https_port = int(arg) https_port = int(arg)
re_argv.append(opt) re_argv.append(opt)
re_argv.append(arg) re_argv.append(arg)
sabnzbd.MY_FULLNAME = os.path.normpath(os.path.abspath(sabnzbd.MY_FULLNAME))
sabnzbd.MY_NAME = os.path.basename(sabnzbd.MY_FULLNAME)
sabnzbd.DIR_PROG = os.path.dirname(sabnzbd.MY_FULLNAME)
sabnzbd.DIR_INTERFACES = real_path(sabnzbd.DIR_PROG, DEF_INTERFACES)
sabnzbd.DIR_LANGUAGE = real_path(sabnzbd.DIR_PROG, DEF_LANGUAGE)
org_dir = os.getcwd()
if getattr(sys, 'frozen', None) == 'macosx_app':
# Correct path if frozen with py2app (OSX)
sabnzbd.MY_FULLNAME = sabnzbd.MY_FULLNAME.replace("/Resources/SABnzbd.py","/MacOS/SABnzbd")
# Need console logging for SABnzbd.py and SABnzbd-console.exe
consoleLogging = (not hasattr(sys, "frozen")) or (sabnzbd.MY_NAME.lower().find('-console') > 0)
# No console logging needed for OSX app
noConsoleLoggingOSX = (sabnzbd.DIR_PROG.find('.app/Contents/Resources') > 0)
if noConsoleLoggingOSX:
consoleLogging = 1
LOGLEVELS = (logging.WARNING, logging.INFO, logging.DEBUG)
# Setup primary logging to prevent default console logging
gui_log = guiHandler(MAX_WARNINGS)
gui_log.setLevel(logging.WARNING)
format_gui = '%(asctime)s\n%(levelname)s\n%(message)s'
gui_log.setFormatter(logging.Formatter(format_gui))
sabnzbd.GUIHANDLER = gui_log
# Create logger
logger = logging.getLogger('')
logger.setLevel(logging.WARNING)
logger.addHandler(gui_log)
# Detect Windows variant # Detect Windows variant
if sabnzbd.WIN32: if sabnzbd.WIN32:
vista_plus, vista64 = windows_variant() vista_plus, vista64 = windows_variant()
@ -836,12 +892,24 @@ def main():
# Determine web host address # Determine web host address
cherryhost, cherryport, browserhost, https_port = get_webhost(cherryhost, cherryport, https_port) cherryhost, cherryport, browserhost, https_port = get_webhost(cherryhost, cherryport, https_port)
enable_https = sabnzbd.cfg.ENABLE_HTTPS.get()
# When this is a daemon, just check and bail out if port in use
if sabnzbd.DAEMON:
if enable_https and https_port:
try:
cherrypy.process.servers.check_port(cherryhost, https_port)
except IOError, error:
Bail_Out(browserhost, cherryport)
try:
cherrypy.process.servers.check_port(cherryhost, cherryport)
except IOError, error:
Bail_Out(browserhost, cherryport)
# If an instance of sabnzbd(same version) is already running on this port, launch the browser # If an instance of sabnzbd(same version) is already running on this port, launch the browser
# If another program or sabnzbd version is on this port, try 10 other ports going up in a step of 5 # If another program or sabnzbd version is on this port, try 10 other ports going up in a step of 5
# If 'Port is not bound' (firewall) do not do anything (let the script further down deal with that). # If 'Port is not bound' (firewall) do not do anything (let the script further down deal with that).
## SSL ## SSL
enable_https = sabnzbd.cfg.ENABLE_HTTPS.get()
if enable_https and https_port: if enable_https and https_port:
try: try:
cherrypy.process.servers.check_port(browserhost, https_port) cherrypy.process.servers.check_port(browserhost, https_port)
@ -979,6 +1047,10 @@ def main():
# Find external programs # Find external programs
sabnzbd.newsunpack.find_programs(sabnzbd.DIR_PROG) sabnzbd.newsunpack.find_programs(sabnzbd.DIR_PROG)
if not sabnzbd.WIN_SERVICE:
signal.signal(signal.SIGINT, sabnzbd.sig_handler)
signal.signal(signal.SIGTERM, sabnzbd.sig_handler)
init_ok = sabnzbd.initialize(pause, clean_up, evalSched=True) init_ok = sabnzbd.initialize(pause, clean_up, evalSched=True)
if not init_ok: if not init_ok:
@ -1149,7 +1221,16 @@ def main():
# Have to keep this running, otherwise logging will terminate # Have to keep this running, otherwise logging will terminate
timer = 0 timer = 0
while not sabnzbd.SABSTOP: while not sabnzbd.SABSTOP:
time.sleep(3) if sabnzbd.WIN_SERVICE:
rc = win32event.WaitForMultipleObjects((sabnzbd.WIN_SERVICE.hWaitStop,
sabnzbd.WIN_SERVICE.overlapped.hEvent), 0, 3000)
if rc == win32event.WAIT_OBJECT_0:
sabnzbd.save_state()
logging.info('Leaving SABnzbd')
sabnzbd.SABSTOP = True
return
else:
time.sleep(3)
# Check for loglevel changes # Check for loglevel changes
if LOG_FLAG: if LOG_FLAG:
@ -1202,6 +1283,9 @@ def main():
pid = os.fork() pid = os.fork()
if pid == 0: if pid == 0:
os.execv(sys.executable, args) os.execv(sys.executable, args)
elif sabnzbd.WIN_SERVICE:
# Hope for the service manager to restart us
sys.exit(1)
else: else:
cherrypy.engine._do_execv() cherrypy.engine._do_execv()
@ -1218,22 +1302,126 @@ def main():
os._exit(0) os._exit(0)
##################################################################### #####################################################################
# #
# Platform specific startup code # Windows Service Support
# #
if sabnzbd.WIN32:
import servicemanager
class SABnzbd(win32serviceutil.ServiceFramework):
""" Win32 Service Handler """
_svc_name_ = 'SABnzbd'
_svc_display_name_ = 'SABnzbd Binary Newsreader'
_svc_deps_ = ["EventLog", "Tcpip"]
_svc_description_ = 'Automated downloading from Usenet. ' \
'Set to "automatic" to start the service at system startup. ' \
'You may need to login with a real user account when you need ' \
'access to network shares.'
def __init__(self, args):
win32serviceutil.ServiceFramework.__init__(self, args)
self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
self.overlapped = pywintypes.OVERLAPPED()
self.overlapped.hEvent = win32event.CreateEvent(None, 0, 0, None)
sabnzbd.WIN_SERVICE = self
def SvcDoRun(self):
msg = 'SABnzbd-service %s' % sabnzbd.__version__
self.Logger(servicemanager.PYS_SERVICE_STARTED, msg + ' has started')
sys.argv = get_serv_parms(self._svc_name_)
main()
self.Logger(servicemanager.PYS_SERVICE_STOPPED, msg + ' has stopped')
if not getattr(sys, 'frozen', None) == 'macosx_app': def SvcStop(self):
# Windows & Unix/Linux self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.hWaitStop)
if __name__ == '__main__': def Logger(self, state, msg):
main() win32evtlogutil.ReportEvent(self._svc_display_name_,
state, 0,
servicemanager.EVENTLOG_INFORMATION_TYPE,
(self._svc_name_, unicoder(msg)))
def ErrLogger(self, msg, text):
win32evtlogutil.ReportEvent(self._svc_display_name_,
servicemanager.PYS_SERVICE_STOPPED, 0,
servicemanager.EVENTLOG_ERROR_TYPE,
(self._svc_name_, unicoder(msg)),
unicoder(text))
def prep_service_parms(args):
""" Prepare parameter list for service """
else: # Must store our original path, because the Python Service launcher
# won't give it to us.
serv = [os.path.normpath(os.path.abspath(sys.argv[0]))]
# OSX # Convert the tuples to list
for arg in args:
serv.append(arg[0])
if arg[1]:
serv.append(arg[1])
# Make sure we run in daemon mode
serv.append('-d')
return serv
def HandleCommandLine(allow_service=True):
""" Handle command line for a Windows Service
Prescribed name that will be called by Py2Exe.
You MUST set 'cmdline_style':'custom' in the package.py!
Returns True when any service commands were detected.
"""
service, sab_opts, serv_opts, upload_nzbs = commandline_handler()
if service and not allow_service:
# The other frozen apps don't support Services
print "For service support, use SABnzbd-service.exe"
return True
elif service:
if service in ('install', 'update'):
# In this case check for required parameters
path = get_f_option(sab_opts)
if not path:
print 'The -f <path> parameter is required.\n' \
'Use: -f <path> %s' % service
return True
# First run the service installed, because this will
# set the service key in the Registry
win32serviceutil.HandleCommandLine(SABnzbd, argv=serv_opts)
# Add our own parameter to the Registry
sab_opts = prep_service_parms(sab_opts)
if set_serv_parms(SABnzbd._svc_name_, sab_opts):
print '\nYou may need to set additional Service parameters.\n' \
'Run services.msc from a command prompt.\n'
else:
print 'Cannot set required Registry info.'
else:
# Other service commands need no manipulation
win32serviceutil.HandleCommandLine(SABnzbd)
return bool(service)
#####################################################################
#
# Platform specific startup code
#
if __name__ == '__main__':
if sabnzbd.WIN32:
if not HandleCommandLine(allow_service=not hasattr(sys, "frozen")):
main()
elif getattr(sys, 'frozen', None) == 'macosx_app':
# OSX binary
if __name__ == '__main__':
try: try:
from PyObjCTools import AppHelper from PyObjCTools import AppHelper
from SABnzbdDelegate import SABnzbdDelegate from SABnzbdDelegate import SABnzbdDelegate
@ -1260,3 +1448,6 @@ else:
except: except:
main() main()
else:
main()

74
main/package.py

@ -201,6 +201,18 @@ def Unix2Dos(name):
exit(1) exit(1)
def rename_file(folder, old, new):
try:
oldpath = "%s/%s" % (folder, old)
newpath = "%s/%s" % (folder, new)
if os.path.exists(newpath):
os.remove(newpath)
os.rename(oldpath, newpath)
except WindowsError:
print "Cannot create %s" % newpath
exit(1)
print sys.argv[0] print sys.argv[0]
#OSX if svnversion not installed install SCPlugin and execute these commands #OSX if svnversion not installed install SCPlugin and execute these commands
@ -228,7 +240,7 @@ if len(sys.argv) < 2:
else: else:
target = sys.argv[1] target = sys.argv[1]
if target not in ('source', 'binary', 'app'): if target not in ('source', 'binary', 'installer', 'app'):
print 'Usage: package.py binary|source|app' print 'Usage: package.py binary|source|app'
exit(1) exit(1)
@ -236,8 +248,10 @@ if target not in ('source', 'binary', 'app'):
base, release = os.path.split(os.getcwd()) base, release = os.path.split(os.getcwd())
prod = 'SABnzbd-' + release prod = 'SABnzbd-' + release
Win32ServiceName = 'SABnzbd-service.exe'
Win32ConsoleName = 'SABnzbd-console.exe' Win32ConsoleName = 'SABnzbd-console.exe'
Win32WindowName = 'SABnzbd.exe' Win32WindowName = 'SABnzbd.exe'
Win32TempName = 'SABnzbd-windows.exe'
fileIns = prod + '-win32-setup.exe' fileIns = prod + '-win32-setup.exe'
fileBin = prod + '-win32-bin.zip' fileBin = prod + '-win32-bin.zip'
@ -388,7 +402,7 @@ if target == 'app':
os.system(SvnRevertApp + VERSION_FILE) os.system(SvnRevertApp + VERSION_FILE)
os.system(SvnUpdateApp) os.system(SvnUpdateApp)
elif target == 'binary': elif target in ('binary', 'installer'):
if not py2exe: if not py2exe:
print "Sorry, only works on Windows!" print "Sorry, only works on Windows!"
os.system(SvnRevert) os.system(SvnRevert)
@ -414,16 +428,13 @@ elif target == 'binary':
} }
options['zipfile'] = 'lib/sabnzbd.zip' options['zipfile'] = 'lib/sabnzbd.zip'
############################
# Generate the console-app # Generate the console-app
options['console'] = program options['console'] = program
setup(**options) setup(**options)
try: rename_file('dist', Win32WindowName, Win32ConsoleName)
if os.path.exists("dist/%s" % Win32ConsoleName):
os.remove("dist/%s" % Win32ConsoleName)
os.rename("dist/%s" % Win32WindowName, "dist/%s" % Win32ConsoleName)
except:
print "Cannot create dist/%s" % Win32ConsoleName
exit(1)
# Make sure that the root files are DOS format # Make sure that the root files are DOS format
for file in options['data_files'][0][1]: for file in options['data_files'][0][1]:
@ -431,26 +442,45 @@ elif target == 'binary':
DeleteFiles('dist/Sample-PostProc.sh') DeleteFiles('dist/Sample-PostProc.sh')
DeleteFiles('dist/PKG-INFO') DeleteFiles('dist/PKG-INFO')
# Generate the windowed-app (skip datafiles now) DeleteFiles('*.ini')
del options['console']
del options['data_files'] if sys.version_info < (2,6):
# Copy the proper OpenSSL files into the dist folder
shutil.copy2('win/openssl/libeay32.dll', 'dist/lib')
shutil.copy2('win/openssl/ssleay32.dll', 'dist/lib')
############################
# Generate the windowed-app
options['windows'] = program options['windows'] = program
del options['data_files']
del options['console']
setup(**options) setup(**options)
rename_file('dist', Win32WindowName, Win32TempName)
############################
# Generate the service-app
options['service'] = [{'modules':["SABnzbd"], 'cmdline_style':'custom'}]
del options['windows']
setup(**options)
rename_file('dist', Win32WindowName, Win32ServiceName)
# Give the Windows app its proper name
rename_file('dist', Win32TempName, Win32WindowName)
DeleteFiles('*.ini')
# Copy the proper OpenSSL files into the dist folder ############################
shutil.copy2('win/openssl/libeay32.dll', 'dist/lib') if target == 'installer':
shutil.copy2('win/openssl/ssleay32.dll', 'dist/lib')
os.system('makensis.exe /v3 /DSAB_PRODUCT=%s /DSAB_FILE=%s NSIS_Installer.nsi' % \ os.system('makensis.exe /v3 /DSAB_PRODUCT=%s /DSAB_FILE=%s NSIS_Installer.nsi' % \
(release, fileIns)) (release, fileIns))
DeleteFiles(fileBin)
os.rename('dist', prod)
os.system('zip -9 -r -X %s %s' % (fileBin, prod))
os.rename(prod, 'dist')
DeleteFiles(fileBin)
os.rename('dist', prod)
os.system('zip -9 -r -X %s %s' % (fileBin, prod))
os.rename(prod, 'dist')
os.system(SvnRevert) os.system(SvnRevert)
else: else:

1
main/sabnzbd/__init__.py

@ -112,6 +112,7 @@ WEBLOGFILE = None
LOGHANDLER = None LOGHANDLER = None
GUIHANDLER = None GUIHANDLER = None
AMBI_LOCALHOST = False AMBI_LOCALHOST = False
WIN_SERVICE = None # Instance of our Win32 Service Class
WEB_DIR = None WEB_DIR = None
WEB_DIR2 = None WEB_DIR2 = None

42
main/sabnzbd/misc.py

@ -309,6 +309,48 @@ def windows_variant():
return vista_plus, x64 return vista_plus, x64
#------------------------------------------------------------------------------
_SERVICE_KEY = 'SYSTEM\\CurrentControlSet\\services\\'
_SERVICE_PARM = 'CommandLine'
def get_serv_parms(service):
""" Get the service command line parameters from Registry """
import _winreg
value = []
try:
key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, _SERVICE_KEY + service)
for n in xrange(_winreg.QueryInfoKey(key)[1]):
name, value, val_type = _winreg.EnumValue(key, n)
if name == _SERVICE_PARM:
break
_winreg.CloseKey(key)
except WindowsError:
pass
for n in xrange(len(value)):
value[n] = latin1(value[n])
return value
def set_serv_parms(service, args):
""" Set the service command line parameters in Registry """
import _winreg
uargs = []
for arg in args:
uargs.append(unicoder(arg))
try:
key = _winreg.CreateKey(_winreg.HKEY_LOCAL_MACHINE, _SERVICE_KEY + service)
_winreg.SetValueEx(key, _SERVICE_PARM, None, _winreg.REG_MULTI_SZ, uargs)
_winreg.CloseKey(key)
except WindowsError:
return False
return True
################################################################################ ################################################################################
# Launch a browser for various purposes # Launch a browser for various purposes
# including panic messages # including panic messages

Loading…
Cancel
Save