C#で外部アプリケーションから複数行の文字列を取得する方法

このQ&Aのポイント
  • C#で外部のアプリケーションのリッチテキストコントロールの複数行の文字列を取得する方法について説明します。
  • 上記のコードでは、FindWindowとFindWindowExメソッドを使用して、対象のアプリケーションとリッチテキストコントロールを特定しています。
  • SendMessageメソッドを使用して、WM_GETTEXTメッセージを送信し、リッチテキストコントロールの内容を取得しています。
回答を見る
  • ベストアンサー

C# 他のアプリケーションから複数行取得

C#で外部のアプリケーションのリッチテキストコントロールの複数行の文字列を取得したいです。 自分は下のコードを書いたのですが、これだと1行しか取得できませんでした。 どこが悪いでしょうか。 ここでは対象のアプリケーションをA、リッチテキストのコントロールをRichEditとします。 button1をクリックしたら、textbox1にRichEditの内容が表示されるようなものを作ろうとしています。 //ここから [DllImport("user32.dll", CharSet = CharSet.Auto)] static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll", SetLastError = true)] static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); [DllImport("user32.dll", CharSet = CharSet.Auto)] static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, int wParam, StringBuilder lParam); private const int WM_GETTEXT = 0x000D; private void button1_Click(object sender, EventArgs e) { IntPtr hWnd = FindWindow("A", ""); if (hWnd != null) { IntPtr hWndChild = FindWindowEx(hWnd, IntPtr.Zero, "RichEdit", ""); StringBuilder strBuilder = new StringBuilder(); SendMessage(hWndChild, WM_GETTEXT, strBuilder.Capacity, strBuilder); StringReader strReader = new StringReader(strBuilder.ToString()); string stResult = string.Empty; while (strReader.Peek() >= 0) { string stBuffer = strReader.ReadLine(); stResult += stBuffer + System.Environment.NewLine; } strReader.Close(); textbox1.Text = stResult; } }

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

>StringBuilder strBuilder = new StringBuilder(); を、大きめの容量を指定して StringBuilder strBuilder = new StringBuilder(1000); のようにしてみてはどうでしょう。 あと、 >StringReader strReader = new StringReader(strBuilder.ToString()); >string stResult = string.Empty; >while (strReader.Peek() >= 0) >{ > string stBuffer = strReader.ReadLine(); > stResult += stBuffer + System.Environment.NewLine; >} >strReader.Close(); >textbox1.Text = stResult; でもいいと思いますが、 textbox1.Text = strBuilder.ToString(); とするだけでよいのではないかと思います。

nodasdd
質問者

お礼

こんな簡単なことだったとは・・・ 非常に助かりました。ありがとうございました。

関連するQ&A

  • 【C#】FindWindowExの使い方を教えてください

    はじめまして Visual Studio 2005を使用しています。 C#.NETは、いじり初めて1週間の超初心者です。 C#.NETでのFindWindowExの使い方を教えてください。 まずはじめに、vb.netで作ったアプリAの"Form1"があり、その中にテキストボックス"TextBox1"があります。 "TextBox1"のテキスト(キャプション?)には同じく"TextBox1"と入力されています。 そこで、C#側のアプリBでVBのアプリAの"Form1"のハンドルをFindWindowで取得します。 ここまでは出来ました。 次に、FindWindowExを使って"TextBox1"のハンドルを取得したいのですが、どうしてもうまく取得できません(0が返ってきます) 以下、C#のソースです。 (textBox1のMultilineはTrueです) ================================================================== using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; namespace WindowsApplication1 { public partial class Form1 : Form { [DllImport("user32.dll")] static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll")] static extern IntPtr FindWindowEx(IntPtr hWnd, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); public IntPtr hWnd = (IntPtr)0; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { IntPtr hWnd; IntPtr hWndTest; string sClassName = null; string sWindowText = "AppA"; // アプリAのウインドウハンドルを取得 hWnd = FindWindow(sClassName, sWindowText); textBox1.Text = "ウインドウのハンドル " + hWnd + "\r\n"; // アプリAのウインドウ内のTextBox1のハンドルを取得 hWndTest = hWnd; sClassName = null; sWindowText = "TextBox1"; hWnd = FindWindowEx(hWndTest, IntPtr.Zero, sClassName, sWindowText); textBox1.Text += "テキストボックスのハンドル " + hWnd; } } } ================================================================== Spy++で覗くとテキストボックスにもハンドルが割り与えられているので取得できるはずだと思っているのですが、どうしてもいまくいきません。 どうか、よろしくご享受願います。 ちなみに、アプリAのテキストボックスのクラス名が”WindowsForms10.EDIT.app.0.378734a”となっているのですが、これはどの環境でビルド(コンパイル)しても不変なのでしょうか? 不変だとしたら、クラス名を使えば悩まずに取得できると思うのですが・・・(実験済み)

  • C#のDllImportでuint型をどう指定すればいいのでしょうか?

    [DllImport("User32.dll")] public static extern IntPtr GetNextWindow(IntPtr hWnd,uint wCmd);の uint wCmdに GW_HWNDNEXTを指定したいのですがどのような 書き方で指定したらいいのでしょうか? よろしくお願いいたします

  • C#でウィンドウのアイコン取得する方法

    タスクマネージャのアプリケーションタブに 起動しているアプリケーション名とアイコンが一覧で表示されている部分のように 小さいアイコンを取得したいんですがなかなかうまくいきません。 ファイルに紐付くアイコンと解釈していただいても構いません。 とりあえず、下記のWin32 APIの処理を利用してみましたが SHGetFileInfoだけしかうまくいきませんでした。 しかし、SHGetFileInfoも、アイコンは取得できますがこれはファイルに紐付くアイコンではなく 実行体(EXE)に紐付くアイコンで表示されてしまいました。 開いているウィンドウ情報からだと実行プロセスのEXEのパスしか分からないからです。 ★質問★: ファイルに紐付く小さいアイコンの取得方法を教えてください!できればサンプルソース込みだと助かります。 #region 小さいアイコンを取得するためのWin32 API(ファイルパスから) // SHGetFileInfo関数 [DllImport("shell32.dll")] private static extern IntPtr SHGetFileInfo( string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags); // SHGetFileInfo関数で使用するフラグ private const uint SHGFI_ICON = 0x100; // アイコン・リソースの取得 private const uint SHGFI_LARGEICON = 0x0; // 大きいアイコン private const uint SHGFI_SMALLICON = 0x1; // 小さいアイコン private const uint SHGFI_TYPENAME = 0x400;//ファイルの種類 // SHGetFileInfo関数で使用する構造体 private struct SHFILEINFO { public IntPtr hIcon; public IntPtr iIcon; public uint dwAttributes; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string szDisplayName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)] public string szTypeName; }; #endregion #region 小さいアイコンを取得するためのWin32 API(ウィンドウハンドルからその1) [DllImport("user32.dll", EntryPoint = "GetClassLong")] public static extern IntPtr GetClassLongPtr32(IntPtr hWnd, int nIndex); [DllImport("user32.dll", EntryPoint = "GetClassLongPtr")] public static extern IntPtr GetClassLongPtr64(IntPtr hWnd, int nIndex); const int GCL_HICON = (-14); const int GCL_HICONSM = (-34); #endregion #region 小さいアイコンを取得するためのWin32 API(ウィンドウハンドルからその2) [DllImport("User32.dll", EntryPoint = "SendMessage")] public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam); public const int WM_GETICON = 0x7F; public const int WM_SETICON = 0x80; public const int ICON_SMALL = 0; public const int ICON_BIG = 1; #endregion

  • 特定座標のRGB値取得について

    kimarioと申します。 実行中の、あるアプリケーションの任意座標位置のRGB値を取得し、その結果を メッセージボックスにて表示させたいと考えております。 しかし下記のプログラムを実行すると、どの座標位置でもすべて(-1)で返ってき てしまいます。 getDCの戻り値が(0)ではないことを確認しているので、デバイスコンテキストの ハンドルは取得できているものと思われます。 API初心者です。よろしくお願いいたします。 補足) アプリケーションのウィンドウタイトルが「XXYYZZ」 色を特定したい座標を(60, 60)としています。 ############################################################################ public partial class Form1 : Form { [DllImport("user32.dll")] static extern IntPtr GetDC(IntPtr hWnd); [DllImport( "user32.dll" )] static extern int ReleaseDC( IntPtr hWnd, IntPtr hDC ); [DllImport( "gdi32.dll" )] static extern int GetPixel( IntPtr hDC, int x, int y ); public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { foreach (Process p in Process.GetProcesses()) { if (p.MainWindowHandle != IntPtr.Zero) { if (p.MainWindowTitle == "XXYYZZ") { IntPtr dc = GetDC(p.MainWindowHandle); MessageBox.Show(GetPixel(dc, 60, 60).ToString()); } } } } }

  • C# パラメータが消える

    以下の様に 共通変数クラスSystemStartDEC を作成し、変数セットまではできてますが Login_Loadでは変数がクリアされています。 なぜでしょうか? public Login() { InitializeComponent(); Login_Load(); this.BtnCancel.Click += new System.EventHandler(this.BtnCancel_Click); this.BtnLogin.Click += new System.EventHandler(this.BtnLogin_Click); } private void Login_Load() { string[] strParam; //iniファイル読込 if (InspecTool004_02.GetIni(this.lVerComVal) == false) { clsEnc.DeleteFile(strSettingIniName); MessageBox.Show("INIファイルの読み込みに失敗しました。" + "/r/n" + "終了します。"); return; } } public class InspecTool004_02 { class IniFileHandler { [DllImport("KERNEL32.DLL")] public static extern uint GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault, StringBuilder lpReturnedString, int nSize, string lpFileName); [DllImport("KERNEL32.DLL", EntryPoint="GetPrivateProfileStringA")] public static extern uint GetPrivateProfileStringByByteArray(string lpAppName, string lpKeyName, string lpDefault, byte [] lpReturnedString, uint nSize, string lpFileName); [DllImport("KERNEL32.DLL")] public static extern uint GetPrivateProfileInt( string lpAppName, string lpKeyName, int nDefault, string lpFileName ); [DllImport("KERNEL32.DLL")] public static extern uint WritePrivateProfileString( string lpAppName, string lpKeyName, string lpString, string lpFileName); [DllImport("winmm.dll")] public static extern uint timeGetTime(); } //INIファイル読み込み public static Boolean GetIni(SystemStartDEC.strCom lVerComVal ) { StringBuilder sb_1 = new StringBuilder(1024); string strIniName ; string strBuffer ; Boolean bRtn ; strIniName = ".\\" + SystemStartDEC.strCom.SettingIniName; //DB Section IniFileHandler.GetPrivateProfileString("DB", "ConStr", "default", sb_1, sb_1.Capacity, strIniName); if( sb_1.ToString() == "default" ) { MessageBox.Show("SettingINIファイルDBセクションのConStrが読めません。"); return false; } lVerComVal.IniParam.DBStr = sb_1.ToString(); } public class SystemStartDEC { ////// <summary> ////// 全体共通 ////// </summary> ////// <remarks></remarks> public struct strCom { public strIniParam IniParam; public strUserInfo UserInfo ; public strDispInfo DispInfo ; public strMailInfo MailInfo ; } }

  • C# タスクバーを隠したフォーム固定の方法

    前略 ・C#の初心者です。 ・先日このMSN相談箱でtsukasa-12rさんからタスクバーを非表示する下記のプログラムをおしえていだきました。 このプログラムでウィンドウフォームを固定しようとして this.FormBorderStyle = FormBorderStyle.FixedSingle; のコードを1行だけ追加しましたがウィンドウフォームを固定できませんでした。  タスクバーを隠して かつウィンドウフォームを固定したいのですが tsukasa-12rさん以外の方でもかまいませんのでどなたか教えてください。  以上、よろしくお願いします //----------------------------------- using System; using System.Drawing; using System.Runtime.InteropServices; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form1 : Form { [DllImport("user32.dll", SetLastError = true)] static extern IntPtr FindWindow(string lpClassName, IntPtr lpWindowName); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); private const int SW_HIDE = 0; private const int SW_NORMAL = 1; [StructLayout(LayoutKind.Sequential)] struct APPBARDATA { public int cbSize; public IntPtr hwnd; public uint uCallbackMessage; public uint uEdge; public Rectangle rc; public int lParam; }; private const int ABM_SETSTATE = 10; private const int ABS_AUTOHIDE = 1; private const int ABS_ALWAYSONTOP = 2; [DllImport("shell32.dll")] static extern int SHAppBarMessage(int msg, ref APPBARDATA pbd ); public Form1() { InitializeComponent(); // 「タスクバーを自動的に隠す」 APPBARDATA abd = new APPBARDATA(); abd.cbSize = Marshal.SizeOf(abd); abd.lParam = ABS_AUTOHIDE; SHAppBarMessage(ABM_SETSTATE, ref abd); // タスクバーを非表示 ShowWindow(FindWindow("Shell_TrayWnd", IntPtr.Zero), SW_HIDE); // コントロールボックスを非表示 this.ControlBox = false; // 最大表示 this.WindowState = FormWindowState.Maximized; this.FormBorderStyle = FormBorderStyle.FixedSingle;// ← ウィンドウサイズを固定しようとして追加 → 固定できず } private void button1_Click(object sender, EventArgs e) { // タスクバーを常に表示 APPBARDATA abd = new APPBARDATA(); abd.cbSize = Marshal.SizeOf(abd); abd.lParam = ABS_ALWAYSONTOP; SHAppBarMessage(ABM_SETSTATE, ref abd); // タスクバーを表示 ShowWindow(FindWindow("Shell_TrayWnd", IntPtr.Zero), SW_NORMAL); // フォームを閉じる this.Close(); } } }

  • C#からC++のDLLを使いたい時

    C#からC++(unmanaged)のDLLを使いたい時、 DLLをどのように参照すればよいのでしょうか。 [DllImport("名前.dll")] extern static double 関数名(); という指定は分かるのですが、 それだけじゃもちろん、 「DLL (名前.dll) を読み込めません。」 ってなりますよね・・・。

  • C#でのWNetAddConnection3の使い方を教えてください

    現在、C#(VisualStudio2005)で共有フォルダの認証を行い、 そのフォルダ内のファイルを読み込む処理を行ないたいと考えています。 ■動作------------------------------------------------------ 1.ボタン押下によってフォルダ(\\aaa)をユーザ(user)、パスワード(pass)で認証を行なう 2.ファイル(bbb.txt)の内容をメッセージボックスに出力する 3.認証を切る ■現在の実装状況-------------------------------------------- private void btnGetShareFileData_Click(object sender, EventArgs e) { NETRESOURCE netresource = new NETRESOURCE(); netresource.dwType = 1; netresource.lpLocalName = null; netresource.lpRemoteName = "\\\\aaa"; netresource.lpProvider = null; try { int returnNo1 = WNetAddConnection3(IntPtr.Zero, ref netresource, "user", "pass", 0); System.IO.StreamReader streamReader = new System.IO.StreamReader("\\\\aaa\\bbb.txt", System.Text.Encoding.GetEncoding(932)); MessageBox.Show(streamReader.ReadToEnd()); int returnNo2 = WNetCancelConnection2("\\\\aaa", "0", true); } catch (Exception ex) { MessageBox.Show(ex.Message); } } [StructLayout(LayoutKind.Sequential)] public struct NETRESOURCE { public int dwType; public string lpLocalName; public string lpRemoteName; public string lpProvider; } [DllImport("mpr.dll")] private static extern int WNetAddConnection3( System.IntPtr hWndOwner, ref NETRESOURCE lpNetResource, string lpPassword, string lpUserName, int dwFlags ); [DllImport("mpr.dll")] private static extern int WNetCancelConnection2( string lpName, string dwFlags, bool fForce ); [DllImport("mpr.dll")] private static extern int WNetAddConnection2( ref NETRESOURCE lpNetResource, string lpPassword, string lpUsername, int dwFlags ); ■結果------------------------------------------------------ WNetAddConnection3の戻り値が「487」で System.IO.StreamReader streamReaderを実行されると 「ログオン失敗:ユーザ名を認識できないかまたはパスワードが間違っています。」 とエラーになってします。 WNetAddConnection3でのログオン自体がうまくできていないのでしょうですが、 どうすればよいのかがわかりません。 (ちなみにWNetAddConnection2でやってみても同様です) どなたか教えていただけないでしょうか? いろいろなページは参考にさせていただいているのですが、 知識が足らず読み解くことができないので、 できればサンプルコード等を教えていただけると助かります。 よろしくお願いいたします。

  • VS2010C#からのDLL使用について

    VS2010 C#からVC6で作成したDLLへint配列を引数として渡したい。 VC++6で作成されたDLLがあります。 ここで定義されている int test(char*fname,int* x,int* y); ファイルのフルパスを渡すと 返り値が関数の成否のコードを返す。 処理内で x,y にファイルから読み込んだ値が それぞれ上限100個としてセットして返す といったような関数を C#から呼び出したいのですが 1 [DllImport("dll名", EntryPoint = "test", CallingConvention = CallingConvention.Cdecl)] public unsafe static extern int test(IntPtr fname, ref int* x,ref int* y); 2 [DllImport("dll名", EntryPoint = "test", CallingConvention = CallingConvention.Cdecl)] public unsafe static extern int test(IntPtr fname, ref IntPtr x,ref IntPtr y); と2種類の呼び出し方法をこころみました。 ファイルのフルパスは IntPtr fnamePtr = Marshal.StringToHGlobalAnsi(string型ファイルフルパス); としております。 1の場合は int[] resX = new int[100]; int[] resY = new int[100]; fixed(int* x= resX) fixed(int* x= resY) として呼び出そうとすると : エラー CS1657: '固定変数' であるため、'x' を ref または out 引数として渡せません となり失敗してしまいます。 2 で試みた場合 int size = sizeof(int)*100; IntPtr x = Marshal.AllocHGlobal(size); IntPtr y = Marshal.AllocHGlobal(size); と引き渡したところ ビルドは通りますが 実行時に System.AccessViolationException' のハンドルされていない例外が 発生しました。 追加情報: 保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。 となってしまいます。 どのようにすれば思惑通りの結果を得られますでしょうか。

  • dllの呼び出しで引数が渡らないらしい

    dllの呼び出しで引数が渡らないらしい 50間近になって.NETにチャレンジ。日々?!?の毎日です。 ネットに転がっていた「静的にdllを引用する」コードは動きました。が、「動的にdllを引用」するコードをネットからかき集めてくみ上げましたが引数が旨く渡らないのか、思うように動きません。当該dllはgogo.dllで有名だと思います。 正直、ManagedとUnmanagedのメモリ管理とか、呼び出しの引数の渡し方も理解していません。見よう見まね状態ですが、どうしても当該dllを使いたいので掲載してしまいました。(^_^; 下記の問題が2つ 1)引数に「ref」を付けないと「保護されたメモリ…」のエラーが発生してしまう。  たぶん、このような現象が出ること自体に呼び出し方の問題がある? 2)最終的にファイル名fnがdll側に旨く渡っていないように思える。  Marshal…を使うのかも知れませんが、よくわかりません。 素人質問で恐縮ですが、下記のような動的なdllの引用で、静的な引用と同じように動くコードの書き方を教えて下さい。言語はc#です。 下記がコードですが、文字数削るためかなり行を削っています。初期化とかはちゃんとコーディングしています。 [静的にdll引用=>正常終了] [DllImport("gogo.dll", EntryPoint = "MPGE_setConfigure")] static extern int MPGE_setConfigureStrings(int mode, int dwPara1, string dwPara2); (中略) string fn = "D:\\test.wav"; i = MPGE_setConfigureStrings(1, 0, fn); =>この後、test.wavに対しての処理で正常終了が返る(^_^) [動的にdllを引用=>ダメ] [DllImport("kernel32")] static extern int LoadLibrary(string lpLibFileName); [DllImport("kernel32")] static extern IntPtr GetProcAddress(int hModule, string lpProcName); [UnmanagedFunctionPointer(CallingConvention.StdCall, SetLastError = true, CharSet = CharSet.Ansi)] delegate int d_MPGE_setConfigure(ulong mode, ref ulong dwPara1, string dwPara2); [MarshalAs(UnmanagedType.FunctionPtr)] static d_MPGE_setConfigure e_MPGE_setConfigure; (中略) IntPtr p_MPGE_setConfigure = GetProcAddress(dllHandle, "MPGE_setConfigure"); e_MPGE_setConfigure = (d_MPGE_setConfigure)Marshal.GetDelegateForFunctionPointer(p_MPGE_setConfigure, typeof(d_MPGE_setConfigure)); string fn = "D:\\test.wav"; ulong p1 = 0; i = e_MPGE_setConfigure(1, ref p1, fn); =>この後、dllからtest.wavが読み込めない旨のメッセージが吐かれる(T.T) 以上です。

専門家に質問してみよう