6

複数の ClickOnce アプリケーションで使用するライブラリがあります。このライブラリでエラーが発生した場合は、エラーを windows に書き込みたいと思いますEventLog

方法に関するKB 記事を見つけましたが、ソースを検索するには管理者権限が必要なようです。Security具体的には、イベント ログを検索しようとすると停止します。

これを回避して ClickOnce アプリケーションのイベント ログに書き込む方法はありますか? ある人が既知のソースに書き込もうとしているのを見ましたが、一貫して利用可能なソースを見つけることができなかったようです。

編集:

ここでの回答に基づいて、最初の実行時に実行できるアプリケーションに含まれるプログラムを作成して、管理者権限を取得できるイベント ソースを設定します。ただし、ソースが作成されると、まだ書き込めないようです。

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        if (!EventLog.SourceExists("ATE"))
        {
            EventLog.CreateEventSource("ATE", "Application");
        }
    }

ソースを適切に作成します (これは、Yannick Blondeau によって提供されたレジストリ編集と同等です)。昇格されていないアプリケーションでソースに書き込むと、新しいエラーが発生しますが、それでも機能しません。新しいエラーは次のとおりです。

Cannot open log for source 'ATE'. You may not have write access.

編集2:

私は今、CustomSD キーのレジストリ編集を通じてそれを機能させようとしています。(A;;0x7;;;AU) を追加して、認証されたユーザーにフル アクセスを許可しようとしましたが、効果がないように見えました。

4

3 に答える 3

8

残念ながら、イベント ソースを作成するには管理者権限が必要です。ただし、イベント ログへの書き込みや読み取りに管理者権限は必要ありません。

これには 2 つの方法があります。

管理者としてアプリケーションをインストールするときに、新しいイベント ソースを追加します。

アプリケーションを構成するために管理者として実行する単純なアプリを作成します。これは、インストーラーに含めることもできます。

インストーラーがない場合、または必要な場合は、アプリを管理者としてコンピューターにロードし、プログラムを 1 回実行します。イベント ソースがまだ存在しない場合は、アプリの起動時にイベント ソースを構成する必要があります。(わかりました、それは3つの方法です。)

このコード スニペットは Microsoft からのものです: http://msdn.microsoft.com/en-us/library/system.diagnostics.eventlog.aspxであり、管理者ユーザーとして実行するように設計されています。

using System;
using System.Diagnostics;
using System.Threading;

class MySample
{
    public static void Main()
    {
        // Create the source, if it does not already exist. 
        if (!EventLog.SourceExists("MySource"))
        {
             //An event log source should not be created and immediately used. 
             //There is a latency time to enable the source, it should be created 
             //prior to executing the application that uses the source. 
             //Execute this sample a second time to use the new source.
             EventLog.CreateEventSource("MySource", "MyNewLog");
             Console.WriteLine("CreatedEventSource");
             Console.WriteLine("Exiting, execute the application a second time to use the source.");
            // The source is created.  Exit the application to allow it to be registered. 
            return;
        }
        // Create an EventLog instance and assign its source.
        EventLog myLog = new EventLog();
        myLog.Source = "MySource";

        // Write an informational entry to the event log.    
        myLog.WriteEntry("Writing to event log.");
    }
}

私はそれがあなたが求めていたものと正確に一致しないかもしれないことを知っていますが、これがこれを行う唯一の方法だと思います.

編集1:さらにコードを追加

public class EventLogger
{
    private const string logName = "Application";
    private static string appName = "";
    private static bool sourceExists = false;

    public static string AppName
    {
        get { return appName; }
        set { appName = value; }
    }

    public static void Init(string appName)
    {
        AppName = appName;
        sourceExists = EventLog.SourceExists(AppName);

        if (!sourceExists)
        {
            EventLog.CreateEventSource(AppName, logName);
            sourceExists = true;
        }
    }

    private static void Write(string entry, EventLogEntryType logType, int eventID)
    {
        if (sourceExists)
        {
            EventLog.WriteEntry(AppName, entry, logType, eventID);
        }
    }

    public static void Warning(string entry) { Write(entry, EventLogEntryType.Warning, 200); }
    public static void Warning(string entry, int eventID) { Write(entry, EventLogEntryType.Warning, eventID); }
    public static void Error(string entry) { Write(entry, EventLogEntryType.Error, 300); }
    public static void Error(string entry, int eventID) { Write(entry, EventLogEntryType.Error, eventID); }
    public static void Info(string entry) { Write(entry, EventLogEntryType.Information, 100); }
    public static void Info(string entry, int eventID) { Write(entry, EventLogEntryType.Information, eventID); }
}

これは、本番アプリケーションで使用されている EventLogger クラスを実装した方法です。

コードを投稿していただければ、比較を行うことができます。

ソースを作成するときに、アプリケーション名を使用しているのに、アプリケーション ログファイルをそのまま使用していることに気付きました。また、新しいログファイルを作成しようとしていますか? その場合は、イベント ビューアで作成されていることを確認してください。

編集 2: ゼロのユーザー トークン値でユーザーを偽装する

これはちょっと困ったことです。

イベント書き込みコードをラップしたこのコードを試してください。

System.Security.Principal.WindowsImpersonationContext wic = System.Security.Principal.WindowsIdentity.Impersonate(IntPtr.Zero);
// your code to write to event log or any to do something which needs elevated permission--
wic.Undo();

私のコードが機能しているという理由だけで、私はこれを試していません。 -書き込みアクセスを持っている/

于 2012-09-27T06:03:29.697 に答える
2

これに代わる方法は、ClickOnce setup.exe ファイルをダウンロードし、右クリックして管理者として実行することです。あまり満足のいくものではありませんが、機能しているようです。

于 2013-11-09T10:36:24.390 に答える
0

ClickOnceのドキュメントでは、ClickOnceアプリケーションを実行しているユーザーが管理者でない場合、アプリケーションはイベントログへの書き込みに失敗すると言われています。

完全な引用:

ClickOnce配置後、アプリケーションがイベントログにイベントを書き込もうとしたときに、イベントソースがまだ存在しない場合、アプリケーションはイベントソースを作成します。ユーザーが管理者でない場合、試行は失敗し、アプリケーションはイベントをログに記録しません。この場合、イベントソースを手動で作成できます。

イベントソースを手動で作成するには、展開プロセス中に次のようなエントリをレジストリに追加する必要があります。

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application\YourApp]
"EventMessageFile"="%SystemRoot%\\Microsoft.NET\\Framework\\v2.0.50727\\EventLogMessages.dll"

このアプローチにより、展開フェーズでの高度の必要性が制限されます。

于 2012-09-27T07:30:54.350 に答える