Can I get the Automatic Daylight Saving Time info from a VM through powershell? - azure

I need to get a CSV of VMs that have the "Adjust for daylight saving time automatically?" set as off.
I think I can't create a script that search all the VMs in my subscription at once, since the information about the DST is not in the Azure portal. So maybe can I run something on each VM to get the expected result?
Is there any way to get this information using powershell at all?
Thanks!

Here's a handy script for Windows VMs: https://devblogs.microsoft.com/scripting/check-for-daylight-savings-time-by-using-powershell/

I cannot test this myself, but I think you only have to see if the DaylightBias property returned by Get-CimInstance -ClassName Win32_TimeZone is anything other than 0
Get-VM | ForEach-Object {
if ($_.State -eq 'Running') {
$tz = Get-CimInstance -ClassName Win32_TimeZone -ComputerName $_.Name
$dst = if (!$tz.DaylightBias) { 'Off' } else { 'On' }
}
else {
$dst = 'Unknown'
}
[PsCustomObject]#{
'Computer' = $_.Name
'Status' = $_.State
'DaylightSavingTime' = $dst
}
} | Export-Csv -Path 'D:\VM-DstInfo.csv' -NoTypeInformation
Or perhaps execute cmdlet Get-TimeZone on the VM will get you the info you need:
Get-VM | ForEach-Object {
if ($_.State -eq 'Running') {
$tz = Invoke-Command -ComputerName $_.Name -ScriptBlock {Get-TimeZone}
$dst = if (!$tz.SupportsDaylightSavingTime) { 'Off' } else { 'On' }
}
else {
$dst = 'Unknown'
}
[PsCustomObject]#{
'Computer' = $_.Name
'Status' = $_.State
'DaylightSavingTime' = $dst
}
} | Export-Csv -Path 'D:\VM-DstInfo.csv' -NoTypeInformation

Related

How to create an elseif condition in a script with Runspaces

In the original script, I was attempting to search for a string in a text file in a running log. It worked fine however, since there is a -wait parameter in the loop, it wasn't easy to find a solution that would allow for the same script to search over multiple text files. Since then the following script was introduced to me that incorporates Runspaces:
using namespace System.Management.Automation.Runspaces
using namespace System.Threading
# get the log files here
$LogGroup = ('C:\log 0.txt', 'C:\Log 1.txt', 'C:\Log 2.txt')
# this help us write to the main log file in a thread safe manner
$lock = [SemaphoreSlim]::new(1, 1)
# define the logic used for each thread, this is very similar to the
# initial script except for the use of the SemaphoreSlim
$action = {
param($path)
$PSDefaultParameterValues = #{ "Get-Date:format" = "yyyy-MM-dd HH:mm:ss" }
Get-Content $path -Tail 1 -Wait | ForEach-Object {
if($_ -match 'down') {
# can I write to this file?
$lock.Wait()
try {
Write-Host "Down: $_ - $path" -ForegroundColor Green
Add-Content "path\to\mainLog.txt" -Value "$(Get-Date) Down: $_ - $path"
}
finally {
# release the lock so other threads can write to the file
$null = $lock.Release()
}
}
}
}
try {
$iss = [initialsessionstate]::CreateDefault2()
$iss.Variables.Add([SessionStateVariableEntry]::new('lock', $lock, $null))
$rspool = [runspacefactory]::CreateRunspacePool(1, $LogGroup.Count, $iss, $Host)
$rspool.ApartmentState = [ApartmentState]::STA
$rspool.ThreadOptions = [PSThreadOptions]::UseNewThread
$rspool.Open()
$res = foreach($path in $LogGroup) {
$ps = [powershell]::Create($iss).AddScript($action).AddArgument($path)
$ps.RunspacePool = $rspool
#{
Instance = $ps
AsyncResult = $ps.BeginInvoke()
}
}
# block the main thread
do {
$id = [WaitHandle]::WaitAny($res.AsyncResult.AsyncWaitHandle, 200)
}
while($id -eq [WaitHandle]::WaitTimeout)
}
finally {
# clean all the runspaces
$res.Instance.ForEach('Dispose')
$rspool.ForEach('Dispose')
}
The Runspaces allow for additional threads allowing for multitasking but I am not very skilled and I need help adding an elseif clause after an if statement. But my attempts were rewarded with the following error:
cmdlet ForEach-Object at command pipeline position 2
Supply values for the following parameters:
Process[0]:
Here’s the best I could come up with so far:
$action = {
param($path)
$PSDefaultParameterValues = #{ "Get-Date:format" = "yyyy-MM-dd HH:mm:ss" }
$lock.Wait()
# can I write to this file?
try {
Get-Content $path -Tail 1 -Wait | ForEach-Object
if($_ -match 'down) {
Write-Host "Down: $_ - $path" -ForegroundColor Red
Add-Content "C:\ log_down.txt" -Value "$(Get-Date) Down: $_ - $path"
}
elseif($_ -match 'up') {
Write-Host "Down: $_ - $path" -ForegroundColor Green
Add-Content "C:\ log_up.txt" -Value "$(Get-Date) up: $_ - $path"
}
$lock.Wait()
}
finally {
# release the lock so other threads can write to the file
$null = $lock.Release()
}
}
Thanks in advance for any help!
Here is the only change you need to do, below code only addresses the $action Script Block. Rest of the code should remain the same.
Make sure you're using the Full Paths of the logs.
$action = {
param($path)
$PSDefaultParameterValues = #{ "Get-Date:format" = "yyyy-MM-dd HH:mm:ss" }
Get-Content $path -Tail 1 -Wait | ForEach-Object {
# wait to enter the SemaphoreSlim
$lock.Wait()
try {
if($_ -match 'down') {
Write-Host "Down: $_ - $path" -ForegroundColor Red
Add-Content "C:\log_down.txt" -Value "$(Get-Date) Down: $_ - $path"
}
elseif($_ -match 'up') {
Write-Host "Up: $_ - $path" -ForegroundColor Green
Add-Content "C:\log_up.txt" -Value "$(Get-Date) up: $_ - $path"
}
# more conditions can go here
}
finally {
# release the lock so other threads can write to the file
$null = $lock.Release()
}
}
}
After closer look at your attempt, it seems almost right:
Missing an opening { after ForEach-Object.
Missing a closing } before the finally block.
.Wait() should be inside the loop instead of outside.

Splitting output of a string into separate strings

I've been working on a powershell script and it's been really boggling my mind. There are 2 parts to the script.
First part is a function that gets all servers in a domain. We have 4 different domains, so I check each one individually and output the result.
Second part is a function that outputs the software on a specific remote machine. In my case, the output from the function above will be seeded into this function to see if a server has a particular piece of software installed.
The function that searches the software works properly. The function that I am getting an output of all the servers is what I am having trouble with.
The issue is, that when I output the list of servers (the output is correct), it outputs everything into a single large multiline string...
For example lets say I have 5 servers: (ServerA, ServerB, ServerC, ServerD, ServerE).
When I run the code I will get an output of all the servers for each domain like so:
TestA.com
ServerA
ServerB
ServerC
ServerD
ServerE
TestB.com
ServerA
ServerB
ServerC
ServerD
ServerE
TestC.com
ServerA
ServerB
ServerC
ServerD
ServerE
TestD.com
ServerA
ServerB
ServerC
ServerD
ServerE
However each domain output is all 1 string, so I can't seed it into the function to check software because it's trying to find it in "ServerA,ServerB,ServerC,ServerD,ServerE", instead of each server individually.
I hope this makes sense. Here is my code to get the list of servers.
#Clear Screen
CLS
function Get-Servers
{
#Variables
[array]$MyDomains="TestA.com","TestB.com","TestC.com","TestD.com"
[array]$MySearchBase="dc=TestA,dc=com","dc=TestB,dc=com","dc=TestC,dc=com","dc=TestD,dc=com"
for($i=0; $i -lt $MyDomains.Count; $i++)
{
Write-Output $($MyDomains[$i])
$MyServers = Get-ADComputer -Filter 'OperatingSystem -like "Windows*Server*"' -Properties Name -SearchBase $($MySearchBase[$i]) -Server $($MyDomains[$i]) | Format-Table Name -HideTableHeaders | out-string
foreach ($MyServer in $MyServers)
{
$MyServer
pause
}
}
}
#Get list of servers
Get-Servers
How can I get the output for each server individually to be stored in the "$MyServer" variable?
EDIT:
Here is my function to find remote software
function Get-RemoteRegistryProgram
{
<#
.Synopsis
Uses remote registry to read installed programs
.DESCRIPTION
Use dot net and the registry key class to query installed programs from a
remote machine
.EXAMPLE
Get-RemoteRegistryProgram -ComputerName Server1
#>
[CmdletBinding()]
Param
(
[Parameter(
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
Position=0)]
[string[]]
$ComputerName = $env:COMPUTERNAME
)
begin
{
$hives = #(
[Microsoft.Win32.RegistryHive]::LocalMachine,
[Microsoft.Win32.RegistryHive]::CurrentUser
)
$nodes = #(
"Software\Microsoft\Windows\CurrentVersion\Uninstall",
"Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
)
}
process
{
$ComputerName
forEach ($computer in $ComputerName)
{
forEach($hive in $hives)
{
try
{
$registry = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($hive,$computer)
}
catch
{
throw $PsItem
}
forEach($node in $nodes)
{
try
{
$keys = $registry.OpenSubKey($node).GetSubKeyNames()
forEach($key in $keys)
{
$displayname = $registry.OpenSubKey($node).OpenSubKey($key).GetValue('DisplayName')
if($displayname)
{
$installedProgram = #{
# ComputerName = $computer
DisplayName = $displayname
# Version = $registry.OpenSubKey($node).OpenSubKey($key).GetValue('DisplayVersion')
}
New-Object -TypeName PSObject -Property $installedProgram
}
}
}
catch
{
$orginalError = $PsItem
Switch($orginalError.FullyQualifiedErrorId)
{
'InvokeMethodOnNull'
{
#key maynot exists
}
default
{
throw $orginalError
}
}
}
}
}
}
}
end
{
}
}
EDIT 2:
If I modify my server function like so:
for($i=0; $i -lt $MyDomains.Count; $i++)
{
Write-Output $($MyDomains[$i])
$MyServers = Get-ADComputer -Filter 'OperatingSystem -like "Windows*Server*"' -Properties Name -SearchBase $($MySearchBase[$i]) -Server $($MyDomains[$i]) | Format-Table Name -HideTableHeaders
foreach ($MyServer in $MyServers)
{
Get-RemoteRegistryProgram -ComputerName $MyServer
}
}
I get the following error:
Microsoft.PowerShell.Commands.Internal.Format.FormatStartData
Exception calling "OpenRemoteBaseKey" with "2" argument(s): "The network path was not found.
"
At line:47 char:21
+ $registry = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : IOException
Thank you in advance for any help!
Your code is converting the server names to a string
$MyServers = Get-ADComputer -Filter 'OperatingSystem -like "Windows*Server*"' -Properties Name -SearchBase $($MySearchBase[$i]) -Server $($MyDomains[$i]) | Format-Table Name -HideTableHeaders | out-string
The last part of that is out-string. Instead of piping to a format table and pushing it out as a string, keep the objects and use the properties in each object to get the names of each server.
I ended up rewriting some things and fixing my issue. To avoid the string issue, I export the results to a text file and then using get-content I read line by line from the text file and seeded each server to let me know which servers have the software I need. Here is the end result.
#Clear Screen
CLS
function Get-RemoteRegistryProgram
{
<#
.Synopsis
Uses remote registry to read installed programs
.DESCRIPTION
Use dot net and the registry key class to query installed programs from a
remote machine
.EXAMPLE
Get-RemoteRegistryProgram -ComputerName Server1
#>
[CmdletBinding()]
Param
(
[Parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Position=0)][string]$ComputerName = $env:COMPUTERNAME,
[Parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Position=1)][string]$SoftwareName
)
begin
{
$hives = #(
[Microsoft.Win32.RegistryHive]::LocalMachine,
[Microsoft.Win32.RegistryHive]::CurrentUser
)
$nodes = #(
"Software\Microsoft\Windows\CurrentVersion\Uninstall",
"Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
)
}
process
{
$ComputerName
$skip = $false
forEach ($computer in $ComputerName)
{
forEach($hive in $hives)
{
try
{
$registry = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($hive,$computer)
}
catch
{
$skip = $true
}
if($skip -eq $false)
{
forEach($node in $nodes)
{
try
{
$keys = $registry.OpenSubKey($node).GetSubKeyNames()
forEach($key in $keys)
{
$displayname = $registry.OpenSubKey($node).OpenSubKey($key).GetValue('DisplayName')
#Modified by James
if(($displayname) -like "*$SoftwareName*")
{
$displayname + "`t" + $computer >> c:\scripts\sysaidServers.txt
}
<# Modified by James
if($displayname)
{
$installedProgram = #{
# ComputerName = $computer
DisplayName = $displayname
# Version = $registry.OpenSubKey($node).OpenSubKey($key).GetValue('DisplayVersion')
}
New-Object -TypeName PSObject -Property $installedProgram
}
#>
}
}
catch
{
<#
$orginalError = $PsItem
Switch($orginalError.FullyQualifiedErrorId)
{
'InvokeMethodOnNull'
{
#key maynot exists
}
default
{
throw $orginalError
}
}
#>
}
}
}
}
}
}
end
{
}
}
#Output the servers to a txt file
function Get-Servers
{
param ([Parameter( Mandatory=$true)][string]$SaveFile)
#Variables
[array]$MyDomains="DomainA.com","DomainB.com","DomainC.com","DomainD.com"
[array]$MySearchBase="dc=DomainA,dc=com","dc=DomainB,dc=com","dc=DomainC,dc=com","dc=DomainD,dc=com"
for($i=0; $i -lt $MyDomains.Count; $i++)
{
#I only want servers running Windows Server OS
$MyServers = Get-ADComputer -Filter 'OperatingSystem -like "Windows*Server*"' -Properties Name -SearchBase $($MySearchBase[$i]) -Server $($MyDomains[$i]) | Format-Table Name -HideTableHeaders | out-string
#Remove all whitespace and export to txt file
$MyServers.Trim() -replace (' ', '') >> $SaveFile
}
}
function CheckServerSoftware
{
param ([Parameter( Mandatory=$true)][string]$SaveFile)
Get-Content $SaveFile | ForEach-Object {
if($_ -match $regex)
{
$computer = $_.ToString()
Get-RemoteRegistryProgram -ComputerName $computer.Trim() $SoftwareName
Write-Output ""
}
}
}
#Path to where our exported server list is
$SaveFile = "c:\scripts\servers.txt"
$SoftwareName = "SysAid"
#If the file already exists, remove it
Remove-Item $SaveFile
#Create the text file with servers
Get-Servers $SaveFile
#Import our server list and check software on each server
CheckServerSoftware $SaveFile

Excel report Formatting in PowerShell

Need help to create a script to get a HPOA server blade Health report
The problem is that when I get query Health it outputs in a PSO object with fields (IP,Health,Blades(#{Blade1 Health}{Blade2 Health}{3} . . .) )
I want a report like below
IP Bay Power Health
-- --- ----- -----
10.3.131.2 1 On OK
2 On OK
3 On OK
4 On OK
5 On Degraded
The variables are derived as below .
$sstaInfo = {} | Select IP, Bay, Power, Health, DeviceFailure
$sstaInfo.IP=$ssta.IP (Gives a single IP output)
$sstaInfo.Bay=$sstaBlades.Bay $sstaInfo.Power=$sstaBlades.Power
$sstaInfo.Health=$sstaBlades.Health
How can I get this working ?
$ssta variable has the below output :
#{Power=On; CurrentWattageUsed=480; Health=OK; UnitIdentificationLED=Off; VirtualFan=33%; DiagnosticStatus=; Bay=1} #{Power=On; CurrentWattageUsed=576; Health=OK; UnitIdentificationLED=Off; VirtualFan=47%; DiagnosticStatus=; Bay=2}
#------------------------------------------------------------ Input Variable Definations
$HPOAServers =#(
[pscustomobject]#{Name='10.11.12.13'},
[pscustomobject]#{Name='10.11.12.14'}
)
$Username ="admin"
$Password ="admin"
#------------------------------------------------------------ Main Script Starts Here
# Function for connecting to OA and returning connection object on success
foreach ($HPOAServer in $HPOAServers) {
$con = Connect-HPOA $HPOAServer.Name -username $Username -password $Password
$report = #()
$ssta = Get-HPOAServerStatus -Bay All $con
$sstaBlade=$ssta.Blade
Write-Host $sstaBlade
Foreach ($sstaBlades in $sstaBlade) {
$i++
$sstaInfo = {} | Select IP, Bay, Power, Health, DeviceFailure
$sstaInfo.IP=$ssta.IP
$sstaInfo.Bay=$sstaBlades.Bay
$sstaInfo.Power=$sstaBlades.Power
$sstaInfo.Health=$sstaBlades.Health
$sstaInfo.DeviceFailure=$ssta.Blade.DiagnosticStatus.DeviceFailure
}
$report += $ssta | Select-Object -Property IP
$report += $ssta.Blade | Select-Object -Property Bay, Power, Health | Format-Table *
$report | out-file "HPOA_Health_Report.txt" -Append
}
Disconnect-HPOA $con
I suggest you use Export-CSV instead, so below line
$report | Out-File "HPOA_Health_Report.txt" -Append
will be replaced by:
$report | Export-Csv "HPOA_Health_Report.csv" -Append -NoTypeInformation
Function HPOA () {
try
{
Remove-Item -Path $outputfile -Force
foreach ($HPOAServer in $HPOAServers)
{
$con = Connect-HPOA $HPOAServer.Name -username $Username -password $Password -ErrorAction 'Stop'
$ssta = Get-HPOAServerStatus -Bay All $con
$ssta.Blade | Foreach-Object {
$sstaInfo = $_
$sstaInfo | Select-Object -Property #{Name="Chassis_IP_Address";Expression={$ssta.IP}},
#{Name="Blade_Power_Status";Expression={$_.Power}},
#{Name="Blade_Bay_Number";Expression={$_.Bay}},
#{Name="Blade_Health_Status";Expression={$_.Health}},
#{Name="Blade_Diagnostic_DeviceFailure_Status";Expression={$ssta.Blade.DiagnosticStatus.DeviceFailure}}
} | ConvertTo-Html -Title " $HPOARegionName HPOA Health Report " -Head $Header -Body "<H2> $HPOARegionName HPOA Health Report </H2>" -As Table | Out-File -Append $outputfile
Disconnect-HPOA $con
}
}
catch
{
$ErrorMessage = $_.Exception.Message
$FailedItem = $_.Exception.ItemName
Write-Host $ErrorMessage
Write-Host $FailedItem
}
}
HPOA

The term '' is not recognized as the name of a recognized cmdlet

I have seen a lot of these items out there but none seem to be for a user defined function.
I am new to powershell and have created a script to run the net view command and then test if I have access to the directory:
Function get-netview{
param($hosts)
(net view \\$hosts) | % { if($_.IndexOf(' Disk ') -gt 0){ $_.Split(' ')[0] }}
}
function fastping{
[CmdletBinding()]
param(
[String]$computername = "127.0.0.1",
[int]$delay = 100
)
$ping = new-object System.Net.NetworkInformation.Ping
# see http://msdn.microsoft.com/en-us/library/system.net.networkinformation.ipstatus%28v=vs.110%29.aspx
try {
if ($ping.send($computername,$delay).status -ne "Success") {
return $false;
}
else {
return $true;
}
} catch {
return $false;
}
}
function get-dir{
param($hosts,$dir)
$errors=#()
$i = 0
Get-ChildItem \\$hosts\$dir -ea SilentlyContinue -ErrorVariable +errors | Out-Null
if ($errors.count -gt 0){
$outvar = "Access Denied",$hosts,$dir,"0"
$outvar –join “,” | Out-File .\outfile.txt -append
}
else{
$x = (Get-ChildItem \\$hosts\$dir).count
if ($x -gt 0) {
$outvar = "Access Granted",$hosts,$dir,$x
$outvar –join “,” | out-file .\outfile.txt -append
}
else{
write-host ("Empty Folder",$hosts,$dir,"0") -Separator ","
$outvar = "Empty Folder",$hosts,$dir,"0"
$outvar –join “,” | Out-File .\zzfile.txt -append
}
}
}
function run-netviewall{
param($hosts)
$pings = fastping $hosts 250
if ($pings) {
foreach ($dir in get-netview $hosts) {get-dir $hosts $dir | out-file temtest.txt}
}else{
$hosts | out-file .\notonline.txt
}
}
These are the 4 function I have loaded and they work when i Run them on a single host but when i try to multithread them I get an error that ""The term 'run-netviewall' is not recognized as the name of a cmdlet, function, script file, or operable program.
Any help would be appreciated. Some of the scripts above were obtained online and edited slightly to meet my needs but they work. Any help you can provide would be appreciated.
FYI I have tried 4 different multithreaders and they all give me that error. I'm sure its stomething simple I didn't know about to
Thanks,
Jon

Display all sites and bindings in PowerShell

I am documenting all the sites and binding related to the site from the IIS. Is there an easy way to get this list through a PowerShell script rather than manually typing looking at IIS?
I want the output to be something like this:
Site Bindings
TestSite www.hello.com
www.test.com
JonDoeSite www.johndoe.site
Try this:
Import-Module Webadministration
Get-ChildItem -Path IIS:\Sites
It should return something that looks like this:
Name ID State Physical Path Bindings
---- -- ----- ------------- --------
ChristophersWeb 22 Started C:\temp http *:8080:ChristophersWebsite.ChDom.com
From here you can refine results, but be careful. A pipe to the select statement will not give you what you need. Based on your requirements I would build a custom object or hashtable.
Try something like this to get the format you wanted:
Get-WebBinding | % {
$name = $_.ItemXPath -replace '(?:.*?)name=''([^'']*)(?:.*)', '$1'
New-Object psobject -Property #{
Name = $name
Binding = $_.bindinginformation.Split(":")[-1]
}
} | Group-Object -Property Name |
Format-Table Name, #{n="Bindings";e={$_.Group.Binding -join "`n"}} -Wrap
If you just want to list all the sites (ie. to find a binding)
Change the working directory to "C:\Windows\system32\inetsrv"
cd c:\Windows\system32\inetsrv
Next run "appcmd list sites" (plural) and output to a file. e.g c:\IISSiteBindings.txt
appcmd list sites > c:\IISSiteBindings.txt
Now open with notepad from your command prompt.
notepad c:\IISSiteBindings.txt
The most easy way as I saw:
Foreach ($Site in get-website) { Foreach ($Bind in $Site.bindings.collection) {[pscustomobject]#{name=$Site.name;Protocol=$Bind.Protocol;Bindings=$Bind.BindingInformation}}}
Try this
function DisplayLocalSites
{
try{
Set-ExecutionPolicy unrestricted
$list = #()
foreach ($webapp in get-childitem IIS:\Sites\)
{
$name = "IIS:\Sites\" + $webapp.name
$item = #{}
$item.WebAppName = $webapp.name
foreach($Bind in $webapp.Bindings.collection)
{
$item.SiteUrl = $Bind.Protocol +'://'+ $Bind.BindingInformation.Split(":")[-1]
}
$obj = New-Object PSObject -Property $item
$list += $obj
}
$list | Format-Table -a -Property "WebAppName","SiteUrl"
$list | Out-File -filepath C:\websites.txt
Set-ExecutionPolicy restricted
}
catch
{
$ExceptionMessage = "Error in Line: " + $_.Exception.Line + ". " + $_.Exception.GetType().FullName + ": " + $_.Exception.Message + " Stacktrace: " + $_.Exception.StackTrace
$ExceptionMessage
}
}
function Get-ADDWebBindings {
param([string]$Name="*",[switch]$http,[switch]$https)
try {
if (-not (Get-Module WebAdministration)) { Import-Module WebAdministration }
Get-WebBinding | ForEach-Object { $_.ItemXPath -replace '(?:.*?)name=''([^'']*)(?:.*)', '$1' } | Sort | Get-Unique | Where-Object {$_ -like $Name} | ForEach-Object {
$n=$_
Get-WebBinding | Where-Object { ($_.ItemXPath -replace '(?:.*?)name=''([^'']*)(?:.*)', '$1') -like $n } | ForEach-Object {
if ($http -or $https) {
if ( ($http -and ($_.protocol -like "http")) -or ($https -and ($_.protocol -like "https")) ) {
New-Object psobject -Property #{Name = $n;Protocol=$_.protocol;Binding = $_.bindinginformation}
}
} else {
New-Object psobject -Property #{Name = $n;Protocol=$_.protocol;Binding = $_.bindinginformation}
}
}
}
}
catch {
$false
}
}
I found this page because I needed to migrate a site with many many bindings to a new server. I used some of the code here to generate the powershell script below to add the bindings to the new server. Sharing in case it is useful to someone else:
Import-Module WebAdministration
$Websites = Get-ChildItem IIS:\Sites
$site = $Websites | Where-object { $_.Name -eq 'site-name-in-iis-here' }
$Binding = $Site.bindings
[string]$BindingInfo = $Binding.Collection
[string[]]$Bindings = $BindingInfo.Split(" ")
$i = 0
$header = ""
Do{
[string[]]$Bindings2 = $Bindings[($i+1)].Split(":")
Write-Output ("New-WebBinding -Name `"site-name-in-iis-here`" -IPAddress " + $Bindings2[0] + " -Port " + $Bindings2[1] + " -HostHeader `"" + $Bindings2[2] + "`"")
$i=$i+2
} while ($i -lt ($bindings.count))
It generates records that look like this:
New-WebBinding -Name "site-name-in-iis-here" -IPAddress "*" -Port 80 -HostHeader www.aaa.com
I found this question because I wanted to generate a web page with links to all the websites running on my IIS instance. I used Alexander Shapkin's answer to come up with the following to generate a bunch of links.
$hostname = "localhost"
Foreach ($Site in get-website) {
Foreach ($Bind in $Site.bindings.collection) {
$data = [PSCustomObject]#{
name=$Site.name;
Protocol=$Bind.Protocol;
Bindings=$Bind.BindingInformation
}
$data.Bindings = $data.Bindings -replace '(:$)', ''
$html = "" + $data.name + ""
$html.Replace("*", $hostname);
}
}
Then I paste the results into this hastily written HTML:
<html>
<style>
a { display: block; }
</style>
{paste PowerShell results here}
</body>
</html>

Resources