3

バッチで実行する必要があるクライアント ソフトウェアであるサード パーティ ソフトウェアがあるため、バッチ エンジンに取り組んでいます。

このコードを使用してプロセスIDを列挙しています

public IEnumerable<int> EnumerateProcessWindowHandles(int processId)
{
    var handles = new List<IntPtr>();
    try
    {
        foreach (ProcessThread thread in Process.GetProcessById(processId).Threads)
            Win32.EnumThreadWindows(thread.Id,
                                    (hWnd, lParam) =>
                                        {
                                            handles.Add(hWnd);
                                            return true;
                                        }, IntPtr.Zero);

    }
    catch (Exception e) {}
    return handles.Select(h => (int)h);
}

そして、このコードは各ウィンドウのテキストを取得します

public string GetText(int hWnd)
{
    // Allocate correct string length first
    int length = Win32.GetWindowTextLength(hWnd);
    var sb = new StringBuilder(length + 1);
    Win32.GetWindowText(hWnd, sb, sb.Capacity);
    return sb.ToString();
}

サービスからプログラムを実行すると、探しているウィンドウが見つかりません。コンソール プログラムから起動すると動作します。サービスから calc.exe を起動しようとすると、電卓ウィンドウが表示されるので、サービスからウィンドウを取得できます。私のサービスからcalc.exeを聞いているときの出力

2013-04-16 13:52:09; 冗長; 23000; 1728; 5592; バッチ: ウィンドウ hwnd: 8454324; タイトル: 電卓

2013-04-16 13:52:09; 冗長; 23000; 1728; 5592; バッチ: ウィンドウ hwnd: 393910; 題名:

2013-04-16 13:52:09; 冗長; 23000; 1728; 5592; バッチ: ウィンドウ hwnd: 328806; タイトル: GDI+ ウィンドウ

2013-04-16 13:52:09; 情報; 23000; 1728; 5592; バッチ: 電卓表示

私の実際のアプリケーションを聞いているときの出力

2013-04-16 14:25:16; 冗長; 23000; 5076; 5140; バッチ: ウィンドウ hwnd: 524976; タイトル: .NET-BroadcastEventWindow.2.0.0.0.218f99c.0

2013-04-16 14:25:16; 冗長; 23000; 5076; 5140; バッチ: ウィンドウ hwnd: 524978; タイトル: GDI+ ウィンドウ

2013-04-16 14:25:16; 冗長; 23000; 5076; 5140; バッチ: ウィンドウ hwnd: 590366; 題名:

2013-04-16 14:25:16; 冗長; 23000; 5076; 5140; バッチ: ウィンドウ hwnd: 787088; 題名:

2013-04-16 14:25:16; 冗長; 23000; 5076; 5140; バッチ: ウィンドウ hwnd: 656044; 題名:

2013-04-16 14:25:16; 冗長; 23000; 5076; 5140; バッチ: ウィンドウ hwnd: 721578; 題名:

2013-04-16 14:25:16; 冗長; 23000; 5076; 5140; バッチ: ウィンドウ hwnd: 590926; 題名:

ご覧のとおり、ほとんどの hwnds はタイトルのないものですが、同じことをコンソール モードから行うと、

2013-04-16 14:21:08; 冗長; 23000; 4864; 4120; コンソール: ウィンドウ hwnd: 66672; タイトル: MSCTFIME UI

2013-04-16 14:21:08; 冗長; 23000; 4864; 4120; コンソール: ウィンドウ hwnd: 328694; 題名:

2013-04-16 14:21:08; 冗長; 23000; 4864; 4120; コンソール: ウィンドウ hwnd: 328754; 題名:

2013-04-16 14:21:08; 冗長; 23000; 4864; 4120; コンソール: ウィンドウ hwnd: 197656; 題名:

2013-04-16 14:21:08; 冗長; 23000; 4864; 4120; コンソール: ウィンドウ hwnd: 132122; 題名:

2013-04-16 14:21:08; 冗長; 23000; 4864; 4120; コンソール: ウィンドウ hwnd: 132178; タイトル: .NET-BroadcastEventWindow.2.0.0.0.218f99c.0

2013-04-16 14:21:08; 冗長; 23000; 4864; 4120; コンソール: ウィンドウ hwnd: 132100; タイトル: MSCTFIME UI

2013-04-16 14:21:08; 冗長; 23000; 4864; 4120; コンソール: ウィンドウ hwnd: 132186; タイトル: デフォルト IME

2013-04-16 14:21:08; 冗長; 23000; 4864; 4120; コンソール: ウィンドウ hwnd: 132176; タイトル: GDI+ ウィンドウ

2013-04-16 14:21:08; 冗長; 23000; 4864; 4120; コンソール: ウィンドウ hwnd: 197654; タイトル: デフォルト IME

2013-04-16 14:21:08; 冗長; 23000; 4864; 4120; コンソール: ウィンドウ hwnd: 132144; 題名:

2013-04-16 14:21:08; 冗長; 23000; 4864; 4120; コンソール: ウィンドウ hwnd: 132142; 題名:

2013-04-16 14:21:08; 冗長; 23000; 4864; 4120; コンソール: ウィンドウ hwnd: 132140; タイトル: デフォルト IME

2013-04-16 14:21:08; 冗長; 23000; 4864; 4120; コンソール: ウィンドウ hwnd: 459078; タイトル: タスクの進捗状況

2013-04-16 14:21:08; 冗長; 23000; 4864; 4120; コンソール: ウィンドウ hwnd: 132078; タイトル: デフォルト IME

より多くの hwnds とより多くのタイトルを取得します。興味のあるウィンドウはTask Progressです

これは解決可能ですか?私はプロセスを開始するために Process.Start を訴えています

4

1 に答える 1

0

この問題は以前のバージョンでは発生しないため、Vista 以降を使用していると想定しています。@Damien_The_Unbeliever が言ったように、これはセッション 0 の分離の問題です。

これは解決可能ですか?私はプロセスを開始するために Process.Start を訴えています

一般に、セッション 0 で (コードを制御していない) サードパーティ アプリケーションを起動することはお勧めできません。

  • アプリがセッション 0 の制限の下で実行するように設計されているかどうかはわかりません。
  • このセッションからシステムに大きな損害を与える可能性があるため、セキュリティの問題。

CreateProcessAsUserを使用して、STARTUPINFO の lpDesktop メンバーを "Winsta0\\default" およびCreateEnvironmentBlockを介して取得した環境ブロックに設定するように注意してください。C# からこれらを呼び出す方法については、この投稿を参照してください。

WTSQueryUserTokenを介してユーザー トークンを取得できます。セッション ID は、WTSEnumerateSessionsまたは SERVICE_CONTROL_SESSIONCHANGE メッセージを介してサービスで使用できます。

ご覧のとおり、ほとんどの hwnds にはタイトルがありません。

ウィンドウ テキストを取得できない理由は、Windows が WM_GETTEXT メッセージを送信してこの操作を実行するためです ( msdn の「備考」セクションを参照)。もちろん、エンジンはサービス デスクトップ上にあるため、これを行うことはできません。

ユーザーのデスクトップでSetThreadDesktopを呼び出した別のスレッドで操作を実行することにより、サービスでこれを回避できます (注意してください。注意事項の警告を参照してください)。

于 2013-04-16T19:01:35.583 に答える