Automating a Synchronization


I wanted to sync our Dev Web site with our Prod Web site.
The idea was to move new files into the Prod site and delete any old or extra files.
Rather than write a POSH script I decided to use Beyond Compare 3. Great product, I highly recommend it.
http://www.scootersoftware.com/moreinfo.php
With some help from the folks at Scooter Software, I came up with this:


###### Start Posh Script ########

Function Show-Inputbox {
 Param([string]$message=$(Throw "You must enter a prompt message"),
       [string]$title="Input",
       [string]$default
       )

 [reflection.assembly]::loadwithpartialname("microsoft.visualbasic") | Out-Null
 [microsoft.visualbasic.interaction]::InputBox($message,$title,$default)

}

$Dev = Show-Inputbox -message "The New Web files location" `
-title "Path" -default "E:\DevSite\0000\"

$Prod = Show-Inputbox -message "The Prod Web files location" `
-title "Path" -default "E:\inetpub\0000\"

$left = $Dev
$right = $Prod

$exe = "E:\Tools\BEYOND~1\BCompare.exe"
$p = [diagnostics.process]::Start("cmd.exe", "/c start /wait " + $exe + " @E:\Scripts\PS1\IISProject\SyncWebSite.txt $left $right")

############# End POSH Script ###############


You also need to write a simple text file up that includes the parameters for BeyondCompare like this:

# Keeping a web site in sync
# This script keeps a web site in sync with development files.
######
# Turn verbose logging on.
log verbose append: “E:\WebSyncLog\%date%.txt”

# be carefull with the Quote marks, You may need to change them
# Set the comparison criteria.
criteria binary size
# Load source and target folders.
load %1 %2
# Filter to only include source files, ignore CVS subfolders.
# filter “*.htm;*.html;*.php;*.jpg;*.gif;-CVS\”
# Sync the local files to the web site, creating empty folders.
sync create-empty mirror:left->right
#######
I called it SyncWebSite.txt

Be very carefull with your left and right directories.
Once it’s synced there is no going back.

Powershell, IIS and driving myself nuts


I was asked to come up with a script to recycle the appPools on a variety of Web Servers
with a large number of Web Sites. Some of these servers are IIS6 and some are IIS7 or IIS7.5.
I had to come up with two separate functions because the names of things changed between IIS6 and IIS7.

IIS 6

function Recycle6 {  $strServer = “MyServer”
  $pool= “MyAppPool”
  $appPool = get-wmiobject -namespace "root\MicrosoftIISv2 -class "IIsApplicationPool" -computername $strServer -authentication pktPrivacy |
  where-object {$_.Name -eq "W3SVC/AppPools/$Pool"}
$appPool.Recycle()
Start-Sleep 2
$appPoolState = ([ADSI] "IIS://$strServert/W3SVC/AppPools/$Pool").AppPoolState
switch($appPoolState) {
	1 { $strState = "starting" }
	2 { $strState = "started" }
	3 { $strState = "stopping" }
	4 { $strState = "stopped"	}
	default { $strState = "Unknown"	}
}
	$strDate = Get-Date
	Write-Host "$strServer $pool $strState on $strDate"
If ($error) {
	Write-Host $Error }
	}

How about IIS 7 ?

function Recycle7 {
	$strServer = “MyServer”
	$pool= $combobox1.Text
	$namespace = "root\WebAdministration"
   Write-Host  "$strServer $pool $Namespace"
$strFile ="\\myServer\E$\scripts\ps1\RestartAppPool.log"
Get-WmiObject -Namespace 'root\webadministration' -Class ApplicationPool -ComputerName  $strServer -Authentication 6 -Filter "Name= $pool" |
Invoke-WmiMethod -Name Recycle
$a = Get-WmiObject -class ApplicationPool -computername $strServer -namespace $namespace -authentication 6 -Filter "Name = $pool"
$appPoolState = $a.GetState().ReturnValue
switch($appPoolState) {
	1 { $strState = "starting" }
	2 { $strState = "started" }
	3 { $strState = "stopping" }
	4 { $strState = "stopped"	}
	default { $strState = "Unknown"	}
		}
	$strDate = Get-Date
	Write-Host "$strServer $pool $strState on $strDate"
}

Three things jump out at you when you study these functions:

IIS 6 vs. IIS7

1. $namespace = root\MicrosoftIISv2 vs. -namespace “root\WebAdministration
2. -class IIsApplicationPool vs. –class ApplicationPool
3. -authentication pktPrivacy vs. -authentication 6 ( 6 is PacketPrivacy )

How do I determine the last time a Web Site was visited?


COMMENT: This one looks at a list of IIS servers, checks the Site Logs
to determine the last time someone visited the site.


<# =====================================================================
========================================================================
#>
function Test-Port {
    Param(
        [string] $srv,
        $port=135,
        $timeout=3000,
        [switch]$verbose
    )
    # Test-Port.ps1
    # Does a TCP connection on specified port (135 by default)
    $ErrorActionPreference = "SilentlyContinue"
    # Create TCP Client
    $tcpclient = new-Object system.Net.Sockets.TcpClient
    # Tell TCP Client to connect to machine on Port
    $iar = $tcpclient.BeginConnect($srv,$port,$null,$null)
    # Set the wait time
    $wait = $iar.AsyncWaitHandle.WaitOne($timeout,$false)
    # Check to see if the connection is done
    if(!$wait)
    {
        # Close the connection and report timeout
        $tcpclient.Close()
        if($verbose){Write-Host "Connection Timeout"}
        Return $false
    }
    else
    {
        # Close the connection and report the error if there is one
        $error.Clear()
        $tcpclient.EndConnect($iar) | out-Null
        if(!$?){if($verbose){write-host $error[0]};$failed = $true}
        $tcpclient.Close()
    }
    # Return $true if connection Establish else $False
    if($failed){
        return $false
    } else {
        return $true
    }
} # <a href="http://technet.microsoft.com/en-us/library/ff730959.aspx">http://technet.microsoft.com/en-us/library/ff730959.aspx</a>

$ErrorActionPreference = "SilentlyContinue"
$i = $j = 1
$strFile = "E:\scripts\LogFile.txt"
$oLogFile = New-Item -ItemType file $strFile -Force
$srvName = "IIS Servers"
$strDate = Get-Date -format g
Add-Content -Path $strFile "Server `tOS `tSite ID `tSite Name `tLog File Directory `tDate/Time `tHow many days ago `tLogging Enabled `t$strDate"

$servers = gc IISservers.txt
$C = $Servers.count
foreach($server in $servers)
{ Write-Progress -Activity "Servers..." -Status "$i of $C" `
    -percentcomplete ($i / $C*100) -id 1
      If (Test-Connection -computername $server -Quiet -count 1){  
           $a = Test-Port $server
           If ($a) {
               $WMIJob = Get-WmiObject Win32_OperatingSystem -Comp $server -AsJob
            Wait-Job -ID $WMIJob.ID -Timeout 20
            $os = Receive-Job $WMIJob.ID
            if ($os -ne $null) {
            switch ($os.version) {
                "5.1.2600" {$osVer = "XP/IIS5.1"}
                "5.2.3790" {$osVer = "Server 2003/IIS6"}
                "6.0.6001" {$osVer = "Server 2008/IIS7"}
                "6.1.7600" {$osVer = "Server 2008 R2/IIS7.5"}
                    }
                $iis = [adsi]"IIS://$server/w3SVC"
                $sites = $iis.Children | ?{$_.keytype -eq "IIsWebServer"}
                $sc = $sites.count
                $j = 1
        foreach($site in $sites)
        {     
        Write-Progress -Activity "Sites..." -Status "$j of $sc" `
        -percentcomplete ($j / $sc*100) -ParentID 1
         $daysago = $null
        $logdir = $site.LogFileDirectory
        $lfd = $logdir -replace ':\\', '$\'
        $lfd = "\\$server\$lfd\w3svc$($site.name)"
        $Comment = [string]$($site.ServerComment)
        $WebSite = [string]$($Site.Name)
        Switch ($site.LogType) {
                                0 { $result = "Disabled" }
                                1 { $result = "Enabled" }
                                }
        if(Test-Path $lfd)
            {
            $lwt = gci $lfd | sort lastwritetime -Descending | select -first 1 -ExpandProperty lastwritetime         
            If ($lwt) {
            $daysago = (New-TimeSpan -Start $lwt -End ([datetime]::Now)).days }
                Else {
                    $lwt = "Dir is Empty"
                    }
            $WebSite = [string]$($Site.Name)
            $lfd = [string]$lfd
            $Comment = [string]$($site.ServerComment)
            Add-Content -Path $strFile "$server`t$osVer`t$WebSite `t$Comment `t$lfd `t$lwt `t$daysago `t$result"
                    }
                    Else {
                    Add-Content -Path $strFile "$server`t$osVer`t$WebSite `t$Comment `t$lfd `tLogFile Directory not found `t `t$result"
                        }
                    $j++
                    }
                }
            #   GWMI fail    
            Else {
            $b = $error | select Exception
              $E = $b -split (":")
              $x = $E[1]
            $Error.Clear()
            $d = $x.StartsWith(" Access")
            If ($d){
                    Add-Content -Path $strFile "$server `tAccess Denied"
                    }
                Else {
                    Add-Content -Path $strFile "$server `t$x"
                    }
                }    
             }       
            Else {
                    Add-Content -Path $strFile "$server `tRPC Port not listening"
                    $i++
                    }
        }
    Else {Add-Content -Path $strFile "$server `tDoes Not Ping"
            $i++   
            }
    $i++
}

############# End POSH Script ###############