检测Internet Explorer进程是否正在运行Flash Player

问题描述:

好的,这里有一点点100万美元的问题。我正在开发一个应用程序,用于检查您的任何浏览器是否正在运行Flash应用程序。这是我的核心机实现:检测Internet Explorer进程是否正在运行Flash Player

// Using CreateToolhelp32Snapshot allows to list all the modules loaded by a specific process. 
internal static Boolean ProcessContainsModule(Process process, String moduleMask) 
{ 
    IntPtr snapshotHandle; 

    if (Environment.Is64BitProcess) 
     snapshotHandle = CreateToolhelp32Snapshot((SnapshotFlags.Module | SnapshotFlags.Module32), (UInt32)process.Id); 
    else 
     snapshotHandle = CreateToolhelp32Snapshot(SnapshotFlags.Module, (UInt32)process.Id); 

    if (snapshotHandle == IntPtr.Zero) 
     return false; 

    Boolean result = false; 

    ModuleEntry entry = new ModuleEntry(); 
    entry.Size = ModuleEntry.SizeOf; 

    if (Module32First(snapshotHandle, ref entry)) 
    { 
     do 
     { 
      if (entry.ModuleName.FitsMask(moduleMask)) 
      { 
       result = true; 
       break; 
      } 

      entry = new ModuleEntry(); 
      entry.Size = ModuleEntry.SizeOf; 
     } 
     while (Module32Next(snapshotHandle, ref entry)); 
    } 

    CloseHandle(snapshotHandle); 

    return result; 
} 

// This is a simple wildcard matching implementation. 
public static Boolean FitsMask(this String value, String mask) 
{ 
    Regex regex; 

    if (!s_MaskRegexes.TryGetValue(mask, out regex)) 
     s_MaskRegexes[mask] = regex = new Regex(String.Concat('^', Regex.Escape(mask.Replace(".", "__DOT__").Replace("*", "__STAR__").Replace("?", "__QM__")).Replace("__DOT__", "[.]").Replace("__STAR__", ".*").Replace("__QM__", "."), '$'), RegexOptions.IgnoreCase); 

    return regex.IsMatch(value); 
} 

现在,Process Explorer是我的过程勘探中非常有用的。

与Chrome的检测,这是非常简单的:

if ((process.ProcessName == "chrome") && NativeMethods.ProcessContainsModule(process, "PepFlashPlayer.dll")) 

使用Firefox Detecthing这也很简单:

if ((process.ProcessName.StartsWith("FlashPlayerPlugin")) && NativeMethods.ProcessContainsModule(process, "NPSWF32*")) 

像往常一样,一切,当你正在寻找在Internet Explorer的变化。任何关于如何使用微软浏览器检测的线索?

确定我发现:

if ((process.ProcessName == "iexplore") && NativeMethods.ProcessContainsModule(process, "Flash32*")) 
+0

哥们,对于ProcessContainsModule代码是刚上的第一篇文章。 – 2016-11-25 20:26:31

+0

哎呀,我的错。有趣的选择命名空间名称然后 – MickyD 2016-11-25 23:07:27

我已经Zarathos修改了代码,使之能编译,以及一些个人风格。

TL;博士:这适用于Firefox的,有时为Chrome,而不是在所有的IE

首先,这里的基本代码:

using System; 
using System.Linq; 
using System.Runtime.InteropServices; 
using System.Diagnostics; 

#region pinvoke.net boilerplate 

[Flags] 
private enum SnapshotFlags : uint 
{ 
    HeapList = 0x00000001, 
    Process = 0x00000002, 
    Thread = 0x00000004, 
    Module = 0x00000008, 
    Module32 = 0x00000010, 
    Inherit = 0x80000000, 
    All = 0x0000001F, 
    NoHeaps = 0x40000000 
} 

private struct MODULEENTRY32 
{ 
    private const int MAX_PATH = 255; 
    internal uint dwSize; 
    internal uint th32ModuleID; 
    internal uint th32ProcessID; 
    internal uint GlblcntUsage; 
    internal uint ProccntUsage; 
    internal IntPtr modBaseAddr; 
    internal uint modBaseSize; 
    internal IntPtr hModule; 
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH + 1)] 
    internal string szModule; 
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH + 5)] 
    internal string szExePath; 
} 

[DllImport("kernel32", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] 
static extern IntPtr CreateToolhelp32Snapshot([In]UInt32 dwFlags, [In]UInt32 th32ProcessID); 

[DllImport("kernel32", SetLastError = true)] 
[return: MarshalAs(UnmanagedType.Bool)] 
private static extern bool CloseHandle([In] IntPtr hObject); 

[DllImport("kernel32.dll")] 
static extern bool Module32First(IntPtr hSnapshot, ref MODULEENTRY32 lpme); 

[DllImport("kernel32.dll")] 
static extern bool Module32Next(IntPtr hSnapshot, ref MODULEENTRY32 lpme); 

#endregion 

static bool ProcessContainsModule(Process process, string searchTerm) 
{ 
    bool result = false; 

    //get handle to process 
    IntPtr snapshotHandle = Environment.Is64BitProcess ? 
     CreateToolhelp32Snapshot((UInt32)(SnapshotFlags.Module | SnapshotFlags.Module32), (UInt32)process.Id) : 
     CreateToolhelp32Snapshot((UInt32)SnapshotFlags.Module, (UInt32)process.Id); 
    if (snapshotHandle == IntPtr.Zero) 
    { 
     return result; 
    } 

    //walk the module list 
    try 
    { 
     MODULEENTRY32 entry = new MODULEENTRY32() { dwSize = (uint)Marshal.SizeOf(typeof(MODULEENTRY32)) }; 

     if (Module32First(snapshotHandle, ref entry)) 
     { 
      do 
      { 
       if (entry.szModule.IndexOf(searchTerm, StringComparison.OrdinalIgnoreCase) >= 0) 
       { 
        result = true; 
        break; 
       } 

       entry = new MODULEENTRY32() { dwSize = (uint)Marshal.SizeOf(typeof(MODULEENTRY32)) }; 
      } 
      while (Module32Next(snapshotHandle, ref entry)); 
     } 

     return result; 
    } 
    finally 
    { 
     CloseHandle(snapshotHandle); 
    } 
} 

您可以使用它像这样:

static bool IsFlashLoadedInFirefox() 
{ 
    return Process.GetProcessesByName("plugin-container").Any(x => ProcessContainsModule(x, "NPSWF")); 
} 

static bool IsFlashLoadedInInternetExplorer() 
{ 
    //This doesn't work. For some reason can't get modules from child processes 
    return Process.GetProcessesByName("iexplore").Any(x => ProcessContainsModule(x, "Flash32")); 
} 

static bool IsFlashLoadedInChrome() 
{ 
    //Doesn't work reliably. See description. 
    return Process.GetProcessesByName("chrome").Any(x => ProcessContainsModule(x, "pepflashplayer")); 
} 

正如在评论中指出,只有火狐似乎可靠地工作。在IE(IE11)的情况下,Module32First()出于某种原因失败。在Chrome中的情况下,事情变得更有趣一些:

  • 如果一个新的标签导航到youtube.com或YouTube视频代码工作
  • 如果一个新的选项卡浏览到播放列表但是,在YouTube上,代码失败,因为pepFlashPlayer.dll不在该进程的模块列表中(使用ProcessExplorer进行检查)。而且,如果您继续浏览其他非播放列表的YouTube视频,它仍然不会显示。

请注意,这种检查进程加载的DLL的方法非常脆弱,如果任何浏览器决定更改加载的DLL或加载的DLL,那么代码会中断。

参考文献:

  1. http://pinvoke.net/default.aspx/kernel32.createtoolhelp32snapshot
  2. http://pinvoke.net/default.aspx/kernel32/Module32First.html
  3. http://pinvoke.net/default.aspx/kernel32/Module32Next.html