none
Set Internet Explorer Always on Top (Set-TopMost) with Powershell RRS feed

  • Question

  • Hello, dear colleagues.

    I need your help to set Internet Explorer always on top with Powershell.

    I tried to use this powershell script to set on top using Set-TopMost function from here: click.

    Tried with notepad, mstsc - works perfectly.

    Start-Process "C:\Windows\System32\Notepad.exe"
    Start-Sleep -s 5
    Set-TopMost (get-process notepad).MainWindowHandle

    But with Internet Explorer such a way does not work. Maybe because Internet Explorer create two Threads (even with only one tab open). 

    Tried to use this article to find out PID of Internet Explorer instead of process name and place into Set-TopMost function. 

    Set-TopMost (get-process -id $p).MainWindowHandle

    Unfortunately, no result.

    Can you help me in this case?

    Thanks. Have a nice day.

    P.S. Here is full listing. My comments begins from line 43 (colored in brown) 

    $sig = @"
    [DllImport("user32.dll", SetLastError=true)]
    public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
    
    [DllImport("user32.dll")]
    public static extern IntPtr GetTopWindow(IntPtr hWnd);
    
    [DllImport("user32.dll", SetLastError = true)]
    public static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);
    
    public enum GetWindow_Cmd : uint {
        GW_HWNDFIRST = 0,
        GW_HWNDLAST = 1,
        GW_HWNDNEXT = 2,
        GW_HWNDPREV = 3,
        GW_OWNER = 4,
        GW_CHILD = 5,
        GW_ENABLEDPOPUP = 6
    }
    
    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
    
    [DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)]
    public static extern int GetWindowTextLength(IntPtr hWnd);
    "@
    Add-Type -MemberDefinition $sig -Namespace User32 -Name Util -UsingNamespace System.Text
    
    $iethreads = get-process iexplore |?{!$_.MainWindowTitle} |%{$_.ID}
    
    $p=0
    $window = [User32.Util]::GetTopWindow(0)
    
    while ($window -ne 0) {
        [User32.util]::GetWindowThreadProcessId($window, [ref]$p) |out-null
        if ($iethreads -contains $p) {
            $length = [User32.Util]::GetWindowTextLength($window)
            if ($length -gt 0) {
                $string = New-Object System.Text.Stringbuilder 1024
                [User32.Util]::GetWindowText($window,$string,($length+1)) |out-null
                if ($string.tostring() -notmatch '^MSCTFIME UI$|^Default IME$|^SysFader$|^MCI command handling window$') {
                    new-object psobject -Property @{PID = $p;Title = $string.tostring()}
                    ###########################################################
                    #Here I try to set Internet Explorer always on top.
                    Set-TopMost (get-process -id $p).MainWindowHandle
                    #Also tried this to use process name instead of PID. No luck. Maybe because Internet Explorer create two Threads (even with only one tab open).
                    #I use Start-Process if IE was not previously runned.
                    #Without Start-Sleep does not work for a specific reason. 
                    #Start-Process "C:\Program Files (x86)\Internet Explorer\iexplore.exe"
                    #Start-Sleep -s 5
                    #Set-TopMost (get-process iexplore).MainWindowHandle
                    ###########################################################
                               
                }
            }
        }
        $window = [User32.Util]::GetWindow($window, 2)
    }
    
    $app = Add-Type -MemberDefinition $signature -Name Win32Window -Namespace ScriptFanatic.WinAPI -ReferencedAssemblies System.Windows.Forms -Using System.Windows.Forms -PassThru
     
    function Set-TopMost
    {
            param(         
                    [Parameter(
                            Position=0,ValueFromPipelineByPropertyName=$true
                    )][Alias('MainWindowHandle')]$hWnd=0,
     
                    [Parameter()][switch]$Disable
     
            )
     
           
            if($hWnd -ne 0)
            {
                    if($Disable)
                    {
                            Write-Verbose "Set process handle :$hWnd to NORMAL state"
                            $null = $app::MakeNormal($hWnd)
                            return
                    }
                   
                    Write-Verbose "Set process handle :$hWnd to TOPMOST state"
                    $null = $app::MakeTopMost($hWnd)
            }
            else
            {
                    Write-Verbose "$hWnd is 0"
            }
    }



    • Edited by fapw Monday, November 24, 2014 3:26 PM add listing
    Monday, November 24, 2014 3:02 PM

Answers

All replies

  • I've always used the Visual Basic AppActivate to bring to front myself.  The function I use is :

    function Set-Focus($name){
    
    [void] [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.VisualBasic")
    $a = Get-Process | Where-Object {$_.Name -eq "$name"}
    [Microsoft.VisualBasic.Interaction]::AppActivate($a.ID)
    
    }

    Though as you can see, you can have multiple iexplore.exe processes open.  Instead I recommend something like getting window title and then getting the PID of that window title you're looking for.  Here's some details on that : http://blogs.technet.com/b/heyscriptingguy/archive/2007/02/03/how-can-i-use-windows-powershell-to-get-a-list-of-all-the-open-windows-on-a-computer.aspx

    $myprocess = Get-Process | Where-Object {$_.MainWindowTitle -eq "My Custom IE Window"} 
    
    $myprocess.id = #this is your IE process ID. 

    But I would go a step further and say if you're looking at just keeping IE open, look into Windows 8 Kiosk mode.  You can configure 1 application sandboxed and it always stays up.  Otherwise you'll need to take the above code a step further and implement something to say "do this constantly".  You can find do while information here : http://blogs.technet.com/b/heyscriptingguy/archive/2009/04/29/how-can-i-use-the-do-while-loop-in-windows-powershell.aspx  .  Hope this helps.  Good luck.

    Ryan

    • Marked as answer by fapw Tuesday, November 25, 2014 1:34 PM
    Monday, November 24, 2014 3:27 PM
  • I think you are prevented from doing so from security reasons, because this is what malware programs do.

    -- Bill Stewart [Bill_Stewart]

    Monday, November 24, 2014 3:33 PM
    Moderator
  • Or this is a possibility... :)
    Monday, November 24, 2014 3:39 PM
  • I think you are prevented from doing so from security reasons, because this is what malware programs do.

    -- Bill Stewart [Bill_Stewart]

    Omg, nay, I need to implement it in corporate environment.

    The idea - there is specific IE page, that always on top with corporate info and button - connect to remote desktop server. Why I'm trying to bring IE on top - because not to run explorer.exe is not suitable for us for a specific reason.

    Monday, November 24, 2014 3:51 PM
  • If iexplore.exe ignores "always on top," then you're not going to be able to bypass it except by perhaps a third party solution of some kind. I wouldn't be surprised if this were the case because this is common malware behavior.

    -- Bill Stewart [Bill_Stewart]

    Monday, November 24, 2014 3:57 PM
    Moderator
  • http://en.kioskea.net/faq/636-how-to-use-kiosk-mode-with-internet-explorer

    It is how we do now - we are starting IE in kiosk mode instead of starting explorer.exe (by modifying winlogon hive in registry).

    But for a specific reasons we need to return back explorer.exe, additionally run IE and bring it to the top (to hide desktop). 

    The idea, whatever user do  - IE stays always on top and all actions not visible for user, because displayed below IE. 

     



    • Edited by fapw Monday, November 24, 2014 4:16 PM
    Monday, November 24, 2014 4:10 PM
  • Sorry, but I don't understand your latest message. It may be that there is no way to do what you want.

    -- Bill Stewart [Bill_Stewart]

    Monday, November 24, 2014 4:22 PM
    Moderator
  • So I would have explorer continue running and instead of modifying the shell key, have it run IE first in kiosk mode on boot.  That way explorer will still run in the background and allow for other app processes to continue.  Modifying the shell key otherwise will leave only the app you call running.
    Monday, November 24, 2014 4:23 PM
  • I've always used the Visual Basic AppActivate to bring to front myself.  The function I use is :

    function Set-Focus($name){
    
    [void] [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.VisualBasic")
    $a = Get-Process | Where-Object {$_.Name -eq "$name"}
    [Microsoft.VisualBasic.Interaction]::AppActivate($a.ID)
    
    }

    Though as you can see, you can have multiple iexplore.exe processes open.  Instead I recommend something like getting window title and then getting the PID of that window title you're looking for.  Here's some details on that : http://blogs.technet.com/b/heyscriptingguy/archive/2007/02/03/how-can-i-use-windows-powershell-to-get-a-list-of-all-the-open-windows-on-a-computer.aspx

    $myprocess = Get-Process | Where-Object {$_.MainWindowTitle -eq "My Custom IE Window"} 
    
    $myprocess.id = #this is your IE process ID. 

    But I would go a step further and say if you're looking at just keeping IE open, look into Windows 8 Kiosk mode.  You can configure 1 application sandboxed and it always stays up.  Otherwise you'll need to take the above code a step further and implement something to say "do this constantly".  You can find do while information here : http://blogs.technet.com/b/heyscriptingguy/archive/2009/04/29/how-can-i-use-the-do-while-loop-in-windows-powershell.aspx  .  Hope this helps.  Good luck.

    Ryan

    If to use PID of IE (instead of process name) - Function Set-Focus($name) brings IE to the front (superb), but it's, unfortunately, not set IE always on top.

    Thanks.


    • Edited by fapw Monday, November 24, 2014 4:35 PM
    Monday, November 24, 2014 4:33 PM
  • You cannot lock a window to the top.  You can bring it to the top but it can be overrun by almost any window wanting attention or getting attention.

    ¯\_(ツ)_/¯

    Monday, November 24, 2014 4:34 PM
  • Sorry, but I don't understand your latest message. It may be that there is no way to do what you want.

    -- Bill Stewart [Bill_Stewart]

    Now we are not starting explorer.exe (Shell = "C:\Program Files\Internet Explorer\iexplore -k -extoff http://example.com/"). Only IE page is started without desktop. 

    But now we should to return back (Shell ="explorer.exe"). This way desktop will be loaded, and IE page too, but if user press Win key (start menu appears above IE page), Win+R - notepad and etc. this actions will be displayed above IE page. I'm trying to make IE page be always on top to prevent such situations. 

    Now, I think, you understand what I mean.


    • Edited by fapw Monday, November 24, 2014 4:49 PM
    Monday, November 24, 2014 4:48 PM
  • Sorry, but I don't understand your latest message. It may be that there is no way to do what you want.


    -- Bill Stewart [Bill_Stewart]

    Now we are not starting explorer.exe (Shell = "C:\Program Files\Internet Explorer\iexplore -k -extoff http://example.com/"). Only IE page is started without desktop. 

    But now we should to return back (Shell ="explorer.exe"). This way desktop will be loaded, and IE page too, but if user press Win key (start menu appears above IE page), Win+R - notepad and etc. this actions will be displayed above IE page. I'm trying to make IE page be always on top to prevent such situations. 

    Now, I think, you understand what I mean.


    The best way to do that is to unplug the keyboard. 

    You cannot do what you want with scripting.


    ¯\_(ツ)_/¯

    Monday, November 24, 2014 4:51 PM

  • The best way to do that is to unplug the keyboard. 

    You cannot do what you want with scripting.


    ¯\_(ツ)_/¯

    Ahahah, best advice, jrv))


    • Edited by fapw Monday, November 24, 2014 5:03 PM
    Monday, November 24, 2014 5:03 PM
  • To resume, there is two ways:

    1). To make constant loop to bring IE to the front;

    2). Just remove all links from desktop with gp (article), disable WIN key (article), autohide taskbar (article), disable all third-party autorun programs. There result will be almost the same, if do not run explorer.exe

    • Edited by fapw Tuesday, November 25, 2014 1:45 PM
    Tuesday, November 25, 2014 1:44 PM
  • Tuesday, November 25, 2014 1:46 PM
    Moderator
  • I love going to Kiosks and subverting all of these great ideas.  They don't work and most of us know that.

    Windows desktop versions can be set in kiosk mode.  In that mode you can set IE to be the ONLY application in the system.  It will be fullscreen with no chrome and now one can remove and no Windows can be on top of it.  You can set any propram to be the kiosk mode shell.

    Search for "Windows kiosk mode"


    ¯\_(ツ)_/¯

    Tuesday, November 25, 2014 1:51 PM
  • I love going to Kiosks and subverting all of these great ideas.  They don't work and most of us know that.

    Windows desktop versions can be set in kiosk mode.  In that mode you can set IE to be the ONLY application in the system.  It will be fullscreen with no chrome and now one can remove and no Windows can be on top of it.  You can set any propram to be the kiosk mode shell.

    Search for "Windows kiosk mode"


    ¯\_(ツ)_/¯

    jrv, if you mean to use third-party shell or run "iexplore - k http://example.com/" instead of "explorer.exe", it's not suitable for us. Main condition - to run explorer.exe. That's your idea? OS - Windows 7.


    • Edited by fapw Tuesday, November 25, 2014 2:06 PM
    Tuesday, November 25, 2014 2:04 PM
  • Where did I post anything about a third party shell.  I posted that what you are asking for is how to run Windows in "kiosk" mode.  You just don't know what "kiosk" means in Windows.  It is a part of Windows and has been since NT 4 although I don't think it was called that until W2K.


    ¯\_(ツ)_/¯

    Tuesday, November 25, 2014 3:43 PM
  • What it sounds like he's doing is instead of having a run command of iexplore, he's replaced the shell key with iexplore -k and now needs explorer for multitasking another app. He needs to create a run key for the internet explorer window he wants up and to leave the shell key alone :)
    Tuesday, November 25, 2014 3:48 PM
  • iexplore -k places Internet Explorer into 'kiosk" mode however it does not place the Windows session into "kiosk" mode.  That has to be done in a different way.

    With the IEAK and the SDk we can orchestrate IE in any way we need including changing tabs.  Each tab will be full scree and appear to be a completely separate full screen IE display.


    ¯\_(ツ)_/¯

    Tuesday, November 25, 2014 4:25 PM