当MainWindowHandle为0时,将窗口置于前台

时间:2017-07-12 01:17:08

标签: excel powershell winapi user32

如果MainWindowHandle不是0,则以下代码将窗口置于前台。

如何将窗口带到MainWindowHandle = 0?

的前面

这适用于Microsoft Excel - 兼容性检查器窗口,该窗口显示GUI但在任务栏中没有图标且MainWindowHandle = 0。

我没有其他Excel运行实例。

Add-Type @"
  using System;
  using System.Runtime.InteropServices;
  public class Tricks {
     [DllImport("user32.dll")]
     [return: MarshalAs(UnmanagedType.Bool)]
     public static extern bool SetForegroundWindow(IntPtr hWnd);
  }
"@

$excel = (Get-Process | Where-Object { $_.ProcessName -eq 'EXCEL' }).MainWindowHandle
[void] [Tricks]::SetForegroundWindow($excel)

在Windows任务管理器中,我可以右键单击“Microsoft Excel - 兼容性检查器”,然后单击“置于前面”,这样就可以了。我如何在Powershell中模仿这个功能?

1 个答案:

答案 0 :(得分:2)

感谢IInspectable指出我正确的方向。

此代码获取真正的MainWindowHandle值:

$TypeDef2 = @"

using System;
using System.Text;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace Api
{

public class WinStruct
{
   public string WinTitle {get; set; }
   public int MainWindowHandle { get; set; }
}

public class ApiDef
{
   private delegate bool CallBackPtr(int hwnd, int lParam);
   private static CallBackPtr callBackPtr = Callback;
   private static List<WinStruct> _WinStructList = new List<WinStruct>();

   [DllImport("User32.dll")]
   [return: MarshalAs(UnmanagedType.Bool)]
   private static extern bool EnumWindows(CallBackPtr lpEnumFunc, IntPtr lParam);

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

   private static bool Callback(int hWnd, int lparam)
   {
       StringBuilder sb = new StringBuilder(256);
       int res = GetWindowText((IntPtr)hWnd, sb, 256);
      _WinStructList.Add(new WinStruct { MainWindowHandle = hWnd, WinTitle = sb.ToString() });
       return true;
   }  

   public static List<WinStruct> GetWindows()
   {
      _WinStructList = new List<WinStruct>();
      EnumWindows(callBackPtr, IntPtr.Zero);
      return _WinStructList;
   }

}
}
"@

Add-Type -TypeDefinition $TypeDef2 -Language CSharpVersion3

$excelInstance = [Api.Apidef]::GetWindows() | Where-Object { $_.WinTitle.ToUpper() -eq "Microsoft Excel - Compatibility Checker".ToUpper() }

所以现在使用这个正确的值,我可以调用SetForegroundWindow()函数:

Add-Type @"
  using System;
  using System.Runtime.InteropServices;
  public class Tricks {
     [DllImport("user32.dll")]
     [return: MarshalAs(UnmanagedType.Bool)]
     public static extern bool SetForegroundWindow(IntPtr hWnd);
  }
"@
[void] [Tricks]::SetForegroundWindow($excelInstance.MainWindowHandle)

我在website上写了一篇详细的博客。

我在GitHub上提供了一个关于如何创建Excel文件,编辑它并在不同的线程中运行上述代码的完整示例,因为Excel弹出窗口阻塞了主线程。