Switching Lastname, Firstname in Powershell AD script - excel

I try to export AD groups and users from a OU by Firstname, Lastname but I only get it to work with Lastname, Firstname.
Everything else I try gives me an empty string for members.I tried changing the line under Select-Object to:
#{Name='Member';Expression={$_.FirstName = GetFirstName $_.Name $_.LastName = GetLastName $_.Name}},
$firt = $_.firstname
$last = $_.lastname
#{Name='Member';Expression={$_.name = "$first,$last"}},
This is the working code, but the names should be switched around.
$OU = 'OU=Groups,OU=City,OU=Continent,DC=DomainControler, DC=Domain, DC=net' #Change this to get different groups
$DateTime = Get-Date -f "dd-MM-yyyy"
$MyFileName = "CompanyName-Groups_"+$DateTime+".csv"
$Path = Join-Path $PSScriptRoot $MyFileName
$Groups = get-adobject -Filter 'ObjectClass -eq "group"' -SearchBase $OU
$i=0
$tot = $Groups.count
$Data = foreach ($Group in $Groups) {
$i++
$status = "{0:N0}" -f ($i / $tot * 100)
Write-Progress -Activity "Exporting AD Groups" -status "Processing Group $i of $tot : $status% Completed" -PercentComplete ($i / $tot * 100)
Get-ADGroupMember -Identity $Group |
Select-Object #{Name='Group';Expression={$Group.Name}},
#{Name='Member';Expression={$_.Name}},
#{Name='Enabled';Expression={if ($_.ObjectClass -eq 'user') {Get-ADUser $_ | Select-Object -Expand Enabled} else {'NA/Group'}}}
}
$Data | Export-Csv -Path $Path -NoTypeInformation
This is an example output:
Group, "member", enabled
Admin, "Mario, Speedwagon", True
Admin, "Petey, Cruiser", True
Admin, "Anna, Sthesia", False
HR, "Paul, Molive", True
HR, "Phaedra, Lugt", True
IT, "Paul, Molive", False
IT, "Cliff, Hanger", True
This is what it should become:
Group, "member", enabled
Admin, "Speedwagon, Mario", True
Admin, "Cruiser, Petey", True
Admin, "Sthesia, Anna", False
HR, "Molive, Paul", True
HR, "Lugt, Phaedra", True
IT, "Molive, Paul", False
IT, "Hanger, Cliff", True

I think this might clear things up for you:
$OU = 'OU=Groups,OU=City,OU=Continent,DC=DomainControler, DC=Domain, DC=net'
$PathParams = #{
Path = $PSScriptRoot
ChildPath = "PA-AD-Groups_{0}.csv" -f (Get-Date -f "dd-MM-yyyy")
}
$FilePath = Join-Path #PathParams
$Groups = Get-ADObject -Filter 'ObjectClass -eq "group"' -SearchBase $OU
$i = 0
$tot = $Groups.count
$Data = foreach ($Group in $Groups) {
$i++
$ProgressParams = #{
Activity = 'Exporting AD Groups'
PercentComplete = ($i / $tot * 100)
status = "Processing Group $i of $tot : {0:N0} Completed" -f
($i / $tot * 100)
}
Write-Progress #ProgressParams
Get-ADGroupMember -Identity $Group |
Select-Object #{Name = 'Group'; Expression = {$Group.Name}},
#{Name = 'Member'; Expression = {$_.Name}},
#{Name = 'Enabled'; Expression = {
$Script:User = $false
if ($_.ObjectClass -eq 'user') {
$Script:User = Get-ADUser $_
if ($User.Enabled) {$true} else {$false}
}
else {
'NA/Group'
}
}
},
#{Name = 'FirstName'; Expression = {
if ($User) {
$User.GivenName
}
}
},
#{Name = 'LastName'; Expression = {
if ($User) {
$User.Surname
}
}
},
#{Name = 'CombinedName'; Expression = {
if ($User) {
"{0}, {1}" -f $User.GivenName, $User.Surname
}
}
}
}
$Data | Export-Csv -Path $FilePath -NoTypeInformation
The issue you have is that you can't use the properties from $User outside of the Expression within the Select-Object. This is simply fixed by creating a variable that is available throughout the script and as such is called Script scope, used as $Script:User.
More info can be found in Get-Help about_Scopes or here.
On a side note I would advice you to use proper indentation, it makes things more readable. The splatted parameter hashtable helps in this regard too. As a last tip: don't create a variable if you only use it once. Otherwise it just confuses you later on.

Related

Powershell - Get-AzureADAuditSignInLogs multiple filters

I'm trying to Get last signin date for Global Admins
$role = Get-AzureADDirectoryRole | Where-Object {$_.displayName -eq 'Global Administrator'}
$admins = #(Get-AzureADDirectoryRoleMember -ObjectId $role.ObjectId | select DisplayName, UserPrincipalName)
Foreach ($admin in $admins){
$upn = $admin.UserPrincipalName
$signons = Get-AzureADAuditSignInLogs -Filter "UserPrincipalName eq '$upn' " -Top 1 | select UserDisplayName, #{Name = 'LastSignIn'; Expression = {$_.CreatedDateTime}}
}
And above code works as expected for users who have entry in AuditSignInLogs, but i want to return users who never logged in too, so modified above filter
(all users in for loop)
$signons = Get-AzureADAuditSignInLogs -Filter "UserPrincipalName eq '$upn' or CreatedDateTime eq '$null'" -Top 1 | select UserDisplayName, #{Name = 'LastSignIn'; Expression = {$_.CreatedDateTime}}
But getting error "Message: Invalid filter clause"
also tried or CreatedDateTime eq '' but same error
Please check below powershell commands.
I have initially checked the same for users .
Then checked the same for admin role i.e;admins and could get the lastlogon for all the admins including who has no recored yet in signins.
$AllSiginLogs = Get-AzureADAuditSignInLogs -All $true
$role = Get-AzureADDirectoryRole | Where-Object {$_.displayName -eq 'Global Administrator'}
$admins = #(Get-AzureADDirectoryRoleMember -ObjectId $role.ObjectId | select DisplayName, UserPrincipalName)
$results = #()
Foreach ($admin in $admins){
$LoginRecord = $AllSiginLogs | Where-Object{ $_.UserId -eq $admin.ObjectId } | Sort-Object CreatedDateTime -Descending
if($LoginRecord.Count -gt 0){
$lastLogin = $LoginRecord[0].CreatedDateTime
}else{
$lastLogin = 'no login record'
}
$item = #{
userUPN=$admin.UserPrincipalName
userDisplayName = $admin.DisplayName
lastLogin = $lastLogin
accountEnabled = $admin.AccountEnabled
}
$results += New-Object PSObject -Property $item
Write-Output $results
}
#$results | export-csv -Path d:\result.csv -NoTypeInformation
Result:
Reference:
userlastlogon-export
thanks #kavyasaraboju-MT
Your hint helped me a lot, based on it, i modified my code which gets what i want
$role = Get-AzureADDirectoryRole | Where-Object {$_.displayName -eq 'Global Administrator'}
$admins = #(Get-AzureADDirectoryRoleMember -ObjectId $role.ObjectId | select DisplayName, UserPrincipalName)
$results = #()
Foreach ($admin in $admins){
$upn = $admin.UserPrincipalName
$LoginRecord = Get-AzureADAuditSignInLogs -Filter "UserPrincipalName eq '$upn'" -Top 1
Start-Sleep -Seconds 2
if($LoginRecord.Count -gt 0){
$lastLogin = $LoginRecord.CreatedDateTime
}
else{
$lastLogin = 'no login record'
}
$item = #{
userUPN=$admin.UserPrincipalName
userDisplayName = $admin.DisplayName
lastLogin = $lastLogin
}
$results += New-Object PSObject -Property $item
}
$results | export-csv -Path c:\result.csv -NoTypeInformation -Encoding UTF8

Add exceptions for file paths from azure defender to adaptive application security controls

I have a bunch of machines being monitored by adaptive application security controls that are giving warnings because the training process was not ran long enough to recognize benign executables. What's an easy way to add exceptions for the executables in active alerts to the adaptive security groups?
There's already an existing recommendation that might provide what you are trying to do:
https://learn.microsoft.com/en-us/azure/defender-for-cloud/adaptive-application-controls#respond-to-the-allowlist-rules-in-your-adaptive-application-control-policy-should-be-updated-recommendation
This script grabs the active alerts from defender, and updates the groups.
The alerts must still be dismissed manually.
function Get-ExistingRules {
Param(
$subscriptionId,
$groupName
)
$url = "https://management.azure.com/subscriptions/$subscriptionId/providers/Microsoft.Security/locations/centralus/applicationWhitelistings/${groupName}?api-version=2015-06-01-preview";
return az rest `
--method get `
--url $url `
| ConvertFrom-Json;
}
function Add-NewRules {
Param(
$subscriptionId,
$groupName,
$files
)
$url = "https://management.azure.com/subscriptions/$subscriptionId/providers/Microsoft.Security/locations/centralus/applicationWhitelistings/${groupName}?api-version=2015-06-01-preview";
$existing = Get-ExistingRules $subscriptionId $groupName;
$existing | ConvertTo-Json -Depth 100 > asd.json;
$myList = $existing.properties.pathRecommendations;
foreach ($file in $files) {
$myList += [pscustomobject]#{
path = $file.path
type = "File"
common = $true
action = "Add"
usernames = #(
[pscustomobject]#{
username = "Everyone"
recommendationAction = "Recommended"
}
)
userSids = #(
"S-1-1-0"
)
fileType = $file.type
configurationStatus = "NotConfigured"
};
}
$existing.properties.pathRecommendations = $myList;
$existing.properties = [pscustomobject]#{
protectionMode = $existing.properties.protectionMode
vmRecommendations = $existing.properties.vmRecommendations
pathRecommendations = $existing.properties.pathRecommendations
}
$existing.PSObject.properties.remove("location");
# return $existing;
$body = $existing | ConvertTo-Json -Depth 20 -Compress;
$body > temp.json;
# $body = $body -replace "`"", "\`"";
# return az rest `
# --method PUT `
# --url $url `
# --body $body `
# | ConvertFrom-Json;
# avoid max command length limit by storing body in a file
try {
return az rest `
--method PUT `
--url $url `
--body `#temp.json `
| ConvertFrom-Json;
}
catch {
Write-Warning "Encountered error adding rule";
Write-Warning "$_";
}
return $null;
}
function Format-Body {
param(
$obj
)
$body = $obj | ConvertTo-Json -Depth 100 -Compress;
$body = $body -replace "`"", "\`"";
$body = $body -replace "`r", "";
return $body;
}
Write-Host "Listing subscriptions";
# you can filter to just one subscription if you want
# $subscriptions = az account list --query "[?name=='NPRD'].id" --output tsv;
$subscriptions = az account list --query "[].id" --output tsv;
$allAlerts = New-Object System.Collections.ArrayList;
$i = 0;
foreach ($sub in $subscriptions) {
Write-Progress -Id 0 -Activity "Fetching alerts" -Status $sub -PercentComplete ($i / $subscriptions.Count * 100);
$i = $i++;
$alerts = az security alert list `
--subscription $sub `
| ConvertFrom-Json `
| Where-Object { #("VM_AdaptiveApplicationControlLinuxViolationAudited", "VM_AdaptiveApplicationControlWindowsViolationAudited") -contains $_.alertType } `
| Where-Object { $_.status -eq "Active" };
foreach ($x in $alerts) {
$allAlerts.Add($x) > $null;
}
}
Write-Progress -Id 0 "Done" -Completed;
function Get-Files {
Param(
$alert
)
if ($alert.alertType -eq "VM_AdaptiveApplicationControlLinuxViolationAudited") {
$fileType = "executable";
}
else {
$fileType = "exe";
}
$pattern = "Path: (.*?);";
$str = $alert.extendedProperties.file;
return $str `
| Select-String -Pattern $pattern -AllMatches `
| ForEach-Object { $_.Matches } `
| ForEach-Object { $_.Value } `
| ForEach-Object { [pscustomobject]#{
path = $_
type = $fileType
}};
}
$alertGroups = $allAlerts | Select-Object *, #{Name = "groupName"; Expression = { $_.extendedProperties.groupName } } | Group-Object groupName;
foreach ($group in $alertGroups) {
$groupName = $group.Name;
$group.Group[0].id -match "/subscriptions/([^/]+)/" > $null;
$subscriptionId = $matches[1];
$files = $group.Group | ForEach-Object { Get-Files $_ };
Write-Host "Adding file path rule sub=$subscriptionId group=$groupName count=$($files.Count)";
Add-NewRules $subscriptionId $groupName $files;
}

deploy Lab with windows image with azure Labservices

I try to create a lab Windows 10 or Windows Server in a lab account with PowerShell but he doesn't found any image except when I put :
Image = 'Centos-Based ' he creates a lab with centos-based 8.1
my code please :
# Create a Lab with Windows server
$la = Get-AzLabAccount -ResourceGroupName $ResourceGroupName -LabAccountName $LabAccountName
Write-Host "$LabAccountName lab account created or found."
#param (
$LabName = Read-Host ' Name of Your lab '
$Image = Read-Host ' Name of Your lab '
$Size = Read-Host ' Size of Your lab '
$InstallGpuDriverEnabled = $false
$UserName = Read-Host ' UserName of Your lab '
$Password = Read-Host ' Password of Your lab '
$UsageQuotaInHours = 10
$SharedPasswordEnabled = $false
$idleGracePeriod = 15
$idleOsGracePeriod = 0
$idleNoConnectGracePeriod = 15
$TemplateVmState = "Enabled"
#)
$img = $la | Get-AzLabAccountGalleryImage | Where-Object {$_.name -like $Image} | Select-Object -First 1
if(-not $img -or $img.Count -ne 1) {Write-Error "$Image pattern doesn't match just one image."}
Write-Host "Image $Image found."
begin { }
process {
try {
foreach ($la in $LabAccount) {
$labAccountUri = (ConvertToUri -resource $la)
$createUri = $labAccountUri + "/createLab"
$labUri = $labAccountUri + "/labs/" + $LabName
$environmentSettingUri = $labUri + "/environmentsettings/default"
$sharedPassword = if ($SharedPasswordEnabled) { "Enabled" } else { "Disabled" }
$imageType = if ($Image.id -match '/galleryimages/') { 'galleryImageResourceId' } else { 'sharedImageResourceId' }
InvokeRest -Uri $createUri -Method 'Post' -Body (#{
name = $LabName
labParameters = #{
$imageType = $Image.id
password = $Password
username = $UserName
userQuota = "PT$($UsageQuotaInHours.ToString())H"
vmSize = $Size
sharedPasswordState = $sharedPassword
templateVmState = $TemplateVmState
idleShutdownMode = $idleShutdownMode
idleGracePeriod = "PT$($idleGracePeriod.ToString())M"
enableDisconnectOnIdle = $enableDisconnectOnIdle
idleOsGracePeriod = "PT$($idleOsGracePeriod.ToString())M"
enableNoConnectShutdown = $enableNoConnectShutdown
idleNoConnectGracePeriod = "PT$($idleNoConnectGracePeriod.ToString())M"
installGpuDriverEnabled = $gpuDriverState
}
} | ConvertTo-Json) | Out-Null
}
$lab = WaitProvisioning -uri $labUri -delaySec 60 -retryCount 120
WaitProvisioning -uri $environmentSettingUri -delaySec 60 -retryCount 120 | Out-Null
return $lab
}
catch {
Write-Error -ErrorRecord $_ -EA $callerEA
}
}
end { }
$lab = $la | New-AzLab -LabName $LabName -Image $img -Size $size -UserName $userName -Password $password -UsageQuotaInHours $usageQuota | Publish-AzLab
Write-Host "$LabName lab doesn't exist. Created it."
Regarding the issue, please update the expression as Where-Object {$_.name -like "Windows 10*"}.
For exmaple
$la = Get-AzLabAccount -ResourceGroupName $ResourceGroupName -LabAccountName $LabAccountName
$img = $la | Get-AzLabAccountGalleryImage | Where-Object {$_.name -like "Windows 10*"} | Select-Object -First 1

Create a blank object for Test-Connection

I recently answered a SO post about Test-Connection Powershell script: create loop for ResponseTime
When a Test-Connection cannot connect it will return a System.Net.NetworkInformation.PingException which is fine but I would like to record that as an empty object in output instead of skipping over it. I am aware that I could just select the properties I want and just create a custom object to output on the command line. That is how I approached the linked question but I feel I could do better.
My desire is to have output like this
Source Destination IPV4Address IPV6Address Bytes Time(ms)
------ ----------- ----------- ----------- ----- --------
WYVERN localhost 127.0.0.1 ::1 32 0
failed host 169.254.158.1
WYVERN localhost 127.0.0.1 ::1 32 0
The two returns are proper from Test-Connection with a dummy line inserted. It has all the properties of a proper return from Test-Connection but, since it failed, only some of the properties have values. The only approach that I tried to accomplish this was to create another object of a similar type. Note (Test-Connection -Count 1 localhost).GetType().FullName returned System.Management.ManagementObject
$servers = "10.50.10.100","169.254.54.1"
$servers | ForEach-Object{
Test-Connection $_ -Count 1 -ErrorAction SilentlyContinue
If(!$testconnection){
$blank = New-Object -TypeName System.Management.ManagementObject
$blank.Destination = $_
}
}
Test-Connection returns more than just a basic System.Management.ManagementObject. So the problem is that a new-object will not have the same properties and, as a result, $blank.Destination = $_ will fail since "'Destination' cannot be found on this object". I also experimented with Test-Connection -Count 1 127.0.0.1 | gm -MemberType Property to try and create a property collection that I could use to build my blank object but that was not bearing an fruit. Most likely since I am not doing it right.
FYI
I am hoping to apply this logic in other places in my scripts. While test-connection is the cmdlet I am dwelling on in this question I am hunting for a broader solution.
Attempt
I have tried, unsuccessfully, something like this but the object are not being outputted together.
$props = #{}
Test-Connection -Count 1 127.0.0.1 | gm -MemberType Property | %{$props.($_.Name) = ""}
$props.destination = "FailedHostAddress"
New-Object -TypeName PSCustomObject -Property $props
Not sure if this helps or not:
$base = Test-Connection 127.0.0.1 -Count 1
$blank = $base | select *
foreach ($prop in $base.psobject.Properties.Name)
{$blank.$prop = $null}
The select * will keep all of the properties, but convert them to note properties so they will be writeable, and you can set they to whatever you want them to be.
I would probably do something like this:
$servers = '10.50.10.100', '169.254.54.1', 'somehost'
$servers | % {
$dst = $_
try {
Test-Connection $dst -Count 1 -ErrorAction Stop | % {
$props = [ordered]#{
'Source' = $env:COMPUTERNAME
'Destination' = $dst
'IPv4Address' = $_.IPV4Address
'IPv6Address' = $_.IPV6Address
'Available' = $true
}
}
} catch {
try {
$addr = [ipaddress]$dst
$props = [ordered]#{
'Source' = $env:COMPUTERNAME
'Destination' = $dst
'IPv4Address' = $addr.MapToIPv4()
'IPv6Address' = $addr.MapToIPv6()
'Available' = $false
}
} catch {
$props = [ordered]#{
'Source' = $env:COMPUTERNAME
'Destination' = $dst
'IPv4Address' = $null
'IPv6Address' = $null
'Available' = $false
}
}
}
New-Object -Type PSObject -Property $props
}
The [ordered] hashes make the properties appear in the given order.
With PowerShell v3 or newer it can be simplified to this:
$servers | % {
$dst = $_
try {
Test-Connection $dst -Count 1 -ErrorAction Stop | % {
[PSCustomObject]#{
'Source' = $env:COMPUTERNAME
'Destination' = $dst
'IPv4Address' = $_.IPV4Address
'IPv6Address' = $_.IPV6Address
'Available' = $true
}
}
} catch {
try {
$addr = [ipaddress]$dst
[PSCustomObject]#{
'Source' = $env:COMPUTERNAME
'Destination' = $dst
'IPv4Address' = $addr.MapToIPv4()
'IPv6Address' = $addr.MapToIPv6()
'Available' = $false
}
} catch {
[PSCustomObject]#{
'Source' = $env:COMPUTERNAME
'Destination' = $dst
'IPv4Address' = $null
'IPv6Address' = $null
'Available' = $false
}
}
}
}
The output will look somewhat like this:
Source Destination IPv4Address IPv6Address Available
------ ----------- ----------- ----------- ---------
WYVERN 10.50.10.100 10.50.10.100 fe80::3a8f:4854:248d:787f%11 True
WYVERN 169.254.54.1 169.254.54.1 ::ffff:169.254.54.1 False
WYVERN somehost False

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