none
InvalidArgument=Valueは'start'に対して有効ではありません。 RRS feed

  • 質問

  • ComboBoxを継承したコントロールを作成しています。

    OnTextChangedイベントをOverridesして処理を記述したところ、下記のエラーとなってしまいました。

    「InvalidArgument=Valueは'start'に対して有効ではありません。」

    エラー原因は「Me.SelectionStart」または「Me.SelectionLength」の値を保持しておき、

    色々処理後にまた「Me.SelectionStart」または「Me.SelectionLength」に保持していた値を戻しているのですが、

    どうやら最初の「Me.SelectionStart」または「Me.SelectionLength」の値がマイナスな値になっていて、

    書き戻すときにエラーとなっている様です。

    通常時は起動時に0が入ってきて正常に動作しているのですが、何らかの原因でこの値がマイナスな値になると、

    アプリケーションを再度起動し直しても戻らなくなってしまいます。

    ※PCを再起動すると直ります。

    Win32APIなども使用しているので、その辺が悪さをしているのかもとは思っているのですが、

    原因が特定できません。

    調査方法または原因についてアドバイスをお願いします。

    2019年6月4日 5:23

すべての返信

  • tori10さん、こんにちは。フォーラムオペレーターのHarukaです。
    MSDNフォーラムにご投稿くださいましてありがとうございます。

    Comboboxコードをご提供いただけますでしょうか。
    コードなしでそれが推測にすぎないです。

    以下は私のコードです。
    なぜSelectionStartまたはSelectionLengthの値がマイナスな値かを想像できません。

       Public Class mycombobox
            Inherits ComboBox
            Protected Overrides Sub OnTextChanged(e As EventArgs)
                MyBase.OnTextChanged(e)
                Dim start = Me.SelectionStart
                Dim length = Me.SelectionLength
    
                Me.SelectionStart = start
                Me.SelectionLength = length
            End Sub
    End Class
    

    どうぞよろしくお願いします。


    MSDN/ TechNet Community Support Haruka

    ~参考になった投稿には「回答としてマーク」をご設定ください。なかった場合は「回答としてマークされていない」も設定できます。同じ問題で後から参照した方が、情報を見つけやすくなりますので、
    ご協力くださいますようお願いいたします。また、MSDNサポートに賛辞や苦情がある場合は、MSDNFSF@microsoft.comまでお気軽にお問い合わせください。~

    2019年6月5日 7:58
    モデレータ
  • ご返信ありがとうございます。

    こちらのソースでは「MyBase.OnTextChanged(e)」は最後に実行していますが、上記提示いただいたソースで再現します。

    startまたはlengthの値がマイナス値になり、設定時にエラーとなって落ちます。。。

    一度発生するとPC再起動まで直らないことから、発生以前に行った処理でメモリ?の状態が不正になってしまっているのではと考えています。

    この発生原因を突き止める方法は無いでしょうか?

    頻繁に発生するわけではなく、色々な処理が動いているため、再現手順の特定が困難な状況です。

    アドバイスをお願いします。

    2019年6月6日 2:28
  • 「InvalidArgument=Valueは'start'に対して有効ではありません。」

    どうやら最初の「Me.SelectionStart」または「Me.SelectionLength」の値がマイナスな値になっていて、

    たとえば『ComboBox1.Select(-1, 0)』を呼び出すと、下記に示す例外が出力されていました。上記のメッセージと完全に同じというわけではないですが、非常に良く似ていますね。

    System.ArgumentOutOfRangeException:
     Message'-1' の InvalidArgument=Value は 'start' に対して有効ではありません。
    パラメーター名:start

     ParamNamestart
     HResult&H80131502


    一方、SelectionStart や SelectionLength にマイナス値を渡しただけでは 'start' という語を含んだ例外にはなりませんでした。

    まずは、Select メソッドを直接的あるいは間接的に呼び出している箇所がないかトレースしてみてください

    Win32APIなども使用しているので、その辺が悪さをしているのかもとは思っているのですが、

    どういう API を使っているのか分かりませんが、通常の操作では、マイナスになる要因が思い当たりませんでした。(変数操作を誤って、メモリ破壊を起こしているのでもない限りは)

    もしもユーザー操作で後ろから前に選択されていたとしても、SelectionStart や SelectionLength は常に 0 以上になるはず。

    テキスト選択のための API についても検討してみましたが、CB_SETEDITSEL / CB_GETEDITSEL にしろ
    GetComboBoxInfo & EM_SETSEL にしろ、
    「右側から左側に向かって選択」させることはできず
    「左側から右側に向かって選択」する形に補正されるようです。

    無理矢理 ES_MULTILINE スタイルにして EM_SCROLLCARET すれば逆選択できるかもしれませんが、それで SelectionStart がマイナスになるかというと…。


    2019年6月6日 3:02
  • 魔界の仮面弁士様

    詳しく検証までしていただき、ありがとうございます。

    大変助かります。

    Select メソッドは洗い出し、ログを仕込んで調査してみたいと思います。

    ただ、情報に不備があり申し訳ないのですが、発生している個所は画面の初期表示時になります。

    正常に画面表示できていた機能が、ある時から表示時に上記のエラーとなるようになります。

    同じコントロールを使用している他の画面も同様にエラーとなり、一度発生するとアプリケーションを再度実行しなおしても直らず、PCの再起動が必要になります。

    このことから、メモリ破壊を起こしているのではないかと疑っています。

    また、お気づきの点やどの様に調査してみると良いなど、アドバイスなどありましたら是非お願いいたします。

    2019年6月7日 5:41
  • 『ComboBoxを継承したコントロール』の実装に問題がありそうなのですが、現時点では特定できません。(オリジナルの ComboBox で起きている事象でも無さそうですし)

    どの API をどのタイミングで使っているのかといった、コード内容に関する具体的な追加情報を、公開可能な範囲で提供することはできないでしょうか。

    エラー原因は「Me.SelectionStart」または「Me.SelectionLength」の値を保持しておき、

    色々処理後にまた「Me.SelectionStart」または「Me.SelectionLength」に保持していた値を戻しているのですが、

    SelectionStart や SelectionLength を Shadows で再定義しているわけではないのですよね…。

    どうやら最初の「Me.SelectionStart」または「Me.SelectionLength」の値がマイナスな値になっていて、

    SelectionStart とは異なり、SelectionLength の方はマイナス値をセットしても問題ありません。
    「(SelectionStart + SelectionLength) ≧ 0」という関係ならば OK です。

    Select メソッドは洗い出し、ログを仕込んで調査してみたいと思います。

    "InvalidArgument=Value は 'start' に対して有効ではありません。"
    の例外が発せられるということは、Reference Source で言うところの
     「SR.GetString(SR.InvalidArgument, "start", ~~)」
    にあたる処理が呼び出されている可能性が高いです。

    そしてそれに該当するのは、今のところ、
    ComboBox.Start(Int32, Int32) の第 1 引数に 0 未満の値を渡した場合
    ぐらいしか見当たりませんでした。

      

    そこで、ComboBox が自身の Start(負数, 何某) を
    内部的に呼び出しうるところも探してみました。そうすると、
    ComboBox.SelectionLength の setter
    が見つかりました。下記のコードです。

    public int SelectionLength {
        get {
            int[] end = new int[] { 0 };
            int[] start = new int[] { 0 };
            UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.CB_GETEDITSEL, start, end);
            return end[0] - start[0];
        }
        set {
            // SelectionLength can be negtive...
            Select(SelectionStart, value);
        }
    }

    となると問題は、SelectionStart が負数を返すことがありえるのか否か、なんですよね…。

    SelectionStart は Overridable な実装では無いですし、基本クラスの getter 実装を見ても、CB_GETEDITSEL メッセージで得られる WPARAM を無加工ノーチェックで Int32 として返却しているだけなので、割り込む余地はなさそう…。

    public int SelectionStart {
        get {
            int[] value = new int[] { 0 };
            UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.CB_GETEDITSEL, value, (int[])null);
            return value[0];
        }
        set {
            if (value < 0) {
                throw new ArgumentOutOfRangeException("SelectionStart", SR.GetString(SR.InvalidArgument, "SelectionStart", value.ToString(CultureInfo.CurrentCulture)));
            }
            Select(value, SelectionLength);
        }
    }

    2019年6月7日 6:55
  • API で何をやっているのか気になりますが、PC を再起動しないと治らないってことは、環境を疑ったほうがいいかもしれません。
    他の機種や VM 上で実行してみてはいかがでしょうか。

    特定の操作をすると、ノート PC のタッチパッドが不正なパターンのメッセージを投げてきて VB6.0 製のプログラムがコケていたことがあります。

    フックプロシージャをインストールして対応したのですが、後日 MS に問い合わせたら VB のバグなのでドライバを更新するか、フックプロシージャで対応してくださいとの回答があって苦笑いしたことがあります。
    2019年6月7日 7:32
  • 念のためにお聞きしておきたいのですが、今回使用している .NET Framework のバージョンは幾つですか?

    Public Class Form1
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            ComboBox1.Text = "DummyData"
            ComboBox1.SelectionStart = 7
            ComboBox1.SelectionLength = -4
        End Sub
    End Class
    

    上記は「.Select(3, 4)」と同義になることから、SelectionLength は負数の受け入れを許容するはずなんですが……リファレンスを見ると、負数の場合に ArgumentException を投げることになっていました。

    ドキュメントバグあるいは実装バグの可能性もありますが、環境依存性があるという可能性も考慮し、.NET Framework バージョンについてもチェックしておいた方が良さそうです。 

    SelectionStart は Overridable な実装では無いですし、基本クラスの getter 実装を見ても、CB_GETEDITSEL メッセージで得られる WPARAM を無加工ノーチェックで Int32 として返却しているだけなので、割り込む余地はなさそう…。

    ComboBox を継承したクラスで WndProc または DefWindProc メソッドをオーバーライドし、そこに下記のコードを仕込めば、SelectionStart 値をマイナスに差し替えることが一応可能でした。(現状でこんな処理を書いているとは思えませんが)

    Const CB_GETEDITSEL As Integer = &H140
    If m.Msg = CB_GETEDITSEL AndAlso m.WParam <> IntPtr.Zero Then
        Trace.WriteLine(String.Format("生の SelectionStart 値= {0}", Marshal.ReadInt32(m.WParam)))
        Marshal.WriteInt32(m.WParam, 書き換えたい値)
    End If
    2019年6月7日 7:44
  • 返信が遅くなり申し訳ありません。

    APIは今、整理しています。

    環境は複数のPCで発生しているので、アプリケーションの問題な気がしています。

    .NET Frameworkは4.7.2を使用しています。

    再現手順が確立できていないので、発生したら察知出来るような仕込みをしたいのですが、何か手はありますでしょうか?

    よろしくお願いします。

    2019年6月13日 9:01
  • tori10さん、こんにちは。フォーラムオペレーターのHarukaです。
    MSDNフォーラムにご投稿くださいましてありがとうございます。

    問題を解決しますか。
    問題を回避するには、コードcombobox.SelectionStart = 0、combobox.SelectionLength = 0を挿入し、試してください。

    Public Class Form1
    
        Public Class mycombobox
            Inherits ComboBox
            Protected Overrides Sub OnTextChanged(e As EventArgs)
                MyBase.OnTextChanged(e)
                Dim start = Me.SelectionStart
                Dim length = Me.SelectionLength
                Me.SelectionStart = 0
                Me.SelectionLength = 0
            End Sub
        End Class
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Dim mycom As New mycombobox
            mycom.SelectionLength = 0
            mycom.SelectionStart = 0
            Me.Controls.Add(mycom)
        End Sub
    End Class
    

    どうぞよろしくお願いします。


    MSDN/ TechNet Community Support Haruka

    ~参考になった投稿には「回答としてマーク」をご設定ください。なかった場合は「回答としてマークされていない」も設定できます。同じ問題で後から参照した方が、情報を見つけやすくなりますので、
    ご協力くださいますようお願いいたします。また、MSDNサポートに賛辞や苦情がある場合は、MSDNFSF@microsoft.comまでお気軽にお問い合わせください。~

    2019年6月19日 6:03
    モデレータ