Skip to content

Instantly share code, notes, and snippets.

@crshnbrn66
Last active June 16, 2020 11:04
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save crshnbrn66/79ad91eb21b0b7734ad1663c194c9c74 to your computer and use it in GitHub Desktop.
Save crshnbrn66/79ad91eb21b0b7734ad1663c194c9c74 to your computer and use it in GitHub Desktop.
Retrieves IIS settings from remote machines and presents difference view in winmerge
#Requires -Modules webadministration
#Requires -RunAsAdministrator
#Requires -version 3.0
<#
.SYNOPSIS
Provides a means to get the current backup location for iis changes
.DESCRIPTION
Changes made to the IIS instance are recorded in a history config file. This function provides the means to retreive where it is on the machine
Get-IISSystemHistoryLocation -index '2'
.PARAMETER index
if a value for index is passed it'll get the x number from the collection of history backups.
For instance if there are 5 backups and the index number passed is 2 then It'll get the next backup from the latest.
.Example
PS PS:\> Get-IISSystemHistoryLocation -computerName test 0
\\test\C$\inetpub\history\CFGHISTORY_0000000033
.Example 2
PS PS:\> Get-IISSystemHistoryLocation -computerName test 3
\\test\C$\inetpub\history\CFGHISTORY_0000000030
#>
function Get-IISSystemHistoryLocation
{
[OutputType([string])]
param
(
[string]$computerName,
[Parameter(Mandatory = $false)]
[int16]$index = '1'
)
$computerName = Get-LocalRemoteComputer -computername $computerName
if($computerName -ne $env:COMPUTERNAME)
{
$startingdir = Resolve-EnvVariable -String '%systemroot%' -computername $computername
}
else
{
$startingdir = $env:windir
}
$config = [xml](get-content "$startingDir\system32\inetsrv\config\schema\IIS_schema.xml")
$configHistory = (($config.configSchema.sectionschema | where{ $_.name -like "*configHistory*" }).attribute | ?{ $_.name -like "path" }).defaultvalue
$envVar = $configHistory | Resolve-EnvVariable -computername $computername
$configDir = dir $envVar | Sort-Object -Property lastwritetime -Descending | select -Index $index
$configd = $configdir.fullname
$configd -match '\w:' | out-null
if($Matches)
{
$driveLetter = ($Matches.values).trim(':')
$serverConfig = $configd -replace '\w:', "\\$computername\$driveletter$"
$configd = $serverConfig
}
$configd
}
<#
.SYNOPSIS
A brief description of the Resolve-EnvVariable function.
.DESCRIPTION
Takes an environment variable and resolves it to the actual location stripping off the %% from a dos command.
example
Resolve-EnvVariable -String %temp% -computername $computername
\\servername\C$\Users\TSCHUM~1\AppData\Local\Temp
Resolve-EnvVariable -String %temp% -computername .
C:\Users\TSCHUM~1\AppData\Local\Temp
.PARAMETER String
Enter a string that contains an environmental variable like %WINDIR%
.PARAMETER computername
Name of the computer to check the environment variable against.
#>
function Resolve-EnvVariable
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true,
ValueFromPipeline = $true,
Position = 0,
HelpMessage = 'Enter a string that contains an environmental variable like %WINDIR%')]
[ValidateNotNullOrEmpty()]
[string]$String,
[string]$computername
)
#https://powershell.org/friday-fun-expand-environmental-variables-in-powershell-strings/
Begin
{
$computerName = Get-LocalRemoteComputer -computername $computerName
Write-Verbose "Starting $($myinvocation.mycommand)"
} #Begin
Process
{
#if string contains a % then process it
if ($string -match "%\S+%")
{
Write-Verbose "Resolving environmental variables in $String"
#split string into an array of values
$values = $string.split("%") | Where { $_ }
foreach ($text in $values)
{
#find the corresponding value in ENV:
Write-Verbose "Looking for $text"
if ($env:COMPUTERNAME -ne $computername)
{
[string]$replace = (invoke-command -ComputerName $computername -ScriptBlock { param ([string]$t)get-item env:$t -ErrorAction SilentlyContinue } -ArgumentList $text).value
#(Get-Item env:$text -erroraction "SilentlyContinue").Value
if ($replace)
{
#if found append it to the new string
Write-Verbose "Found $replace"
$newstring += $replace
}
else
{
#otherwise append the original text
$newstring += $text
}
$newstring -match '\w:' | out-null
if ($Matches)
{
$driveLetter = ($Matches.values).trim(':')
$newstring = $newstring -replace '\w:', "\\$computername\$driveletter$"
}
}
else
{
[string]$replace = (Get-Item env:$text -erroraction "SilentlyContinue").Value
if ($replace)
{
#if found append it to the new string
Write-Verbose "Found $replace"
$newstring += $replace
}
else
{
#otherwise append the original text
$newstring += $text
}
}
} #foreach value
Write-Verbose "Writing revised string to the pipeline"
#write the string back to the pipeline
Write-Output $NewString
} #if
else
{
#skip the string and write it back to the pipeline
Write-Output $String
}
} #Process
End
{
Write-Verbose "Ending $($myinvocation.mycommand)"
} #End
} #end Resolve-EnvVariable
<#
.SYNOPSIS
Gets the current backup location of IIS Configs
.DESCRIPTION
Gets the latest directory that contains the last IIS backup
If you do not specify an index number then the function will get index 0 of the number of backups.
Each backup in IIS is a seperate directory the script determines how many there are and sets the first index number to the most recent backup.
.PARAMETER computername
this is as string value that represents the comptutername that we want to find the backups for
.PARAMETER index
This is a integer(16) value that represents the index number of the backup you want to retrieve. the most recent backup is index 0.
.NOTES
This returns a string object of the backup location for the computername passed.
.Example
PS PS:\> Get-LastIISBackupLocation -computername test 1
returns: \\test\C$\Windows\system32\inetsrv\backup\2016-07-14
.Example 2
PS PS:\> Get-LastIISBackupLocation -computername test 0
\\test\C$\Windows\system32\inetsrv\backup\2016-07-15
#>
function Get-LastIISBackupLocation
{
[OutputType([string])]
param
(
[string]$computername,
[int16]$index = '0'
)
$computerName = Get-LocalRemoteComputer -computername $computerName
if ($computerName -ne $env:COMPUTERNAME)
{
$startingdir = Resolve-EnvVariable -String '%systemroot%' -computername $computername
}
else
{
$startingdir = $env:windir
}
$mostRecentDir = dir ("$startingdir\system32\inetsrv\backup") | Sort-Object -Property Lastwritetime -Descending | select -Index $index
$mostRecentDir.fullname
}
<#
.SYNOPSIS
Gets the current directory for the machine that is passed.
.DESCRIPTION
Gets the current installed location of iis from the IIS
.PARAMETER computername
string for computername that we want to find the current installation of iis
.EXAMPLE
Get-CurrentIISConfiguration -computername test
returns: \\test\c$\windows\system32\inetsrv\config
#>
function Get-CurrentIIsConfiguration
{
[OutputType([string])]
param
(
[string]$computername
)
$computerName = Get-LocalRemoteComputer -computername $computerName
if ($computerName -ne $env:COMPUTERNAME)
{
$startingdir = "\\$computername\c$\windows"
}
else
{
$startingdir = $env:windir
}
$mostRecentDir = "$startingdir\system32\inetsrv\config"
$mostRecentDir
}
<#
.SYNOPSIS
Determines if the name passed is the localhost or not
.DESCRIPTION
If the name passed is the localhost then the script will send back the computername:
.example
get-localremotecomputer -computername .
yourmachinename
get-localremotecomputer -computername 127.0.0.1
yourmachinename
get-localremotecomputer -computername servername
servername
.PARAMETER computername
A description of the computername parameter.
.NOTES
Additional information about the function.
#>
function Get-LocalRemoteComputer
{
param
(
[string]$computername
)
if ($computername -eq '.' -or ($env:COMPUTERNAME -eq $computername) -or ($computername -eq 'Localhost') -or ($computername -eq '127.0.0.1'))
{
$computername = $env:COMPUTERNAME
$computername
}
else
{ $computername }
}
<#
.SYNOPSIS
takes to files passed and sends them to winmerge for comparison
.DESCRIPTION
This function will pass the source and differnece file and then launch winmerge.
.PARAMETER sourceFile
file used to be the source of the comparison
.PARAMETER diffFile
file that is the difference file
.PARAMETER winMergeLoc
Physical location of the exe for winmerge. This function will pass the source and differnece file and then launch winmerge.
.NOTES
Additional information about the function.
#>
function Compare-IISConfigsWinMerge
{
param
(
[string]$sourceFile,
[string]$diffFile,
[string]$winMergeLoc
)
if (test-path $winMergeLoc)
{
if (test-path $sourcefile)
{
if (test-path $difffile)
{
& "$winmergeLoc " "$sourcefile " "$diffFile"
$results = $true
}
else { $results = 'bad diff file' }
}
else {$results = 'bad source file'}
}
else {$results = 'bad winmerge location' }
$results
}
$winmerge = '\\server\winmerge\WinMergePortable\winmergeportable.exe'
$history = Get-IISSystemHistoryLocation -computerName 'test' -index '2'
$current = Get-CurrentIIsConfiguration -computername 'test2'
Compare-IISConfigsWinMerge -winMergeLoc $winmerge -sourceFile "$current\applicationhost.config" -diffFile "$history\applicationHost.config"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment