Python Windows 服务问题 - 使用调试参数时有效,但作为服务启动时无效?

发布于 2024-08-11 16:19:09 字数 11663 浏览 5 评论 0原文

希望这里有人可以阐明我的问题:D

我一直在用 python 创建一个 Windows XP 服务,旨在监视/修复选定的 Windows/应用程序/服务设置,atm 我一直专注于默认的 DCOM 设置。

这个想法是在另一个注册表项中备份我们的默认配置以供参考。我希望该服务每 30 分钟(目前每 30 秒进行一次测试)从注册表查询当前 Windows 默认 DCOM 设置,并将结果与​​默认配置进行比较。如果发现差异,该服务将使用自定义配置设置替换当前的 Windows 设置。

我已经创建/测试了我的类来处理注册表检查/修复,到目前为止它运行完美......直到我将其编译为 exe 并将其作为服务运行。

服务本身启动得很好,并且似乎按照定义每 30 秒循环一次,但处理注册表检查/修复的模块似乎没有按指定运行。

我创建了一个日志文件,并能够获得以下错误:

Traceback(最近一次调用最后一次):
RepairDCOM 中的文件“DCOMMon.pyc”,第 52 行
文件“DCOMMon.pyc”,第 97 行,位于 GetDefaultDCOM
文件“pywmi.pyc”,第 396 行,调用
文件“pywmi.pyc”,第 189 行,handle_com_error
x_wmi:-0x7ffdfff7 - 发生异常。
错误:SWbemObjectEx
-0x7ffbfe10 -

当我停止服务并手动运行 exe 并指定调试参数:DCOMMon.exe debug 时,服务启动并运行良好,按预期执行所有任务。我能看到的唯一区别是该服务以 SYSTEM 用户而不是登录用户的身份启动进程,这让我相信(只是在这里猜测)这可能是 SYSTEM 用户缺少某种权限/策略?我已经测试过以另一个用户身份运行该服务,但也没有什么区别。

其他想法是将 wmi 服务添加到我的服务的依赖项中,但说实话,我不知道那会做什么:P 这是我第一次尝试在 python 中创建 Windows 服务,而不使用 srvany.exe 之类的东西。

我昨晚和今天花了大部分时间尝试谷歌搜索并找到一些有关 py2exe 和 wmi 兼容性的信息,但到目前为止我发现的建议并没有帮助解决上述问题。

任何建议将不胜感激。

PS:不要因为糟糕的日志记录而恨我,我从不同的脚本剪切/粘贴了我的记录器,但我没有做出适当的更改,它可能会使每行加倍:P。日志文件可以在这里找到:“%WINDIR%\system32\DCOMMon.log”

更新

我尝试将此项目拆分为两个 exe 文件,而不是一个。让服务对另一个 exe 进行外部调用以运行 wmi 注册表部分。同样,当使用 debug 参数运行时,它工作得很好,但是当我将它作为服务启动时,它会记录相同的错误消息。越来越多的情况开始看起来像是权限问题而不是程序问题:(

更新

DCOMMon.py - 需要 pywin32、wmi(重命名为 pywmi)、

# DCOMMon.py


import win32api, win32service, win32serviceutil, win32event, win32evtlogutil, win32traceutil
import logging, logging.handlers, os, re, sys, thread, time, traceback, pywmi # pywmi == wmi module renamed as suggested in online post
import _winreg as reg


DCOM_DEFAULT_CONFIGURATION      = ["EnableDCOM", "EnableRemoteConnect", "LegacyAuthenticationLevel", "LegacyImpersonationLevel", "DefaultAccessPermission",
                                   "DefaultLaunchPermission", "MachineAccessRestriction", "MachineLaunchRestriction"]

DCOM_DEFAULT_ACCESS_PERMISSION  = [1, 0, 4, 128, 92, 0, 0, 0, 108, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 2, 0, 72, 0, 3, 0, 0, 0, 0, 0, 24, 0, 7, 0, 0, 0, 1, 2,
                                   0, 0, 0, 0, 0, 5, 32, 0, 0, 0, 32, 2, 0, 0, 0, 0, 20, 0, 7, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 5, 7, 0, 0, 0, 0, 0, 20, 0, 7,
                                   0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 5, 32, 0, 0, 0, 32, 2, 0, 0, 1, 2, 0, 0, 0, 0, 0, 5, 32,
                                   0, 0, 0, 32, 2, 0, 0]

DCOM_DEFAULT_LAUNCH_PERMISSION  = [1, 0, 4, 128, 132, 0, 0, 0, 148, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 2, 0, 112, 0, 5, 0, 0, 0, 0, 0, 24, 0, 31, 0, 0, 0, 1,
                                   2, 0, 0, 0, 0, 0, 5, 32, 0, 0, 0, 32, 2, 0, 0, 0, 0, 20, 0, 31, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 5, 7, 0, 0, 0, 0, 0, 20, 0,
                                   31, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 20, 0, 31, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 5, 4, 0, 0, 0, 0, 0, 20, 0,
                                   31, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 5, 18, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 5, 32, 0, 0, 0, 32, 2, 0, 0, 1, 2, 0, 0, 0, 0, 0, 5,
                                   32, 0, 0, 0, 32, 2, 0, 0]

DCOM_MACHINE_ACCESS_RESTRICTION = [1, 0, 4, 128, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 2, 0, 48, 0, 2, 0, 0, 0, 0, 0, 20, 0, 3, 0, 0, 0, 1, 1,
                                   0, 0, 0, 0, 0, 5, 7, 0, 0, 0, 0, 0, 20, 0, 7, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 5, 32, 0,
                                   0, 0, 32, 2, 0, 0, 1, 2, 0, 0, 0, 0, 0, 5, 32, 0, 0, 0, 32, 2, 0, 0]

DCOM_MACHINE_LAUNCH_RESTRICTION = [1, 0, 4, 128, 72, 0, 0, 0, 88, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 2, 0, 52, 0, 2, 0, 0, 0, 0, 0, 24, 0, 31, 0, 0, 0, 1,
                                   2, 0, 0, 0, 0, 0, 5, 32, 0, 0, 0, 32, 2, 0, 0, 0, 0, 20, 0, 31, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 2, 0, 0,
                                   0, 0, 0, 5, 32, 0, 0, 0, 32, 2, 0, 0, 1, 2, 0, 0, 0, 0, 0, 5, 32, 0, 0, 0, 32, 2, 0, 0]

COMPUTER  = os.environ["COMPUTERNAME"]
REGISTRY  = pywmi.WMI(COMPUTER, namespace="root/default").StdRegProv
LOGFILE   = os.getcwd() + "\\DCOMMon.log"


def Logger(title, filename):
    logger = logging.getLogger(title)
    logger.setLevel(logging.DEBUG)
    handler = logging.handlers.RotatingFileHandler(filename, maxBytes=0, backupCount=0)
    handler.setLevel(logging.DEBUG)
    formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
    handler.setFormatter(formatter)
    logger.addHandler(handler)
    return logger


def LogIt(filename=LOGFILE):
    #try:
    #    if os.path.exists(filename):
    #        os.remove(filename)
    #except:
    #    pass
    log = Logger("DCOMMon", filename)
    tb  = str(traceback.format_exc()).split("\n")
    log.error("")
    for i, a in enumerate(tb):
        if a.strip() != "":
            log.error(a)

class Monitor:

    def RepairDCOM(self):
        try:
            repaired = {}
            dict1    = self.GetDefaultDCOM()
            dict2    = self.GetCurrentDCOM()
            compared = self.CompareDCOM(dict1, dict2)

            for dobj in DCOM_DEFAULT_CONFIGURATION:
                try:
                    compared[dobj]
                    if dobj == "LegacyAuthenticationLevel" or dobj == "LegacyImpersonationLevel":
                        REGISTRY.SetDWORDValue(hDefKey=reg.HKEY_LOCAL_MACHINE, sSubKeyName="SOFTWARE\\Microsoft\\Ole", sValueName=dobj, uValue=dict1[dobj])
                    elif dobj == "DefaultAccessPermission" or dobj == "DefaultLaunchPermission" or \
                         dobj == "MachineAccessRestriction" or dobj == "MachineLaunchRestriction":
                        REGISTRY.SetBinaryValue(hDefKey=reg.HKEY_LOCAL_MACHINE, sSubKeyName="SOFTWARE\\Microsoft\\Ole", sValueName=dobj, uValue=dict1[dobj])
                    elif dobj == "EnableDCOM" or dobj == "EnableRemoteConnect":
                        REGISTRY.SetStringValue(hDefKey=reg.HKEY_LOCAL_MACHINE, sSubKeyName="SOFTWARE\\Microsoft\\Ole", sValueName=dobj, sValue=dict1[dobj])
                except KeyError:
                    pass
        except:
            LogIt(LOGFILE)

    def CompareDCOM(self, dict1, dict2):
        compare = {}
        for (key, value) in dict2.iteritems():
            try:
                if dict1[key] != value:
                    compare[key] = value
            except KeyError:
                compare[key] = value
        return compare

    def GetCurrentDCOM(self):
        current = {}
        for name in REGISTRY.EnumValues(hDefKey=reg.HKEY_LOCAL_MACHINE, sSubKeyName="SOFTWARE\\Microsoft\\Ole")[1]:
            value = REGISTRY.GetStringValue(hDefKey=reg.HKEY_LOCAL_MACHINE, sSubKeyName="SOFTWARE\\Microsoft\\Ole", sValueName=str(name))[1]
            if value:
                current[str(name)] = str(value)
            else:
                value = REGISTRY.GetDWORDValue(hDefKey=reg.HKEY_LOCAL_MACHINE, sSubKeyName="SOFTWARE\\Microsoft\\Ole", sValueName=str(name))[1]
                if not value:
                    value = REGISTRY.GetBinaryValue(hDefKey=reg.HKEY_LOCAL_MACHINE, sSubKeyName="SOFTWARE\\Microsoft\\Ole", sValueName=str(name))[1]
            current[str(name)] = value
        return current

    def GetDefaultDCOM(self):
        default = {}
        # Get Default DCOM Settings
        for name in REGISTRY.EnumValues(hDefKey=reg.HKEY_CURRENT_USER, sSubKeyName="Software\\DCOMMon")[1]:
            value = REGISTRY.GetStringValue(hDefKey=reg.HKEY_CURRENT_USER, sSubKeyName="Software\\DCOMMon", sValueName=str(name))[1]
            if value:
                default[str(name)] = str(value)
            else:
                value = REGISTRY.GetDWORDValue(hDefKey=reg.HKEY_CURRENT_USER, sSubKeyName="Software\\DCOMMon", sValueName=str(name))[1]
                if not value:
                    value = REGISTRY.GetBinaryValue(hDefKey=reg.HKEY_CURRENT_USER, sSubKeyName="Software\\DCOMMon", sValueName=str(name))[1]
            default[str(name)] = value
        return default

class DCOMMon(win32serviceutil.ServiceFramework):
    _svc_name_         = "DCOMMon"
    _svc_display_name_ = "DCOM Monitoring Service"
    _svc_description_  = "DCOM Monitoring Service"
    _svc_deps_         = ["EventLog"]

    def __init__(self, args):
        win32serviceutil.ServiceFramework.__init__(self, args)
        self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
        self.isAlive   = True

    def SvcDoRun(self):
        import servicemanager
        servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE, servicemanager.PYS_SERVICE_STARTED,
                              (self._svc_name_, ': DCOM Monitoring Service - Service Started'))
        self.timeout=30000  # In milliseconds
        while self.isAlive:
            rc = win32event.WaitForSingleObject(self.hWaitStop, self.timeout)
            if rc == win32event.WAIT_OBJECT_0:
                 break
            else:
                servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE, servicemanager.PYS_SERVICE_STARTED,
                                      (self._svc_name_, ': DCOM Monitoring Service - Examining DCOM Configuration'))
                Monitor().RepairDCOM()
        servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE, servicemanager.PYS_SERVICE_STOPPED,
                              (self._svc_name_, ': DCOM Monitoring Service - Service Stopped'))
        return

    def SvcStop(self):
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        win32event.SetEvent(self.hWaitStop)
        LOG.close()
        self.isAlive = False
        return

#def ctrlHandler(ctrlType):
#    return True

if __name__ == '__main__':
#    win32api.SetConsoleCtrlHandler(ctrlHandler, True)
    #print Monitor().RepairDCOM()
    win32serviceutil.HandleCommandLine(DCOMMon)

DCOMMon_setup.py - 需要 py2exe(可自行执行,不需要 py2exe arg)

# DCOMMon_setup.py (self executable, no need for py2exe arg)

# Usage:
# DCOMMon.exe install
# DCOMMon.exe start
# DCOMMon.exe stop
# DCOMMon.exe remove
# DCOMMon.exe debug

# you can see output of this program running python site-packages\win32\lib\win32traceutil



try:
    # (snippet I found somewhere, searching something??)
    # if this doesn't work, try import modulefinder
    import py2exe.mf as modulefinder
    import win32com, sys
    for p in win32com.__path__[1:]:
        modulefinder.AddPackagePath("win32com", p)
    for extra in ["win32com.shell"]: #,"win32com.mapi"
        __import__(extra)
        m = sys.modules[extra]
        for p in m.__path__[1:]:
            modulefinder.AddPackagePath(extra, p)
except ImportError:
    print "NOT FOUND"


from distutils.core import setup
import py2exe, sys

if len(sys.argv) == 1:
    sys.argv.append("py2exe")
    #sys.argv.append("-q")

class Target:
    def __init__(self, **kw):
        self.__dict__.update(kw)
        # for the versioninfo resources
        self.version      = "1.0.0.1"
        self.language     = "English (Canada)"
        self.company_name = "Whoever"
        self.copyright    = "Nobody"
        self.name         = "Nobody Home"


myservice = Target(
    description = 'DCOM Monitoring Service',
    modules = ['DCOMMon'],
    cmdline_style='pywin32'
    #dest_base = 'DCOMMon'
)

setup(
    options = {"py2exe": {"compressed": 1, "bundle_files": 1, "ascii": 1, "packages": ["encodings"]} },   
    console=["DCOMMon.py"],
    zipfile = None,
    service=[myservice]
) 

hopefully someone here can shed some light on my issue :D

I've been creating a Windows XP service in python that is designed to monitor/repair selected Windows/Application/Service settings, atm I have been focusing on default DCOM settings.

The idea is to backup our default configuration within another registry key for reference. Every 30 minutes (currently every 30 seconds for testing) I would like the service to query the current windows default DCOM settings from the registry and compare the results to the default configuration. If discrepancies are found, the service will replace the current windows settings with the custom configuration settings.

I have already created/tested my class to handle the registry checking/repairing and so far it runs flawlessly.. Until I compile it to an exe and run it as a service.

The service itself starts up just fine and it seems to loop every 30 seconds as defined, but my module to handle the registry checking/repairing does not seem to get run as specified.

I created a log file and was able to obtain the following error:

Traceback (most recent call last):
File "DCOMMon.pyc", line 52, in RepairDCOM
File "DCOMMon.pyc", line 97, in GetDefaultDCOM
File "pywmi.pyc", line 396, in call
File "pywmi.pyc", line 189, in handle_com_error
x_wmi: -0x7ffdfff7 - Exception occurred.
Error in: SWbemObjectEx
-0x7ffbfe10 -

When I stop the service and run the exe manually, specifying the debug argument: DCOMMon.exe debug, the service starts up and runs just fine, performing all tasks as expected. The only differences that I can see is that the service starts the process as the SYSTEM user instead of the logged on user which leads me to believe (just guessing here) that it might be some sort of missed permission/policy for the SYSTEM user? I have tested running the service as another user but there was no difference there either.

Other thoughts were to add the wmi service to the dependencies of my service but truthfully I have no idea what that would do :P This is the first time I've attempted to create a windows service in python, without using something like srvany.exe.

I have spent the better part of last night and today trying to google around and find some information regarding py2exe and wmi compatibility but so far the suggestions I have found have not helped solve the above issue.

Any suggestions would be appreciated.

PS: Don't hate me for the poor logging, I cut/pasted my logger from a different scripts and I have not made the appropriate changes, it might double up each line :P. The log file can be found here: "%WINDIR%\system32\DCOMMon.log"

UPDATE

I have tried to split this project up into two exe files instead of one. Let the service make and external call to the other exe to run the wmi registry portion. Again, when running with the debug arg it works just fine, but when I start it as a service it logs the same error message. More and more this is starting to look like a permission issue an not a program issue :(

UPDATE

DCOMMon.py - Requires pywin32, wmi (renamed to pywmi),

# DCOMMon.py


import win32api, win32service, win32serviceutil, win32event, win32evtlogutil, win32traceutil
import logging, logging.handlers, os, re, sys, thread, time, traceback, pywmi # pywmi == wmi module renamed as suggested in online post
import _winreg as reg


DCOM_DEFAULT_CONFIGURATION      = ["EnableDCOM", "EnableRemoteConnect", "LegacyAuthenticationLevel", "LegacyImpersonationLevel", "DefaultAccessPermission",
                                   "DefaultLaunchPermission", "MachineAccessRestriction", "MachineLaunchRestriction"]

DCOM_DEFAULT_ACCESS_PERMISSION  = [1, 0, 4, 128, 92, 0, 0, 0, 108, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 2, 0, 72, 0, 3, 0, 0, 0, 0, 0, 24, 0, 7, 0, 0, 0, 1, 2,
                                   0, 0, 0, 0, 0, 5, 32, 0, 0, 0, 32, 2, 0, 0, 0, 0, 20, 0, 7, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 5, 7, 0, 0, 0, 0, 0, 20, 0, 7,
                                   0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 5, 32, 0, 0, 0, 32, 2, 0, 0, 1, 2, 0, 0, 0, 0, 0, 5, 32,
                                   0, 0, 0, 32, 2, 0, 0]

DCOM_DEFAULT_LAUNCH_PERMISSION  = [1, 0, 4, 128, 132, 0, 0, 0, 148, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 2, 0, 112, 0, 5, 0, 0, 0, 0, 0, 24, 0, 31, 0, 0, 0, 1,
                                   2, 0, 0, 0, 0, 0, 5, 32, 0, 0, 0, 32, 2, 0, 0, 0, 0, 20, 0, 31, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 5, 7, 0, 0, 0, 0, 0, 20, 0,
                                   31, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 20, 0, 31, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 5, 4, 0, 0, 0, 0, 0, 20, 0,
                                   31, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 5, 18, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 5, 32, 0, 0, 0, 32, 2, 0, 0, 1, 2, 0, 0, 0, 0, 0, 5,
                                   32, 0, 0, 0, 32, 2, 0, 0]

DCOM_MACHINE_ACCESS_RESTRICTION = [1, 0, 4, 128, 68, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 2, 0, 48, 0, 2, 0, 0, 0, 0, 0, 20, 0, 3, 0, 0, 0, 1, 1,
                                   0, 0, 0, 0, 0, 5, 7, 0, 0, 0, 0, 0, 20, 0, 7, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 5, 32, 0,
                                   0, 0, 32, 2, 0, 0, 1, 2, 0, 0, 0, 0, 0, 5, 32, 0, 0, 0, 32, 2, 0, 0]

DCOM_MACHINE_LAUNCH_RESTRICTION = [1, 0, 4, 128, 72, 0, 0, 0, 88, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 2, 0, 52, 0, 2, 0, 0, 0, 0, 0, 24, 0, 31, 0, 0, 0, 1,
                                   2, 0, 0, 0, 0, 0, 5, 32, 0, 0, 0, 32, 2, 0, 0, 0, 0, 20, 0, 31, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 2, 0, 0,
                                   0, 0, 0, 5, 32, 0, 0, 0, 32, 2, 0, 0, 1, 2, 0, 0, 0, 0, 0, 5, 32, 0, 0, 0, 32, 2, 0, 0]

COMPUTER  = os.environ["COMPUTERNAME"]
REGISTRY  = pywmi.WMI(COMPUTER, namespace="root/default").StdRegProv
LOGFILE   = os.getcwd() + "\\DCOMMon.log"


def Logger(title, filename):
    logger = logging.getLogger(title)
    logger.setLevel(logging.DEBUG)
    handler = logging.handlers.RotatingFileHandler(filename, maxBytes=0, backupCount=0)
    handler.setLevel(logging.DEBUG)
    formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
    handler.setFormatter(formatter)
    logger.addHandler(handler)
    return logger


def LogIt(filename=LOGFILE):
    #try:
    #    if os.path.exists(filename):
    #        os.remove(filename)
    #except:
    #    pass
    log = Logger("DCOMMon", filename)
    tb  = str(traceback.format_exc()).split("\n")
    log.error("")
    for i, a in enumerate(tb):
        if a.strip() != "":
            log.error(a)

class Monitor:

    def RepairDCOM(self):
        try:
            repaired = {}
            dict1    = self.GetDefaultDCOM()
            dict2    = self.GetCurrentDCOM()
            compared = self.CompareDCOM(dict1, dict2)

            for dobj in DCOM_DEFAULT_CONFIGURATION:
                try:
                    compared[dobj]
                    if dobj == "LegacyAuthenticationLevel" or dobj == "LegacyImpersonationLevel":
                        REGISTRY.SetDWORDValue(hDefKey=reg.HKEY_LOCAL_MACHINE, sSubKeyName="SOFTWARE\\Microsoft\\Ole", sValueName=dobj, uValue=dict1[dobj])
                    elif dobj == "DefaultAccessPermission" or dobj == "DefaultLaunchPermission" or \
                         dobj == "MachineAccessRestriction" or dobj == "MachineLaunchRestriction":
                        REGISTRY.SetBinaryValue(hDefKey=reg.HKEY_LOCAL_MACHINE, sSubKeyName="SOFTWARE\\Microsoft\\Ole", sValueName=dobj, uValue=dict1[dobj])
                    elif dobj == "EnableDCOM" or dobj == "EnableRemoteConnect":
                        REGISTRY.SetStringValue(hDefKey=reg.HKEY_LOCAL_MACHINE, sSubKeyName="SOFTWARE\\Microsoft\\Ole", sValueName=dobj, sValue=dict1[dobj])
                except KeyError:
                    pass
        except:
            LogIt(LOGFILE)

    def CompareDCOM(self, dict1, dict2):
        compare = {}
        for (key, value) in dict2.iteritems():
            try:
                if dict1[key] != value:
                    compare[key] = value
            except KeyError:
                compare[key] = value
        return compare

    def GetCurrentDCOM(self):
        current = {}
        for name in REGISTRY.EnumValues(hDefKey=reg.HKEY_LOCAL_MACHINE, sSubKeyName="SOFTWARE\\Microsoft\\Ole")[1]:
            value = REGISTRY.GetStringValue(hDefKey=reg.HKEY_LOCAL_MACHINE, sSubKeyName="SOFTWARE\\Microsoft\\Ole", sValueName=str(name))[1]
            if value:
                current[str(name)] = str(value)
            else:
                value = REGISTRY.GetDWORDValue(hDefKey=reg.HKEY_LOCAL_MACHINE, sSubKeyName="SOFTWARE\\Microsoft\\Ole", sValueName=str(name))[1]
                if not value:
                    value = REGISTRY.GetBinaryValue(hDefKey=reg.HKEY_LOCAL_MACHINE, sSubKeyName="SOFTWARE\\Microsoft\\Ole", sValueName=str(name))[1]
            current[str(name)] = value
        return current

    def GetDefaultDCOM(self):
        default = {}
        # Get Default DCOM Settings
        for name in REGISTRY.EnumValues(hDefKey=reg.HKEY_CURRENT_USER, sSubKeyName="Software\\DCOMMon")[1]:
            value = REGISTRY.GetStringValue(hDefKey=reg.HKEY_CURRENT_USER, sSubKeyName="Software\\DCOMMon", sValueName=str(name))[1]
            if value:
                default[str(name)] = str(value)
            else:
                value = REGISTRY.GetDWORDValue(hDefKey=reg.HKEY_CURRENT_USER, sSubKeyName="Software\\DCOMMon", sValueName=str(name))[1]
                if not value:
                    value = REGISTRY.GetBinaryValue(hDefKey=reg.HKEY_CURRENT_USER, sSubKeyName="Software\\DCOMMon", sValueName=str(name))[1]
            default[str(name)] = value
        return default

class DCOMMon(win32serviceutil.ServiceFramework):
    _svc_name_         = "DCOMMon"
    _svc_display_name_ = "DCOM Monitoring Service"
    _svc_description_  = "DCOM Monitoring Service"
    _svc_deps_         = ["EventLog"]

    def __init__(self, args):
        win32serviceutil.ServiceFramework.__init__(self, args)
        self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
        self.isAlive   = True

    def SvcDoRun(self):
        import servicemanager
        servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE, servicemanager.PYS_SERVICE_STARTED,
                              (self._svc_name_, ': DCOM Monitoring Service - Service Started'))
        self.timeout=30000  # In milliseconds
        while self.isAlive:
            rc = win32event.WaitForSingleObject(self.hWaitStop, self.timeout)
            if rc == win32event.WAIT_OBJECT_0:
                 break
            else:
                servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE, servicemanager.PYS_SERVICE_STARTED,
                                      (self._svc_name_, ': DCOM Monitoring Service - Examining DCOM Configuration'))
                Monitor().RepairDCOM()
        servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE, servicemanager.PYS_SERVICE_STOPPED,
                              (self._svc_name_, ': DCOM Monitoring Service - Service Stopped'))
        return

    def SvcStop(self):
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        win32event.SetEvent(self.hWaitStop)
        LOG.close()
        self.isAlive = False
        return

#def ctrlHandler(ctrlType):
#    return True

if __name__ == '__main__':
#    win32api.SetConsoleCtrlHandler(ctrlHandler, True)
    #print Monitor().RepairDCOM()
    win32serviceutil.HandleCommandLine(DCOMMon)

DCOMMon_setup.py - Requires py2exe (self executable, no need for py2exe arg)

# DCOMMon_setup.py (self executable, no need for py2exe arg)

# Usage:
# DCOMMon.exe install
# DCOMMon.exe start
# DCOMMon.exe stop
# DCOMMon.exe remove
# DCOMMon.exe debug

# you can see output of this program running python site-packages\win32\lib\win32traceutil



try:
    # (snippet I found somewhere, searching something??)
    # if this doesn't work, try import modulefinder
    import py2exe.mf as modulefinder
    import win32com, sys
    for p in win32com.__path__[1:]:
        modulefinder.AddPackagePath("win32com", p)
    for extra in ["win32com.shell"]: #,"win32com.mapi"
        __import__(extra)
        m = sys.modules[extra]
        for p in m.__path__[1:]:
            modulefinder.AddPackagePath(extra, p)
except ImportError:
    print "NOT FOUND"


from distutils.core import setup
import py2exe, sys

if len(sys.argv) == 1:
    sys.argv.append("py2exe")
    #sys.argv.append("-q")

class Target:
    def __init__(self, **kw):
        self.__dict__.update(kw)
        # for the versioninfo resources
        self.version      = "1.0.0.1"
        self.language     = "English (Canada)"
        self.company_name = "Whoever"
        self.copyright    = "Nobody"
        self.name         = "Nobody Home"


myservice = Target(
    description = 'DCOM Monitoring Service',
    modules = ['DCOMMon'],
    cmdline_style='pywin32'
    #dest_base = 'DCOMMon'
)

setup(
    options = {"py2exe": {"compressed": 1, "bundle_files": 1, "ascii": 1, "packages": ["encodings"]} },   
    console=["DCOMMon.py"],
    zipfile = None,
    service=[myservice]
) 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

黯然 2024-08-18 16:19:09

所以我想是时候承认我的愚蠢了...... :P

事实证明这不是 python 问题,py2exe 问题,也不是 WMI 问题。 :(

这或多或少是一个简单的权限问题。如此简单,我在一个月的大部分时间里都忽略了它。:(

经验法则,如果您想创建一个调用特定注册表项来获取的服务(在本例中) )默认配置设置....

也许...只是可能....

人们应该将默认密钥放在“HKEY_LOCAL_MACHINE”中,而不是“ HKEY_CURRENT_USER"?? :P

是的,就是这么简单...

我应该从我过去参与过的其他项目中记住这条规则。当您作为本地系统帐户运行时,简单地说,有没有“HKEY_CURRENT_USER”子项可以访问。如果您绝对必须访问特定用户的“HKEY_CURRENT_USER”子项,我猜唯一的方法就是模拟该用户。对我来说,这对于我想要完成的任务来说并不是必需的。

以下链接为我提供了唤起记忆并解决问题所需的内容:

http://msdn.microsoft.com/en-us/library/ms684190%28VS.85%29.aspx

所以长话短说,我将所有默认值迁移到 “HKEY_LOCAL_MACHINE\SOFTWARE” 子项,并且我的服务运行良好。 :D

感谢你们的帮助,但是这个问题已经解决了;)

So I guess it's time to admit my stupidity.... :P

It turns out this was not a python issue, py2exe issue, nor a WMI issue. :(

This was more or less a simple permission issue. So simple I overlooked it for the better part of a month. :(

Rule of thumb, if you want to create a service that calls to specific registry keys to obtain (in this case) default configuration settings....

maybe... JUST MAYBE....

One should place their default key within the "HKEY_LOCAL_MACHINE", instead of "HKEY_CURRENT_USER"?? :P

Yeah, it's that simple...

I should have remembered this rule from other projects I have worked on in the past. When you are running as the Local System account, simply put, there is no "HKEY_CURRENT_USER" subkey to access. If you absolutely have to access a specific user's "HKEY_CURRENT_USER" subkey, I would guess the only way would be to impersonate the user. Luckily for me this is not necessary for what I am attempting to accomplish.

The below link provided me with what I needed to jog my memory and fix the issue:

http://msdn.microsoft.com/en-us/library/ms684190%28VS.85%29.aspx

So to make a long story short, I migrated all of my default values over to "HKEY_LOCAL_MACHINE\SOFTWARE" subkey and my service is working perfectly. :D

Thanks for your help guys but this problem is solved ;)

や三分注定 2024-08-18 16:19:09

我不是这方面的专家,但这是我的两分钱的价值:

这篇文章告诉我,您可能需要以具有所需目标系统权限的身份登录。

不过,我觉得有点过分了。您是否尝试过从命令行编译脚本,同时以计算机管理员身份运行命令提示符 - 以便您可以解锁所有权限(在 Windows Vista 和 Windows 7 上,这是通过右键单击窗口中的命令提示符图标来实现的)开始菜单并单击“以管理员身份运行”)。

希望这有帮助

I am not an expert at this, but here are my two cents worth:

This article tells me that you might need to be logged in as someone with the required target system permissions.

However, I find that a little excessive. Have you tried compiling your script from the command line while running the command prompt as the administrator of the computer - so that you can unlock all permissions (on Windows Vista and Windows 7, this is achieved by right clicking on the command prompt icon in the start menu and clicking on "run as administrator").

Hope this helps

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文