web-dev-qa-db-ja.com

Stringの内容をC#のクリップボードにコピーするにはどうすればよいですか?

文字列にテキストがある場合、ユーザーが別のウィンドウに貼り付けることができるように(たとえば、アプリケーションからメモ帳に)クリップボードにコピーするにはどうすればよいですか?

250
Elie

System.Windows.Forms.Clipboard.SetText(...)を使用できます。

315
ravuya
129
Jeff Moser

SetTextの呼び出しは簡単でしたが、対処しなければならない落とし穴がかなりあります。呼び出しているスレッドがSTAで実行されていることを確認する必要があります。アクセス拒否エラーで失敗し、数秒後に問題なく動作することがあります-クリップボードのCOMタイミングの問題と関係があります。また、アプリケーションがリモートデスクトップ経由でアクセスされる場合、クリップボードへのアクセスは不完全です。 SetTextを直接呼び出すのではなく、これらのシナリオをすべて処理するために集中化されたメソッドを使用します。

@Stecy:集中コードは次のとおりです。

StaHelperクラスは、クリップボードが必要とするシングルスレッドアパートメント(STA)のスレッドで任意のコードを実行するだけです。

abstract class StaHelper
{
    readonly ManualResetEvent _complete = new ManualResetEvent( false );    

    public void Go()
    {
        var thread = new Thread( new ThreadStart( DoWork ) )
        {
            IsBackground = true,
        }
        thread.SetApartmentState( ApartmentState.STA );
        thread.Start();
    }

    // Thread entry method
    private void DoWork()
    {
        try
        {
            _complete.Reset();
            Work();
        }
        catch( Exception ex )
        {
            if( DontRetryWorkOnFailed )
                throw;
            else
            {
                try
                {
                    Thread.Sleep( 1000 );
                    Work();
                }
                catch
                {
                    // ex from first exception
                    LogAndShowMessage( ex );
                }
            }
        }
        finally
        {
            _complete.Set();
        }
    }

    public bool DontRetryWorkOnFailed{ get; set; }

    // Implemented in base class to do actual work.
    protected abstract void Work();
}

次に、クリップボードにテキストを設定するための特定のクラスがあります。 Windows/.NETの一部のバージョンのEdgeの場合には、DataObjectを手動で作成する必要があります。今は正確なシナリオを思い出せませんが、.NET 3.5では必要ないかもしれません。

class SetClipboardHelper : StaHelper
{
    readonly string _format;
    readonly object _data;

    public SetClipboardHelper( string format, object data )
    {
        _format = format;
        _data = data;
    }

    protected override void Work()
    {
        var obj = new System.Windows.Forms.DataObject(
            _format,
            _data
        );

        Clipboard.SetDataObject( obj, true );
    }
}

使用方法は次のとおりです。

new SetClipboardHelper( DataFormats.Text, "See, I'm on the clipboard" ).Go();
64
Paul Alexander

WPF:System.Windows.Clipboard(PresentationCore.dll)

Winforms:System.Windows.Forms.Clipboard

どちらにも静的なSetTextメソッドがあります。

22
bsneeze

これは私のために働く:

あなたがしたい:

System.Windows.Forms.Clipboard.SetText("String to be copied to Clipboard");

ただし、ApartmentState.STAの単一スレッド内にある必要があるというエラーが発生します。

それでは、そのようなスレッドで実行させましょう。そのコード:

public void somethingToRunInThread()
{
    System.Windows.Forms.Clipboard.SetText("String to be copied to Clipboard");
}

protected void copy_to_clipboard()
{
    Thread clipboardThread = new Thread(somethingToRunInThread);
    clipboardThread.SetApartmentState(ApartmentState.STA);
    clipboardThread.IsBackground = false;
    clipboardThread.Start();
}

copy_to_clipboard()を呼び出した後、文字列がクリップボードにコピーされるため、貼り付けまたは Ctrl + V そして、文字列をクリップボードにコピーされる文字列として返します。

16
benli1212

この質問に示されているソリューションSystem.Windows.Forms.Clipboard.SetText(...)を使用すると、例外が発生します。

OLE呼び出しを行う前に、現在のスレッドをシングルスレッドアパートメント(STA)モードに設定する必要があります

これを防ぐために、属性を追加できます。

[STAThread]

static void Main(string[] args)
13
Leroy

Windowsフォームでは、文字列がテキストボックスにある場合、これを簡単に使用できます。

textBoxcsharp.SelectAll();
textBoxcsharp.Copy();
textBoxcsharp.DeselectAll();
6
Magnetic_dud