28

SQLを生成して文字列変数に格納する.NET4.0コンソールアプリケーションがあります。この文字列をクリップボードに直接コピーしたい。

これまでのところ、私の調査によると、これを実行できる唯一の方法は、System.Windows.Formsへの参照を追加することです。コンソールアプリケーションに関係のないアセンブリへの参照を追加したくありません。

私たちが現在存在しているユニバース内に、System.Windows.Formsへの参照や、目的が必要最低限​​のコンソールアプリケーション?

4

2 に答える 2

52

クリップボードAPIを呼び出すプラットフォームが可能な解決策です。例:

using System.Runtime.InteropServices;
class Program
{
    [DllImport("user32.dll")]
    internal static extern bool OpenClipboard(IntPtr hWndNewOwner);

    [DllImport("user32.dll")]
    internal static extern bool CloseClipboard();

    [DllImport("user32.dll")]
    internal static extern bool SetClipboardData(uint uFormat, IntPtr data);

    [STAThread]
    static void Main(string[] args)
    {
        OpenClipboard(IntPtr.Zero);
        var yourString = "Hello World!";
        var ptr = Marshal.StringToHGlobalUni(yourString);
        SetClipboardData(13, ptr);
        CloseClipboard();
        Marshal.FreeHGlobal(ptr);
    }
}

これは単なる例です。P / Invoke関数の戻り値をチェックするなど、コードの周りに少しエラー処理を追加すると、良い追加になります。

SetClipboardData面白いビットです。また、クリップボードも必ず開閉する必要があります。

最初の13引数として渡されるのはデータ形式です。13はUnicode文字列を意味します

于 2012-11-26T19:15:45.113 に答える
9

このMarshal.StringToHGlobalUni関数は、実際には に不適切な方法でメモリを割り当てますSetClipboardData (using LocalAlloc with LMEM_FIXED)。これにより、クラッシュが発生する可能性があります (メソッド名が指定されているとは思わないでしょうが、ReSharperを使用するなどしてコードにステップインすると、これが明らかになります)。

SetClipboardDataドキュメントに従って必要です: GlobalAllocMSDNのSetClipboardDataGMEM_MOVABLE

以下は、MIT ライセンスの System.Windows.Forms の代替で、テスト済みでエラー処理が完了しています: Clippy

(コード自体をプッシュするクリップボードは、Clippy.csにあります。)

于 2014-07-11T13:49:01.183 に答える