Monday, December 31, 2012

Place Outlook Reminders as top window using PowerShell

Place Outlook Reminders as top window using PowerShell

NOTE: In order for this to work.
        1. It should be in a powershell window and it should not be closed.
        2. Must be run with Admin Privledges.
(For information about WmiEvents read this great site:http://www.ravichaganti.com/blog/?p=1509)
#There are 2 parts to this program. 1. Set up the triggers for when outlook gets opened in the future.
#                                   2. Set up the triggers when outlook is already opened.
try{
#Connect reciever if Outlook is not yet open#
#Create a Trigger which will execute code when a program called 'OUTLOOK.EXE' starts#
Register-WmiEvent -Query "Select * from Win32_ProcessStartTrace WHERE ProcessName='OUTLOOK.EXE'"   `
                  -SourceIdentifier "OutlookProcess"                                               `
                  -Action {     #Get the process ID which is assigned to the Outlook program
                                $ProcessID = $Event.SourceEventArgs.NewEvent.ProcessID;
                                #Create a Trigger which will execute when Outlook starts a new thread#
                                Register-WmiEvent -Query "Select * from Win32_ThreadStartTrace WHERE ProcessID=$ProcessID"   `
                                                  -SourceIdentifier "OutlookThread"                                          `
                                                  -Action {      #Get the threads parent process (The window that started this thread) so we can see if the title on the window has labeled with "Reminder" in it.
                                                                 $ThreadsParentProcess = Get-Process -id $($Event.SourceEventArgs.NewEvent.ProcessID);      
                                                                 if($ThreadsParentProcess.MainWindowTitle.Contains("Reminder")) {
#Expose this C++ method that puts a specified window as the top most window using C# code                                                                
Add-Type @"
  using System;
  using System.Runtime.InteropServices;
  public class WindowStatus {
     static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
     const UInt32 SWP_NOSIZE = 0x0001;
     const UInt32 SWP_NOMOVE = 0x0002;
     const UInt32 TOPMOST_FLAGS = SWP_NOMOVE | SWP_NOSIZE;
     [DllImport("user32.dll")]
     [return: MarshalAs(UnmanagedType.Bool)]
     public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
     public static void OnTop(IntPtr hWnd) {
            SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS);
     }
  }
"@;                    
                                                                      #Call the C# Method that we created in the above statement to place this threads parent process as the top most window.
                                                                      [WindowStatus]::OnTop( $ThreadsParentProcess.MainWindowHandle);
                                                                 }
                                                                 #Remove(Dispose) the $ThreadsParentProcess variable from memory#
                                                                 $ThreadsParentProcess.Dispose();
                                                          }
                                #Force garbage collection to run to make double sure that we have no residue in memorey#
                                [GC]::Collect();
                                #Create a Trigger which will execute when Outlook is closed to remove the triggers we created#
                                Register-WmiEvent -Query "Select * from Win32_ProcessStopTrace WHERE ProcessID=$ProcessID"   `
                                                  -Action {     Unregister-Event -SourceIdentifier "OutlookThread" ; }
                           }
}                          
catch{}                      

#Connect reciever if Outlook is already open#
try{ $ProcessID = $(Get-Process |?{$_.Name -eq "OUTLOOK" } |select Id).Id }
catch{}
if($ProcessID -gt 0) {
                                #Create a Trigger which will execute when Outlook starts a new thread#
                                Register-WmiEvent -Query "Select * from Win32_ThreadStartTrace WHERE ProcessID=$ProcessID"   `
                                                  -SourceIdentifier "OutlookThread"                                          `
                                                  -Action {      #Get the threads parent process (The window that started this thread) so we can see if the title on the window has labeled with "Reminder" in it.
                                                                 $ThreadsParentProcess = Get-Process -id $($Event.SourceEventArgs.NewEvent.ProcessID);      
                                                                 if($ThreadsParentProcess.MainWindowTitle.Contains("Reminder")) {
#In order to expose this C++ method that puts any specified window as the top most window we have to use C# code                                                                 
Add-Type @"
  using System;
  using System.Runtime.InteropServices;
  public class WindowStatus {
     static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
     const UInt32 SWP_NOSIZE = 0x0001;
     const UInt32 SWP_NOMOVE = 0x0002;
     const UInt32 TOPMOST_FLAGS = SWP_NOMOVE | SWP_NOSIZE;
     [DllImport("user32.dll")]
     [return: MarshalAs(UnmanagedType.Bool)]
     public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
    public static void OnTop(IntPtr hWnd) {
            SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS);
     }
  }
"@;                    
                                                                      #Call the C# Method that we created in the above statement to place this threads parent process as the top most window.
                                                                      [WindowStatus]::OnTop( $ThreadsParentProcess.MainWindowHandle);
                                                                 }
                                                                 #Remove(Dispose) the $ThreadsParentProcess variable from memory#
                                                                 $ThreadsParentProcess.Dispose();
                                                          }
                                #Force garbage collection to run to make double sure that we have no residue in memorey#
                                [GC]::Collect();
                                #Create a Trigger which will execute when Outlook is closed to remove the triggers we created#
                                Register-WmiEvent -Query "Select * from Win32_ProcessStopTrace WHERE ProcessID=$ProcessID"   `
                                                  -Action {     Unregister-Event -SourceIdentifier "OutlookThread" ; }
   
}

No comments:

Post a Comment