locked
クリップボードからのデータの読込み RRS feed

  • 質問

  • お世話になります

     

    カスタムアクティビティ内でクリップボードからデータを読み込む処理を作成したいと考えています

    しかし、アクティビティ内で System.Windows.Clipboard.GetDataObject() を呼び出すと、
    "OLE を呼び出す前に、現在のスレッドをシングル スレッド アパートメント (STA) モードに設定しておく必要があります。"
    という例外が発生してしまいます

     

    WFを実行しているアプリは WPF で作成しており、WorkflowInvoker.Invoke() メッソド呼び出しで WF を実行しています

    また、System.Windows.Forms.Clipboard.GetDataObject() メソッドの場合は null が返されてデータの取得はできませんでした

     

    アクティビティからクリップボードのデータを取得する方法をご存知の方がいらっしゃいましたら、
    お知恵をお貸しください

    以上、よろしくお願いいたします


    2011年8月22日 9:25

回答

  • もう解決されてしまいましたか・・・?

     

    私も色々と試してみました。WorkflowInvoker ではなく WorkflowApplication を利用してクリップボードを読み出す事は出来ました。

    Dim _WfApps As New WorkflowApplication(_sampleWfFile)
    _wfApps.SynchronizationContext = SynchronizationContext.Current
    


    ワークフロー実行側をこのような形で、同期コンテキストにてスレッド間の同期を取る様に指定したところ、

        Protected Overrides Sub Execute(context As System.Activities.CodeActivityContext)
            Dim res = System.Windows.Clipboard.GetDataObject()
            If res IsNot Nothing Then
                If res.GetDataPresent(Windows.DataFormats.Text) Then
    
                    Windows.Forms.MessageBox.Show(res.GetData(Windows.DataFormats.Text).ToString)
                Else
                    Windows.Forms.MessageBox.Show(res.ToString)
                End If
            Else
                Windows.Forms.MessageBox.Show("GetDataObject returns Nothing")
            End If
        End Sub
    


    このようなアクティビティにてクリップボードからの取得は行えました。

    このような方法ではどうでしょうか?

    • 回答としてマーク Nymphaea 2011年9月28日 10:31
    2011年9月21日 11:07

すべての返信

  • アクティビティの中からクリップボードの内容を読み出すのではなく、アプリケーションでクリップボードデータを読みだして、それを WF に渡す方が素直な設計な気がします。

    それではダメなのでしょうか?

    2011年8月22日 13:41
  • 渋木様 返信ありがとうございます。

     

    > アクティビティの中からクリップボードの内容を読み出すのではなく、アプリケーションでクリップボードデータを読みだして、それを WF に渡す方が素直な設計な気がします。

    本来はその通りだと思うのですが、WF 起動後の実行過程で外部アプリを呼び出してクリップボードにデータが格納されるため、ワークフローの実行途中でクリップボードからデータを取り出す必要があります。

     

    データをクリップボードに格納する外部アプリは自作ではないため変更できず、クリップボードからデータを取り出す代替案としてデータを取り出す外部アプリを作成し、それを WF から呼び出す方法を試しました。
    しかし、アプリ単体では実行に問題ないのですが WF から呼び出すとアクティビティ内に記述した際と同様のエラーが発生してしまいます。

    別な方法として、サービスとしてデータを取り出す機能を実装し、それを呼び出す方法を試してその方法であれば問題ないことは確認しているのですが、可能な限り機能を WF 内でまとめてしまいたいため、このような質問をさせていただきました。

    2011年8月23日 4:03
  • もう解決されてしまいましたか・・・?

     

    私も色々と試してみました。WorkflowInvoker ではなく WorkflowApplication を利用してクリップボードを読み出す事は出来ました。

    Dim _WfApps As New WorkflowApplication(_sampleWfFile)
    _wfApps.SynchronizationContext = SynchronizationContext.Current
    


    ワークフロー実行側をこのような形で、同期コンテキストにてスレッド間の同期を取る様に指定したところ、

        Protected Overrides Sub Execute(context As System.Activities.CodeActivityContext)
            Dim res = System.Windows.Clipboard.GetDataObject()
            If res IsNot Nothing Then
                If res.GetDataPresent(Windows.DataFormats.Text) Then
    
                    Windows.Forms.MessageBox.Show(res.GetData(Windows.DataFormats.Text).ToString)
                Else
                    Windows.Forms.MessageBox.Show(res.ToString)
                End If
            Else
                Windows.Forms.MessageBox.Show("GetDataObject returns Nothing")
            End If
        End Sub
    


    このようなアクティビティにてクリップボードからの取得は行えました。

    このような方法ではどうでしょうか?

    • 回答としてマーク Nymphaea 2011年9月28日 10:31
    2011年9月21日 11:07
  • Ahf 様ご返信が遅くなってしまい、申し訳ありませんでした
    アラート設定するのを忘れていたうえに、別な案件にかかりきりになっておりました・・・

    わたしの方でもインターネットで調べた際に、海外サイトで XPS ドキュメントの生成アクティビティの作成で同様の問題があり、
    アクティビティ内で STA モードでスレッドを作成して実行するという記事を見つけたのですが、
    アクティビティ内でスレッドを作成するのは無いね・・・ ということで別な方法を探しまして、
    Ahf 様にご提案いただいている SynchronizationContext を利用する方法も見つけることが出来たのですが、
    影響範囲がよくわからず TechNet などでドキュメントを読み漁っておりました

    結論としては SynchronizationContext を利用する方法が推奨されており、
    修正による影響も軽微だったためこの方法で対応することとなりました

    もっと早く Ahf 様のレスに気付いていればよかったのですが・・・

    Ahf 様ご返信ありがとうございました

    2011年9月28日 10:29