2013-05-15 1 views
0

У меня есть проблема, которую я пытаюсь получить название оконного путем этого имя процесса, и я не могу это сделать здесь то, что я пробовал:Получить заголовок окна по его имя процесса без главного окна

Process[] p = Process.GetProcessesByName("Acrobat"); 
Console.WriteLine(p[0].MainWindowTitle); 
Console.ReadLine(); 

Но проблема в том, что я могу получить его только в том случае, если связанный процесс имеет главное окно. Как я могу заставить его работать?

Основная цель состоит в том, что я имею метод, названный BringToFront() Но этот метод запросит имя заголовка, который является «thenameofthePDF.pdf - Adobe Acrobat Pro (Да, акробат запущен с открытой PDF) I . хотел бы, чтобы перед моим окном Acrobat .. , но для этого мне нужно имя окна, как мой метод прошу подпись Вот весь код в данный момент:

class Program 
{ 
    [DllImport("User32.dll")] 
    public static extern Int32 SetForegroundWindow(int hWnd); 

    [DllImport("user32.dll")] 
    public static extern int FindWindow(string lpClassName, string lpWindowName); 

    private static void BringToFront(string className, string CaptionName) 
    { 
     SetForegroundWindow(FindWindow(className, CaptionName)); 
    } 

    static void Main(string[] args) 
    { 
     // BringToFront("Acrobat", "mypdf.pdf - Adobe Acrobate Pro"); 
     Process[] p = Process.GetProcesses(); 
     foreach (var process in p) 
     { 
      Console.WriteLine(process.MainWindowTitle); 
     } 
     Console.ReadLine(); 
    } 
} 
+0

Вы хотите найти название окна, которое не существует? Вы внимательно подумали о том, что это значит? –

+0

Я действительно не понимаю, почему он не работает, может ли программа иметь «подокна» без наличия «основного» окна? Почему он не работает, я уверен, что acrobat работает, имеет заголовок Windows и имеет графический интерфейс. –

+1

Мы можем сделать лучше, если узнаем вашу общую цель - я предполагаю, что конечная цель заключается не только в том, чтобы иметь возможность сбрасывать название окна Acrobat на консоль - похоже, что это часть «решения» проблемы, t рассказал нам о - и вы, возможно, не решаете его правильно. –

ответ

0

Одним из возможных решений является перечислить все на высшем уровне окна и выбрать тот, который вас интересует. В вашем случае это будут все окна с классом AcrobatSDIWindow и заголовок окна, начинающийся с вашего имени документа.

class Program 
{ 
    public class SearchData 
    { 
     public string ClassName { get; set; } 
     public string Title { get; set; } 

     private readonly List<IntPtr> _result = new List<IntPtr>(); 
     public List<IntPtr> Result 
     { 
      get { return _result; } 
     } 
    } 

    [DllImport("User32.dll")] 
    public static extern Int32 SetForegroundWindow(IntPtr hWnd); 

    [DllImport("user32.dll")] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, ref SearchData data); 

    private delegate bool EnumWindowsProc(IntPtr hWnd, ref SearchData data); 

    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] 
    public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount); 

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); 

    public static bool EnumProc(IntPtr hWnd, ref SearchData searchData) 
    { 
     var sbClassName = new StringBuilder(1024); 
     GetClassName(hWnd, sbClassName, sbClassName.Capacity); 
     if (searchData.ClassName == null || Regex.IsMatch(sbClassName.ToString(), searchData.ClassName)) 
     { 
      var sbWindowText = new StringBuilder(1024); 
      GetWindowText(hWnd, sbWindowText, sbWindowText.Capacity); 
      if (searchData.Title == null || Regex.IsMatch(sbWindowText.ToString(), searchData.Title)) 
      { 
       searchData.Result.Add(hWnd); 
      } 
     } 
     return true; 
    } 

    static void Main(string[] args) 
    { 
     var searchData = new SearchData 
      { 
       ClassName = "AcrobatSDIWindow", 
       Title = "^My Document\\.pdf.*" 
      }; 

     EnumWindows(EnumProc, ref searchData); 

     var firstResult = searchData.Result.FirstOrDefault(); 
     if (firstResult != IntPtr.Zero) 
     { 
      SetForegroundWindow(firstResult); 
     } 
    } 
} 
+0

Спасибо, что это сработало –

2

ли вам прочитайте руководство, применимы ли следующие меры:

Процесс имеет связанное с ним главное окно, только если процесс имеет графический интерфейс. Если связанный процесс не имеет главного окна (так что MainWindowHandle равен нулю), MainWindowTitle - это пустая строка (""). Если вы только что запустили процесс и хотите использовать его заголовок главного окна, подумайте об использовании метода WaitForInputIdle, чтобы процесс завершился, и убедитесь, что был создан дескриптор главного окна. В противном случае система выдает исключение.

+0

Вопрос отредактирован –

0

Если вы сбрасываете их все, используя GetProcesses(), похоже, что заголовок окна будет иметь «Adobe Reader» с префиксом имени PDF, если он открыт. Таким образом, вам может понадобиться сделать это и вместо этого перейти к массиву.

Например, если у меня есть UserManual.pdf открытым и я бегу код ниже отображает UserManual.pdf - Adobe Reader на консоли:

 Process[] p = Process.GetProcesses(); 
     String Title = String.Empty; 
     for (var i = 0; i < p.Length; i++) 
     { 
      Title = p[i].MainWindowTitle; 

      if (Title.Contains(@"Adobe")) 
       Console.WriteLine(Title); 
     } 
+0

Да, файл открыт, но это не работает. Я могу видеть только «Acrobat». И в пределах цикла foreach с использованием свойства MainWindowTitle я не вижу имя pdf. –