11

これは少しトリッキーなので、我慢してください...

私は簡単な小さな方法を持っています:

Public Overloads Shared Function DoStuff(ByVal path As String) As Boolean
        If Not IO.File.Exists(ipath) Then Throw New ArgumentException

        Dim result As Boolean
        Using fs As FileStream = New FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)
            ' do stuff here, details are not important
            fs.Close()
        End Using

        Return result
    End Function

メソッドがストリームの使用方法を示していないことを理解していますが、以下で説明するように詳細は関係ありません。

このメソッドは、クラス ライブラリにぴったりと収まっています。他のさまざまなプロジェクトで参照するヘルパー。明らかに、ほとんどのコードは、パスが有効であり、アクセス可能であるなどの前提で問題なく見えるはずです。

さて本題。ヘルパーアセンブリで前述のメソッドを参照および使用する WCF サービス ライブラリがあります。WCF サービス ライブラリは Windows サービス内でホストされており、これはサーバーの 1 つに常駐しています。WCF サービスには、ファイルの UNC パスを受け取る操作があり、通常のフローでは、ヘルパー クラスで上記のメソッドを呼び出します。

私が送信するパスは、ネットワーク上の共有上のファイル用です。「Using fs As...」という行は、次の例外で失敗します。

System.UnauthorizedAccessException: パス ' my file path is listed here ' へのアクセスが拒否されました。System.IO.__Error.WinIOError (Int32 errorCode、文字列の多分フルパス) で System.IO.FileStream.Init (文字列パス、FileMode モード、FileAccess アクセス、Int32 権限、ブール値の useRights、FileShare 共有、Int32 bufferSize、FileOptions オプション、SECURITY_ATTRIBUTES secAttrs 、System.IO.FileStream..ctor(文字列パス、FileMode モード、FileAccess アクセス、FileShare 共有、Int32 bufferSize、FileOptions オプション、文字列 msgPath、ブール bFromProxy) の文字列 msgPath、ブール値の bFromProxy、ブール値の useLongPath) ..ctor(String パス、FileMode モード) at MyHelperAssemblyName.DoStuff(String filePath)残りの例外は、メソッド、アセンブリ、wcf サービスなどを指すスタック トレースです。 "

さて、私が問題を診断しようとしたことのリスト(ばかばかしいほど明白な手順を含む):

  • スタック トレースにリストされているパスを Windows エクスプローラー (ローカル マシンとサーバーの両方) にコピー アンド ペーストして、ファイルが存在し、アクセス可能であることを確認します -->ファイルにアクセスできます

  • Windows サービスのアカウントがファイルを読み取るための十分なアクセス許可を持っていることを確認します --> [有効なアクセス許可] には、サービスのアカウントがフル コントロールとしてリストされます。

  • 個人の管理者アカウントを使用するように Windows サービスのアカウントを変更し (一時的な措置)、明らかにサービスを再起動して変更を有効にする -->同じコード行が失敗する

  • ファイルを含むディレクトリをローカル マシンにコピーし、ローカル マシンに対してサービスを実行します (ファイルをホストする NAS が原因ではないことを確認したかったのです) -->同じコード行が失敗します

  • 簡単なコンソール アプリケーションを作成し、ヘルパー アセンブリのメソッドからアプリケーションにコードをコピーして貼り付け、同じファイル パスを挿入し、ローカルで実行してからサーバーで実行します (サーバー上とは、同じ管理者を使用してサーバーにリモート接続することを意味します)。前述のアカウントを作成して実行します) -->アプリケーションは問題なくコードを実行できます

  • コンソール アプリケーションを作成し、コンソール アプリケーション内で WCF サービス ライブラリをホストする一括標準方法を使用します。アプリケーションをローカルで実行し、コンソール アプリのベース アドレスとして指定したローカル アドレスに対してWcfStormを使用して、通常のサービスが失敗するのと同じパスで同じメソッドを呼び出します --> WcfStorm からの結果は、コードが問題はありませんでした

  • WCF サービス ライブラリのコードを再確認して、テストに影響を与える固有の条件付きロジックがないことを確認します -->ヘルパー メソッドは、サービス操作の実装が開始された直後 (引数の検証の直後) に呼び出されます。ヘルパー メソッドを実行せずに操作で一貫した結果を返すことはできないため、以前に一貫した結果を受け取っていて、「奇妙な」ファイル アクセス コードが実行されたと想定していたときに、実際には実行されていました。

  • Windows サービス ホスト、WCF サービス ライブラリ、およびヘルパー アセンブリをクリーンにリビルドしてサービスを再展開しました (画面上のコードがサーバー上で実行されていたコードと同じであることを確認したかったため) -->変更なし

  • EDIT 2011-06-24 16:32GMT - 以前に作成したコンソール アプリを使用して WCF サービスをホストし、それに応じて baseAddress を調整し、サーバーに展開します。上記と同じ管理者アカウントを使用してアプリを実行します。WcfStorm を使用して、新しいベース アドレスで新しいアプリをテストします。-->コードは期待どおりに動作し、良好な結果を返します (この段階では、Windows サービスの障害に絞り込むことができると思いますか?)

  • EDIT 2011-06-27 10:21GMT - ヘルパー クラスを参照する単純な Windows サービスを作成しました。サーバーにインストールされ、サービスのアカウントはライブ サーバーと同じに設定されます。-->新しいサービスはコードを実行し、ファイルにアクセスできました

  • EDIT 2011-06-27 10:23GMT - サービスが機能していたことに腹を立て、週末に実行したままにしていた WcfStorm を開きました。結果は、ライブ サービスが失敗したことを示す金曜日から表示された静止画でした。同じリクエストを再送します -->うまくいきました...問題を追跡する実際の手段がないため、実際にはもっとイライラしています

    したがって、サービスは今のところ正しく機能しています。このような断続的な失敗の原因は何ですか? 同僚は、週末に何も変更されていないことを保証しています(少なくとも手動ではありません)。困惑...

4

4 に答える 4

4

process monitor を試してください。ファイルにアクセスしているユーザーと、返された特定の Windows エラー コードが表示されます。次に、一部のファイルで機能し、他のファイルで機能しない理由を確認できるはずです。

于 2011-07-01T15:17:17.480 に答える
1

WCF サービスは偽装を使用していますか?

これにより、新しい Windows サービスではアクションを実行できるのに、WCF サービスでは実行できなかった理由が説明されます。新しいサービスは、NAS に対して直接認証します。古いサービスで WCF が呼び出し元を偽装していた場合、クライアント コンピューターがユーザーを認証し、そのトークンが WCF サービスに渡され、WCF サービスがセキュリティ トークンを NAS に渡すため、ダブル ホップの問題が発生します。

次のように、アクティブなセキュリティ コンテキストをサービス アカウントに戻すことができます

using (WindowsIdentity.Impersontate(IntPtr.Zero))
{
    DoStuff();
}

もちろん、これは断続的に機能していた理由を説明するものではありません。ただし、それをホストしているマシンでローカルに呼び出されたときにWCFサービスが機能することは説明できますが、リモートクライアントマシンからではありません。

于 2011-07-02T10:29:29.220 に答える
1

いくつかの予感があります。

「FileAccess.Read」および/または「FileShare.Read」を「ReadWrite」に設定してみましたか?

また、この警告が要因になる可能性はありますか? http://msdn.microsoft.com/en-us/library/5h0z48dh.aspxから:

注意

特定のカルチャ設定で文字セットをコンパイルし、異なるカルチャ設定で同じ文字を取得すると、文字が解釈できず、例外がスローされる可能性があります。

于 2011-07-03T03:18:41.840 に答える
1

私のコードがまだ完全にディスクに書き込まれていない新しいファイルにアクセスしていたときに、似たようなことがありました。したがって、数ミリ秒待つと解決しました。ディスクに完全に書き込まれる前に、そのストリームを読み込もうとしている可能性はありますか?

于 2011-06-27T10:23:47.897 に答える