0

うまくいけば、ここの誰かが私の問題に光を当てることができます:D

選択した Windows/アプリケーション/サービス設定を監視/修復するように設計された Python で Windows XP サービスを作成してきましたが、デフォルトの DCOM 設定に焦点を当てています。

アイデアは、参照用に別のレジストリ キー内の既定の構成をバックアップすることです。30 分ごと (現在はテストのため 30 秒ごと) に、サービスで現在の Windows の既定の DCOM 設定をレジストリからクエリし、結果を既定の構成と比較したいと考えています。不一致が見つかった場合、サービスは現在の Windows 設定をカスタム構成設定に置き換えます。

レジストリのチェック/修復を処理するクラスを既に作成/テストしており、これまでのところ問題なく実行されています.exeにコンパイルしてサービスとして実行するまで。

サービス自体は正常に起動し、定義どおりに 30 秒ごとにループしているように見えますが、レジストリのチェック/修復を処理するモジュールが指定どおりに実行されていないようです。

ログ ファイルを作成したところ、次のエラーを取得できました。

トレースバック (最新の最後の呼び出し):
ファイル "DCOMMon.pyc"、52 行目、RepairDCOM
ファイル "DCOMMon.pyc"、97 行目、GetDefaultDCOM
ファイル "pywmi.pyc"、396 行目、呼び出し
ファイル "pywmi.pyc" 内、189 行目、handle_com_error
x_wmi: -0x7ffdfff7 - 例外が発生しました。
エラー: SWbemObjectEx
-0x7ffbfe10 -

サービスを停止し、デバッグ引数DCOMMon.exe debugを指定して exe を手動で実行すると、サービスが起動して正常に実行され、すべてのタスクが期待どおりに実行されます。私が見ることができる唯一の違いは、サービスがログオンしたユーザーではなくSYSTEMユーザーとしてプロセスを開始することです. 別のユーザーとしてサービスの実行をテストしましたが、違いはありませんでした。

他の考えは、私のサービスの依存関係にwmiサービスを追加することでしたが、正直なところ、それが何をするのかわかりません:P srvany.exeのようなものを使用せずに、PythonでWindowsサービスを作成しようとしたのはこれが初めてです.

昨夜と今日の大部分をグーグルで検索して、py2exeとwmiの互換性に関する情報を見つけようとしましたが、これまでのところ、私が見つけた提案は上記の問題の解決には役立っていません.

任意の提案をいただければ幸いです。

PS: 貧弱なロギングで私を憎まないでください。別のスクリプトからロガーをカット/ペーストしましたが、適切な変更を加えていません。各行が 2 倍になる可能性があります :P. ログ ファイルは次の場所にあります: "%WINDIR%\system32\DCOMMon.log"

アップデート

このプロジェクトを 1 つではなく 2 つの exe ファイルに分割しようとしました。wmi レジストリ部分を実行するために、サービスに他の exe への外部呼び出しを行わせます。繰り返しますが、デバッグ引数を使用して実行すると問題なく動作しますが、サービスとして開始すると同じエラー メッセージがログに記録されます。ますますこれは、プログラムの問題ではなく、許可の問題のように見え始めています:(

アップデート

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]
) 
4

2 に答える 2

1

だから私は私の愚かさを認める時が来たと思います....:P

これは、Pythonの問題、py2exeの問題、またはWMIの問題ではないことがわかりました。:(

これは多かれ少なかれ単純な許可の問題でした。とても単純な私は月の大部分の間それを見落としました。:(

経験則として、特定のレジストリキーを呼び出して(この場合は)デフォルトの構成設定を取得するサービスを作成する場合は...

多分...たぶん...

「HKEY_CURRENT_USER」ではなく、「HKEY_LOCAL_MACHINE」内にデフォルトのキーを配置する必要がありますか?:P

ええ、それはとても簡単です...

過去に取り組んだ他のプロジェクトからこのルールを覚えておくべきでした。ローカルシステムアカウントとして実行している場合、簡単に言えば、アクセスする「HKEY_CURRENT_USER」サブキーはありません。特定のユーザーの「HKEY_CURRENT_USER」サブキーに絶対にアクセスする必要がある場合、唯一の方法はユーザーになりすますことだと思います。幸いなことに、これは私が達成しようとしていることには必要ありません。

以下のリンクは、私の記憶をジョギングして問題を修正するために必要なものを私に提供しました:

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

簡単に言うと、デフォルト値をすべて「HKEY_LOCAL_MACHINE \ SOFTWARE」サブキーに移行したところ、サービスは完全に機能しています。:D

助けてくれてありがとう、でもこの問題は解決しました;)

于 2009-12-14T23:30:00.450 に答える
0

私はこれの専門家ではありませんが、ここに私の 2 セントの価値があります。

この記事では、必要なターゲット システム権限を持つユーザーとしてログインする必要がある場合があることを説明しています。

しかし、それは少し過剰だと思います。コンピューターの管理者としてコマンド プロンプトを実行しているときに、コマンド ラインからスクリプトをコンパイルしてみましたか?スタートメニューをクリックし、「管理者として実行」をクリックします)。

お役に立てれば

于 2009-11-22T22:41:32.543 に答える