Sunday, April 20, 2014

Function Update-ImageColor{

[CmdletBinding()]

Param( [Parameter(Mandatory=$True,Position=1)] [string]$CurrentFileName,

[Parameter(Mandatory=$True,Position=1)] [string]$NewFileName,

[System.Drawing.Color]$newColor = [System.Drawing.Color]::Black,

[int]$MinCombined = -1,

[int]$MaxCombined = 800,

[int]$MaxRed = 400,

[int]$MaxGreen = 400,

[int]$MaxBlue = 400,

[int]$MinRed = -1,

[int]$MinGreen = -1,

[int]$MinBlue = -1,

[int]$Width=0,

[int]$height=0,

[int]$WidthStartPosition=0,

[int]$heighttartPosition=0,

[int]$ZoomFactor=1)

try {

$scrBitmap = [System.Drawing.Bitmap]($CurrentFileName)

$ActualColor = New-Object System.Drawing.Color

#make an empty bitmap the same size as scrBitmap

if($Width -eq 0){$Width = $scrBitmap.Width}

if($height -eq 0){$height = $scrBitmap.Height}

$newBitmap = new-object System.Drawing.Bitmap $Width, $height

for ($i = 0; $i -lt $newBitmap.Width; $i++) {

for ($j = 0; $j -lt $newBitmap.Height; $j++) {

#get the pixel from the scrBitmap image

$actulaColor = $scrBitmap.GetPixel($i+$WidthStartPosition, $j+$heighttartPosition);

if(($actulaColor.R -gt $MaxRed -or $actulaColor.R -lt $MinRed) -or

($actulaColor.G -gt $MaxGreen -or $actulaColor.G -lt $MinGreen) -or

($actulaColor.B -gt $MaxBlue -or $actulaColor.B -lt $MinBlue) -or

($actulaColor.R + $actulaColor.G + $actulaColor.B) -lt $MinCombined -or

($actulaColor.R + $actulaColor.G + $actulaColor.B) -gt $MaxCombined){

$newBitmap.SetPixel($i, $j, $newColor)



}

else {

$newBitmap.SetPixel($i, $j, $actulaColor)



}

}

}

Remove-Item $NewFileName -Force -ErrorAction SilentlyContinue

#Size newSize = new Size((int)(originalBitmap.Width * zoomFactor), (int)(originalBitmap.Height * zoomFactor));

#Bitmap bmp = new Bitmap(originalBitmap, newSize);

$newBitmap.Save($NewFileName,[System.Drawing.Imaging.ImageFormat]::Jpeg)

$newBitmap.Dispose()

$scrBitmap.Dispose()

return "$NewFileName : Conversion Complete."



}

catch [Net.WebException] {

return $_.Exception



}

}


PowerShell function to display RGB parts for a pixel

#Here is an example how to call the powershell function which displays a window with any image. 
#When you click on a pixel in the image it displays the parts of Red, Green and Blue for that pixel.  #You can use this to help identify which color spectrums you want to remove or update when cleaning up images for OCR'ing your images.
#get-ImagePixelColor "$home\Pictures\PayStubSinglePage.jpg"
 
Function get-ImagePixelColor{
    [CmdletBinding()]
    Param(  [Parameter(Mandatory=$True,Position=1)] [string]$FileName)

    [void][reflection.assembly]::LoadWithPartialName("System.Windows.Forms")
    $file = (get-item $FileName)
    $img = [System.Drawing.Image]::Fromfile($file);
 
    $form = new-object Windows.Forms.Form
    $form.Text = "Display Image"
    $form.Width = [System.Windows.Forms.Screen]::PrimaryScreen.WorkingArea.Width-50;
    $form.Height = [System.Windows.Forms.Screen]::PrimaryScreen.WorkingArea.Height-50;

    $panel = New-Object System.Windows.Forms.Panel
    $panel.Height =  $form.Height-50;
    $panel.Width = $form.Width-200;
    $panel.AutoScroll = $true

    function createLabel {
      Param(  [Parameter(Mandatory=$True)] [int]$Top,
              [Parameter(Mandatory=$True)] [System.Drawing.Color]$BackColor)     
        $lbl = New-Object System.Windows.Forms.Label
        $lbl.Height = 50
        $lbl.Width = 100
        $lbl.Left = $form.Width-150;
        $lbl.Top = $top;
        $lbl.Text = ""
        $lbl.BackColor = $BackColor
        $font = New-Object System.Drawing.Font([System.Drawing.FontFamily]::GenericSansSerif, 24)
        $lbl.Font = $font    
        return $lbl
    }
    $lblBlue = createLabel 50 $([System.Drawing.Color]::Blue)
    $lblRed  = createLabel 125 $([System.Drawing.Color]::Red)
    $lblGreen = createLabel 200 $([System.Drawing.Color]::Green)

    #Mouse click event for pictureBox
    function pictureBox_MouseClick($Sender, $EventArgs)
    { 
        $image = new-object System.Drawing.Bitmap $pictureBox.Image;
        $color = $image.GetPixel($EventArgs.X, $EventArgs.Y);
        $lblBlue.Text = $color.B
        $lblGreen.Text = $color.G
        $lblRed.Text = $color.R
    }
    $pictureBox = new-object Windows.Forms.PictureBox
    $pictureBox.SizeMode =  [System.Windows.Forms.PictureBoxSizeMode]::AutoSize;   
    $pictureBox.Image = $img;
    $pictureBox.add_MouseClick({pictureBox_MouseClick $this $_})

    $form.controls.add($lblBlue)
    $form.controls.add($lblRed)
    $form.controls.add($lblGreen)
    $form.controls.add($panel)
    $panel.controls.add($pictureBox)
    $form.Add_Shown( { $form.Activate() } )
    $form.ShowDialog()
}

PowerShell function to convert pdf to jpg using GhostScript

#Here is an example on how to call this function to convert pdf to jpg.
#convert-PdfToImage -OriginalFile "$home\Pictures\PayStubSinglePage.pdf" -NewFile "$home\Pictures\PayStubSinglePage.jpg"
 
Function convert-PdfToImage {
    [CmdletBinding()]
    Param(  [Parameter(Mandatory=$True)] [string]$OriginalFile,
            [Parameter(Mandatory=$True)] [string]$NewFile)

    #Path to your Ghostscript EXE
    $tool = 'C:\Users\Greg\Programming\GhostScript\bin\gswin64c.exe'
   
    #Directory containing the PDF files that will be converted
    $inputDir = $OriginalFile
 
    #Output path where the TIF files will be saved
    $outputDir = $NewFile
 
    $pdf = get-childitem $OriginalFile
    $jpg = $outputDir
    Remove-Item $jpg -Force -ErrorAction SilentlyContinue
    'Processing ' + $pdf.Name       

    $param = "-sOutputFile=$jpg"
    & $tool -q -dNOPAUSE -sDEVICE=jpeg $param -r1200 $pdf.FullName -c quit

    #& "$tool" "-q -dNOPAUSE -dNOPROMT -sDEVICE=jpeg $param -r1200 $pdf.FullName -dMaxBitmap=500000000 -dAlignToPixels=0 dGridFitTT=2 -sDEVICE=pngalpha -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -c quit"
    #& "$tool" "-q -dNOPAUSE -dQuiet -dSAFER -dNOPROMT -sDEVICE=jpeg $param -r1200 $pdf.FullName -c quit"
    #& "$tool -dNOPAUSE -sDEVICE=jpeg -sOutputFile=image%d.jpg -dJPEGQ=100 -r300x300 -q C:\Users\Greg\Pictures\PayStubSinglePage.pdf -c quit"
    #& "$tool" "-q -dBATCH -dNOPAUSE -sDEVICE=jpeg -r350 dJPEGQ=100 $pdf.FullName -sOutputFile=C:\Users\Greg\Pictures\PayStubSinglePage.jpg -c quit"
    #& "$tool" "- -q -dQuiet -dSAFER -dBATCH -dNOPAUSE -dNOPROMT -dMaxBitmap=500000000 -dAlignToPixels=0 dGridFitTT=2 -sDEVICE=pngalpha -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -sOutputFile=C:\Users\Greg\Pictures\PayStubSinglePage.jpg -f $pdf.FullName" 
}

Installation Script for GhostScript

#This script must be run with admin privledges
#This script downloads and installs ghostscript which is used to convert PDF files to images. 
$Date = [System.datetime]::now.ToString("yyyy-MM-dd")
$Junk = "$Home\Junk$Date"
if(!$(Test-Path $Junk)) { $void = New-Item -ItemType directory -Path $Junk }

#Create a programming folder in our Home directory if it doesn't exist.
$pgmDirectory = "$Home" + "\programming"
if(!$(Test-Path $pgmDirectory)) { $void = New-Item -ItemType directory -Path $pgmDirectory }

#If the TessNet language pack is not downloaded yet, download and extract it.
$gsDirectory = $pgmDirectory + "\GhostScript"
if(!$(Test-Path $gsDirectory)) {
    Write-Host "Downloading GhostScript"
    $webclient = New-Object System.Net.WebClient
    $file = "$Junk\gs914w64.exe"
    $webclient.DownloadFile($url,$file)
    Start-Sleep -Seconds 2
    Write-Host "Download complete, now installing GhostScript"

    & "$Junk\gs914w64.exe" "/S" "/NCRC" "/D=$gsDirectory"
    Start-Sleep -Seconds 2
    Write-Host "GhostScript is installed, now cleaning up downloaded files."

}
else {
    Write-Host "GhostScript has already been installed" 
}

Remove-Item $Junk -Force -Recurse -ErrorAction SilentlyContinue

<#
#Run this commented out section to uninstall GhostScript.  
#This uninstalled assummes that you have it installed in the same directories this script installed it to. 
$unstlDirectory = "$Home" + "\programming" + "\GhostScript"
& "$unstlDirectory\uninstgs.exe "  "/S" "/NCRC"
Remove-Item $unstlDirectory -Force -Recurse
#>

Thursday, July 18, 2013

PowerShell and RSS feeds

With google reader shutting down and with the crazy amount of rss feeds available I became curious about what an rss feed actually is.
I was amazed at how basic this whole rss feed process really is.  For instance to display the necessary xml from the latest technology news item on CBC you could run this command.
$([xml]$(New-Object System.Net.WebClient).DownloadString(“http://rss.cbc.ca/lineup/technology.xml”)).rss.channel.item[0]
This really is not formatted too nicely but it gives you the idea how easy it is to get rss feed data from online sources using powershell.

Using rss feeds I created comandlets to get a variety of information that is online. At the bottom of this post is a "Get-Weather" commandlet I added to my profile to easily display the weather forecast.

To get the weather for Houston Texas run:
Get-Weather -City Houston -Province Texas -Country US
For my current location I run:
Get-Weather

function Get-Weather {
[CmdletBinding()]
Param(  [String]$City = "Melville",
        [string]$Province = "Saskatchewan",
        [string]$Country = "Canada")
    
    if($City.Equals("Melville",[System.StringComparison]::InvariantCultureIgnoreCase) -and $Province.Equals("Saskatchewan",[System.StringComparison]::InvariantCultureIgnoreCase)) {
        $LocAbrev = "cask0200"
    }
    else {
        if($Country.Equals("US",[System.StringComparison]::InvariantCultureIgnoreCase)){$Country = "United-States"}
        [System.Reflection.Assembly]::LoadWithPartialName("System.web") | Out-Null
        $SiteUrl = “http://www.theweathernetwork.com/weather/$Country/$Province/$City”
        $Location = (New-Object System.Net.WebClient).DownloadString($SiteUrl)
        [string[]]$Test = '<script>window._uf={};window._uf.p='
        $LocAbrev = $Location.split($Test,[system.StringSplitOptions]::None)[1].split(';')[0].trim('"')
    }

    #Get The Weather From the Weather Networks RSSFeed
    [System.Reflection.Assembly]::LoadWithPartialName("System.web") | Out-Null
    $SiteUrl = “http://rss.theweathernetwork.com/weather/$LocAbrev”
    [xml]$weather = (New-Object System.Net.WebClient).DownloadString($SiteUrl)
    write-Host $weather.rss.channel.title
    foreach($Day in $weather.rss.channel.GetElementsByTagName("item")) {
       Write-Host "Date:       " $Day.title
       Write-Host "Description: " -NoNewline
       $counter = 0
       foreach($Desc in $Day.description.split(',') ) {
             if ($counter++ -ge 1) {Write-host "             " -NoNewline}
             if(![string]::IsNullOrWhiteSpace($Desc.Trim()) -and ![string]::IsNullOrEmpty($Desc.Trim())) {
                 [System.Web.HttpUtility]::HtmlDecode($Desc.Trim());
             
             }
       }
       Write-host ""
    }
} 

Saturday, May 18, 2013

Place Outlook Reminders as top window using C#


Place Outlook Reminders as top window using C#

This program subscribes to WMI events and therefore must be run as an admin account.  It can be added to scheduled jobs so it runs automatically.

It is created as a console application and hides its console window to run in the background.
Basically it watches for whenever Outlook kicks off a new thread and if the window heading has Reminder in it, it forces the window to be on top of all others.

using System;
using System.Management;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace OutlookReminder
{
    class Program
    {
        ManagementEventWatcher startThreadWatch;

        static void Main(string[] args)
        {
            //create a processwatcher that will watch for outlook programs that will be getting opened.
            ProcessWatcher processWatcher = new ProcessWatcher("OUTLOOK.EXE");
            //create a list of threadWatchers for each outlook program that is currently open, however...there really should only be one open at a time.
            List<ThreadsWatcher> threadsWatcher = Process.GetProcessesByName("OUTLOOK").ToList().Select(x => new ThreadsWatcher(x.Id)).ToList();
            
            //Hide this console window and let it live in the background.
            WindowControl.ShowWindow(Process.GetCurrentProcess().MainWindowHandle, (int)WindowControl.WindowState.Hide);
            Console.WriteLine("Press ENTER to stop the Outlook reminders to be forced as the top most window.");
            Console.ReadLine();

            //Dispose of the process watcher that is watching for the outlook program to get opened.
            processWatcher.Dispose();
            //Dispose of all the threads that are not null and not disposed of yet.
            threadsWatcher.Where(x => x != null && !x.disposed).ToList().ForEach(x => x.Dispose());
        }
    }
    #region watchers
    public class ProcessWatcher : IDisposable
    {
        ManagementEventWatcher startProcessWatch;
        ManagementEventWatcher stopProcessWatch;
        ThreadsWatcher threadWatcher;
        public string processName { get; private set; }
        public bool disposed { get; private set; }
        public ProcessWatcher(string _processName)
        {
            processName = _processName;
            disposed = false;
            startProcessWatch = new ManagementEventWatcher(new WqlEventQuery(string.Format("Select * from Win32_ProcessStartTrace WHERE ProcessName='{0}'", processName)));
            startProcessWatch.EventArrived += new EventArrivedEventHandler(startProcessWatch_EventArrived);
            startProcessWatch.Start();
            stopProcessWatch = new ManagementEventWatcher(new WqlEventQuery(string.Format("Select * from Win32_ProcessStopTrace WHERE ProcessName='{0}'", processName)));
            stopProcessWatch.EventArrived += new EventArrivedEventHandler(stopProcessWatch_EventArrived);
            stopProcessWatch.Start();
        }
        #region disposeAndFinalize
        ~ProcessWatcher()
        {
            if (startProcessWatch != null)
            {
                startProcessWatch.Stop();
            }
        }
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    startProcessWatch.Stop();
                    startProcessWatch.Dispose();
                    if (threadWatcher != null && !threadWatcher.disposed)
                    {
                        threadWatcher.Dispose();
                    }
                }
                disposed = true;
            }
        }
        #endregion disposeAndFinalize
        void stopProcessWatch_EventArrived(object sender, EventArrivedEventArgs e)
        {
            if (threadWatcher != null && !threadWatcher.disposed)
            {
                threadWatcher.Dispose();
            }
        }
        void startProcessWatch_EventArrived(object sender, EventArrivedEventArgs e)
        {
            int processID = 0;
            int.TryParse(e.NewEvent.Properties["ProcessID"].Value.ToString(), out processID);
            threadWatcher = new ThreadsWatcher(processID);
        }
    }
    public class ThreadsWatcher : IDisposable
    {
        ManagementEventWatcher startThreadWatch;
        public bool disposed { get; private set; }
        public int processID { get; private set; }
        #region constructors
        public ThreadsWatcher(int _processID)
        {
            disposed = false;
            processID = _processID;
            startThreadWatch = new ManagementEventWatcher(new WqlEventQuery("Select * from Win32_ThreadStartTrace WHERE ProcessID=" + processID));
            startThreadWatch.EventArrived += new EventArrivedEventHandler(startThreadWatch_EventArrived);
            startThreadWatch.Start();
        }
        #endregion constructors
        #region disposeAndFinalize
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    startThreadWatch.Stop();
                    startThreadWatch.Dispose();
                }
                disposed = true;
            }
        }
        ~ThreadsWatcher()
        {
            if (startThreadWatch != null)
            {
                startThreadWatch.Stop();
            }
        }
        #endregion disposeAndFinalize
        void startThreadWatch_EventArrived(object sender, EventArrivedEventArgs e)
        {
            int processID = 0;
            int.TryParse(e.NewEvent.Properties["ProcessID"].Value.ToString(), out processID);
            Process outlookProcess = Process.GetProcessById(processID);

            if (outlookProcess.MainWindowTitle.Contains("Reminder"))
            {
                //Place window as TopMost window.
                WindowControl.SetWindowPos(outlookProcess.MainWindowHandle, WindowControl.SpecialWindowHandles.TopMost, 0, 0, 0, 0, WindowControl.SetWindowPosFlags.TopMostFlag);

                //The next 2 commands are use to ensure that if the window is minimized it will still be maximized and displayed.
                //force the window as the foreground window.
                WindowControl.SetForegroundWindow(outlookProcess.MainWindowHandle);
                //Restore the window to be maximized 
                WindowControl.ShowWindow(outlookProcess.MainWindowHandle, (int)WindowControl.WindowState.Restore);
            }
            outlookProcess.Dispose();
        }
    }
    #endregion watchers
    static class WindowControl
    {
        #region WindowControlEnums
        //First few classes are defined to replace an enum however defining it this way we can load any type.
        public static class SpecialWindowHandles
        {
            public static IntPtr
            NoTopMost = new IntPtr(-2),
            TopMost = new IntPtr(-1),
            Top = new IntPtr(0),
            Bottom = new IntPtr(1);
        }
        public static class SetWindowPosFlags
        {
            public static readonly uint
            NoSize = 0x0001,
            NoMove = 0x0002,
            NoZOrder = 0x0004,
            NoRedraw = 0x0008,
            NoActivate = 0x0010,
            DrawFrame = 0x0020,
            FrameChanged = 0x0020,
            ShowsWindow = 0x0040,
            HideWindow = 0x0080,
            NoCopyBits = 0x0100,
            NoOwnerZOrder = 0x0200,
            NoRrPosition = 0x0200,
            NoSendChanging = 0x0400,
            DeferErase = 0x2000,
            AsyncWindowPos = 0x4000,
            TopMostFlag = NoMove | NoSize;
        }

        //Loaded this great enum values from http://www.pinvoke.net/default.aspx/user32.showwindow.  It loads the XML descriptions so you can read
        //the description in the code when you are using it.
        public enum WindowState :uint
        {
            Hide = 0,
            /// <summary>Activates and displays a window. If the window is minimized 
            /// or maximized, the system restores it to its original size and 
            /// position. An application should specify this flag when displaying 
            /// the window for the first time.</summary>
            /// <remarks>See SW_SHOWNORMAL</remarks>
            ShowNormal = 1,
            /// <summary>Activates the window and displays it as a minimized window.</summary>
            /// <remarks>See SW_SHOWMINIMIZED</remarks>
            ShowMinimized = 2,
            /// <summary>Activates the window and displays it as a maximized window.</summary>
            /// <remarks>See SW_SHOWMAXIMIZED</remarks>
            ShowMaximized = 3,
            /// <summary>Maximizes the specified window.</summary>
            /// <remarks>See SW_MAXIMIZE</remarks>
            Maximize = 3,
            /// <summary>Displays a window in its most recent size and position. 
            /// This value is similar to "ShowNormal", except the window is not 
            /// actived.</summary>
            /// <remarks>See SW_SHOWNOACTIVATE</remarks>
            ShowNormalNoActivate = 4,
            /// <summary>Activates the window and displays it in its current size 
            /// and position.</summary>
            /// <remarks>See SW_SHOW</remarks>
            Show = 5,
            /// <summary>Minimizes the specified window and activates the next 
            /// top-level window in the Z order.</summary>
            /// <remarks>See SW_MINIMIZE</remarks>
            Minimize = 6,
            /// <summary>Displays the window as a minimized window. This value is 
            /// similar to "ShowMinimized", except the window is not activated.</summary>
            /// <remarks>See SW_SHOWMINNOACTIVE</remarks>
            ShowMinNoActivate = 7,
            /// <summary>Displays the window in its current size and position. This 
            /// value is similar to "Show", except the window is not activated.</summary>
            /// <remarks>See SW_SHOWNA</remarks>
            ShowNoActivate = 8,
            /// <summary>Activates and displays the window. If the window is 
            /// minimized or maximized, the system restores it to its original size 
            /// and position. An application should specify this flag when restoring 
            /// a minimized window.</summary>
            /// <remarks>See SW_RESTORE</remarks>
            Restore = 9,
            /// <summary>Sets the show state based on the SW_ value specified in the 
            /// STARTUPINFO structure passed to the CreateProcess function by the 
            /// program that started the application.</summary>
            /// <remarks>See SW_SHOWDEFAULT</remarks>
            ShowDefault = 10,
            /// <summary>Windows 2000/XP: Minimizes a window, even if the thread 
            /// that owns the window is hung. This flag should only be used when 
            /// minimizing windows from a different thread.</summary>
            /// <remarks>See SW_FORCEMINIMIZE</remarks>
            ForceMinimized = 11
        }

        #endregion

        [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);

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.I4)]
        public static extern int SetForegroundWindow(IntPtr hWnd);

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
    }
}