none
ProviderExceptionで例外発生 RRS feed

  • 質問

  • 方法:サンプルメンバーシップを実装する を参考にして

    プログラムを書きました。

    イベントログが書かれるかテストしています。

    コネクションの文字列を変えてみたとこと

    Throw New ProviderException(exceptionMessage)

    の次でエラーになってしまいました。

    ユーザーコードによってハンドルされませんでした。

    と表示されています。

    Finallyでは拾ってもらえないのでしょうか?

    サンプルソースにもthrowしたものを拾っている箇所が見当たりません。

    どんな仕組みが想定されているのでしょうか?

    よろしくお願いします。

            Try
                conn.Open()

            Catch ex As SqlException
                If WriteExceptionsToEventLog Then
                    WriteToEventLog(ex, "ValidateUser")

                    Throw New ProviderException(exceptionMessage)
                Else
                    Throw ex
                End If

            Finally
                If Not reader Is Nothing Then
                    reader.Close()
                End If

                conn.Close()

            End Try

     

     

    2011年3月8日 2:34

回答

  • 単にスローした例外を補足するコードが書かれていないだけでしょう。

    これはFinallyではダメということでしょうか?

    Throw New ProviderException(exceptionMessage)

    の後

    Else

    で落ちてしまいます。

    サンプルは Throw New ProviderException(exceptionMessage) の後

    Elseの中に入って Throw を実行して イベントが終わるようになっているのでしょうか?


    Finally句を記述しても例外を補足したことにはなりません。サンプルのソースがどうなっているのかはわかりませんが、往々にしてサンプルコードは例外処理等の冗長な処理は省かれて記述されることが多いと思います。

    .NETの例外処理については、こちらが参考になります。

    .NETの例外処理 Part.1 - とあるコンサルタントのつぶやき - Site Home - MSDN Blogs

    .NETの例外処理 Part.2 - とあるコンサルタントのつぶやき - Site Home - MSDN Blogs

    .NETの例外処理 Part. 3 - とあるコンサルタントのつぶやき - Site Home - MSDN Blogs

    .NET の例外処理 Part. 4 - とあるコンサルタントのつぶやき - Site Home - MSDN Blogs


    Blog:プログラマーな日々 http://d.hatena.ne.jp/JHashimoto/
    2011年3月8日 7:49
  • ProviderExceptionをcatchするのは
    呼び出し元関数のログイン関数の部分をtry catchにするということでしょうか。

    例外をスローする関数を利用する部分、あるいはそれをさらに利用する部分など、適切な場所で try-catch を書いて、例外が発生したときにどうするかを記述することでしょう。
    普通に使っていて起きる例外は try-catch で処理し、あり得ない例外は素直に Application_Error でロギングするぐらいでしょうか。

    ところで、ProviderException とやらは発生して良い例外なんですか?普通に起きるものなんですか?
    それが妥当なのかは、第三者には判断不可能なので、自分で判断してください。

    Global.asaxとweb.configにコードを追加しましたが例外を拾ってくれません。
    設定が足りないのでしょうか。

    この手の 最終手段 はデバッガーで例外を検知するタイミングよりも後の処理になります。(つまり、デバッガーで実行しているとみることのできない画面となる)
    デバッガーなしで実行した場合に表示されるのはこのためだと予想します。

    あくまで 最終手段 であって、通常起きうる例外は適切な処理(エラーの内容をわかりやすくユーザーに伝える、代替処理を実行するなど)を実装するべきです。


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    2011年3月10日 14:25
    モデレータ

すべての返信

  • Finallyでは拾ってもらえないのでしょうか?

    Finally句は例外発生時にも必ず実行されます。単にスローした例外を補足するコードが書かれていないだけでしょう。

    サンプルソースにもthrowしたものを拾っている箇所が見当たりません。

    どんな仕組みが想定されているのでしょうか?

    よろしくお願いします。

    集約例外ハンドラという機構があります。こちらが参考になると思います。

    例外処理デリゲート

     

    本題からは逸れますが、「Throw ex」と書くとそれを書いた箇所が例外の基点となってしまい、本来の例外発生箇所を示すスタックトレースが失われ、障害調査が困難になります。なので単に「Throw」と書くのが定石です。

    FxCopではちゃんとエラーとして検出してくれます。

    【C#プログラミングレッスン】 No.226-FxCopに学ぶ(8): CA2200 [C#プログラミングレッスン] - メルマ!

     


    Blog:プログラマーな日々 http://d.hatena.ne.jp/JHashimoto/
    2011年3月8日 3:59
  • 単にスローした例外を補足するコードが書かれていないだけでしょう。

    これはFinallyではダメということでしょうか?

    Throw New ProviderException(exceptionMessage)

    の後

    Else

    で落ちてしまいます。

    System.Configuration.Provider.ProviderException はユーザー コードによってハンドルされませんでした。
      Message=An exception occurred. Please check the Event Log.
      Source=App_Code.xpw2ruer
      StackTrace:
           場所 CustomMembershipProvider.ValidateUser(String username, String password) 場所 D:\WebSite2\App_Code\CustomMembershipProvider.vb:行 271
           場所 System.Web.Security.Membership.ValidateUser(String username, String password)
           場所 LoginAuth.Login1_Authenticate(Object sender, AuthenticateEventArgs e) 場所 D:\WebSite2\LoginAuth.aspx.vb:行 9
           場所 System.Web.UI.WebControls.Login.OnAuthenticate(AuthenticateEventArgs e)
           場所 System.Web.UI.WebControls.Login.AttemptLogin()
           場所 System.Web.UI.WebControls.Login.OnBubbleEvent(Object source, EventArgs e)
           場所 System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args)
           場所 System.Web.UI.WebControls.Button.OnCommand(CommandEventArgs e)
           場所 System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument)
           場所 System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument)
           場所 System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument)
           場所 System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData)
           場所 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
      InnerException:

     

    サンプルは Throw New ProviderException(exceptionMessage) の後

    Elseの中に入って Throw を実行して イベントが終わるようになっているのでしょうか?


    「Throw ex」については勉強になりました。

    ありがとうございます。

    2011年3月8日 6:48
  • 単にスローした例外を補足するコードが書かれていないだけでしょう。

    これはFinallyではダメということでしょうか?

    Throw New ProviderException(exceptionMessage)

    の後

    Else

    で落ちてしまいます。

    サンプルは Throw New ProviderException(exceptionMessage) の後

    Elseの中に入って Throw を実行して イベントが終わるようになっているのでしょうか?


    Finally句を記述しても例外を補足したことにはなりません。サンプルのソースがどうなっているのかはわかりませんが、往々にしてサンプルコードは例外処理等の冗長な処理は省かれて記述されることが多いと思います。

    .NETの例外処理については、こちらが参考になります。

    .NETの例外処理 Part.1 - とあるコンサルタントのつぶやき - Site Home - MSDN Blogs

    .NETの例外処理 Part.2 - とあるコンサルタントのつぶやき - Site Home - MSDN Blogs

    .NETの例外処理 Part. 3 - とあるコンサルタントのつぶやき - Site Home - MSDN Blogs

    .NET の例外処理 Part. 4 - とあるコンサルタントのつぶやき - Site Home - MSDN Blogs


    Blog:プログラマーな日々 http://d.hatena.ne.jp/JHashimoto/
    2011年3月8日 7:49
  • Throw New ProviderException(exceptionMessage)
    の後
    Else
    で落ちてしまいます。

    認識に少し誤りがあるようです。

    このコードでは、ProviderException という例外をスローしているが、例外を処理するコードを書いていないので、ハンドルされていない例外としてデバッガー(Visual Studio)が検知して、処理を止めています。
    実行位置は Else に見えるかもしれませんが、あくまで Throw の行を実行した直後の位置が表示されているだけであって、デバッグが止まったのは Throw で投げた(スローした)例外が処理されていないことが原因です。

    このコードを利用する人は、利用する側のメソッドやプロパティで ProviderException を Catch してあげなければなりません。
    サンプルコードは部分的に掲載されていることが多いので、そういった Catch の部分が書かれていないだけでしょう。


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    2011年3月8日 14:13
    モデレータ
  • ありがとうございます。

     

    例外をまとめて拾う仕組みは分かりました。

    Global.asaxとweb.configにコードを追加しましたが

    例外を拾ってくれません。

    設定が足りないのでしょうか。

     

    <Global.asax>

        Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
            ' ハンドルされていないエラーが発生したときに実行するコードです
           
            Dim ex As Exception = Server.GetLastError
            Dim errMsg = String.Format("エラーメッセージ\{0}\n\nスタックトレース\n{1}\n", ex.Message, ex.StackTrace)
           
            eventlog.writeentry("Application", errMsg, eventlogentrytype.error)
           
            Response.Redirect("error.htm")
        End Sub

     

    <web.config>

        <customErrors mode="On" defaultRedirect="error.htm" />

    2011年3月10日 5:19
  • ありがとうございます。

    ProviderExceptionをcatchするのは

    呼び出し元関数のログイン関数の部分をtry catchにするということでしょうか。

    try

            If (Membership.ValidateUser(username, password)) Then
                FormsAuthentication.RedirectFromLoginPage(username, False)
            End If

    catch

     

    end try

     

     

     

    2011年3月10日 5:27
  • デバックではなくwebサイトに配置して実行したら

    エラー画面に遷移できました。

    イベントログに

    イベント ID (0) (ソース Application 内) に関する説明が見つかりませんでした。リモート コンピュータからメッセージを表示するために必要なレジストリ情報またはメッセージ DLL ファイルがローカル コンピュータにない可能性があります。この説明を取得するために /AUXSOURCE= フラグを使用することができる可能性があります。詳細については、ヘルプとサポートを参照してください。次の情報はイベントの一部です: エラーメッセージ\種類 'System.Web.HttpUnhandledException' の例外がスローされました。\n\nスタックトレース\n   場所 System.Web.UI.Page.HandleError(Exception e)
       場所 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
       場所 System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
       場所 System.Web.UI.Page.ProcessRequest()
       場所 System.Web.UI.Page.ProcessRequestWithNoAssert(HttpContext context)
       場所 System.Web.UI.Page.ProcessRequest(HttpContext context)
       場所 ASP.loginauth_aspx.ProcessRequest(HttpContext context)
       場所 System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
       場所 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)\n.

    イベント コード: 3005
    イベント メッセージ: ハンドルされていない例外が発生しました。
    イベント時間: 2011/03/10 15:21:16
    イベント時間 (UTC): 2011/03/10 6:21:16
    イベント ID: 16427637bcf3412490f8b99660b10c4f
    イベント シーケンス: 4
    イベント発生: 1
    イベント詳細コード: 0
     
    アプリケーション情報:
        アプリケーション ドメイン: /LM/W3SVC/1/Root/website-1-129442116425156250
        信頼レベル: Full
        アプリケーションの仮想パス: /website
        アプリケーション パス: C:\Inetpub\wwwroot\website\
        コンピューター名: XXXX
     
    プロセス情報:
        プロセス ID: 2596
        プロセス名: aspnet_wp.exe
        アカウント名: XXXX\ASPNET
     
    例外情報:
        例外の種類: ProviderException
        例外メッセージ: An exception occurred. Please check the Event Log.
       場所 CustomMembershipProvider.ValidateUser(String username, String password)
       場所 LoginAuth.Login1_Authenticate(Object sender, AuthenticateEventArgs e)
       場所 System.Web.UI.WebControls.Login.OnAuthenticate(AuthenticateEventArgs e)
       場所 System.Web.UI.WebControls.Login.AttemptLogin()
       場所 System.Web.UI.WebControls.Login.OnBubbleEvent(Object source, EventArgs e)
       場所 System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args)
       場所 System.Web.UI.WebControls.Button.OnCommand(CommandEventArgs e)
       場所 System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument)
       場所 System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument)
       場所 System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument)
       場所 System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData)
       場所 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

     
     
    要求情報:
        要求 URL: http://XXXX/website/LoginAuth.aspx?ReturnUrl=/website/member/20110114.pdf
        要求パス: /website/LoginAuth.aspx
        ユーザーのホスト アドレス: 192.168.XXX.XXX
        ユーザー: 
        認証済み: False
        認証の種類: 
        スレッド アカウント名: XXXX\ASPNET
     
    スレッド情報:
        スレッド ID: 1
        スレッド アカウント名: XXXXX\ASPNET
        偽装: False
        スタック トレース:    場所 CustomMembershipProvider.ValidateUser(String username, String password)
       場所 LoginAuth.Login1_Authenticate(Object sender, AuthenticateEventArgs e)
       場所 System.Web.UI.WebControls.Login.OnAuthenticate(AuthenticateEventArgs e)
       場所 System.Web.UI.WebControls.Login.AttemptLogin()
       場所 System.Web.UI.WebControls.Login.OnBubbleEvent(Object source, EventArgs e)
       場所 System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args)
       場所 System.Web.UI.WebControls.Button.OnCommand(CommandEventArgs e)
       場所 System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument)
       場所 System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument)
       場所 System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument)
       場所 System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData)
       場所 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
     
     
    カスタム イベントの詳細:

    詳細な情報は、http://go.microsoft.com/fwlink/events.asp の [ヘルプとサポート センター] を参照してください。

     

    が書かれていました。

    2つめがちゃんと例外処理で動いた結果のような気がします。

    1つめが出力されるのが合っているのかわかりません。

    2011年3月10日 6:32
  • ProviderExceptionをcatchするのは
    呼び出し元関数のログイン関数の部分をtry catchにするということでしょうか。

    例外をスローする関数を利用する部分、あるいはそれをさらに利用する部分など、適切な場所で try-catch を書いて、例外が発生したときにどうするかを記述することでしょう。
    普通に使っていて起きる例外は try-catch で処理し、あり得ない例外は素直に Application_Error でロギングするぐらいでしょうか。

    ところで、ProviderException とやらは発生して良い例外なんですか?普通に起きるものなんですか?
    それが妥当なのかは、第三者には判断不可能なので、自分で判断してください。

    Global.asaxとweb.configにコードを追加しましたが例外を拾ってくれません。
    設定が足りないのでしょうか。

    この手の 最終手段 はデバッガーで例外を検知するタイミングよりも後の処理になります。(つまり、デバッガーで実行しているとみることのできない画面となる)
    デバッガーなしで実行した場合に表示されるのはこのためだと予想します。

    あくまで 最終手段 であって、通常起きうる例外は適切な処理(エラーの内容をわかりやすくユーザーに伝える、代替処理を実行するなど)を実装するべきです。


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    2011年3月10日 14:25
    モデレータ
  • ありがとうございます。

    ProviderExceptioは通常はおきません。

    デバックと実際の例外が違う理由もわかりました。

     

    2011年3月11日 4:31